From 845c953665547497347cea5d7eb9652be22706b6 Mon Sep 17 00:00:00 2001 From: Igor Labutin Date: Sun, 22 Feb 2026 23:16:18 +0300 Subject: [PATCH] transcriptions 118..129 and fix of old ones --- .../Radio/Transcriptions/RadioDotNet-105.txt | 1512 +++++++------- .../Radio/Transcriptions/RadioDotNet-118.txt | 523 +++++ .../Radio/Transcriptions/RadioDotNet-119.txt | 707 +++++++ .../Radio/Transcriptions/RadioDotNet-120.txt | 543 +++++ .../Radio/Transcriptions/RadioDotNet-121.txt | 392 ++++ .../Radio/Transcriptions/RadioDotNet-122.txt | 501 +++++ .../Radio/Transcriptions/RadioDotNet-123.txt | 406 ++++ .../Radio/Transcriptions/RadioDotNet-124.txt | 488 +++++ .../Radio/Transcriptions/RadioDotNet-125.txt | 645 ++++++ .../Radio/Transcriptions/RadioDotNet-126.txt | 658 ++++++ .../Radio/Transcriptions/RadioDotNet-127.txt | 581 ++++++ .../Radio/Transcriptions/RadioDotNet-128.txt | 472 +++++ .../Radio/Transcriptions/RadioDotNet-129.txt | 539 +++++ input/Radio/Transcriptions/RadioDotNet-61.txt | 1787 ++++++++-------- input/Radio/Transcriptions/RadioDotNet-62.txt | 1671 ++++++++------- input/Radio/Transcriptions/RadioDotNet-63.txt | 1537 +++++++------- input/Radio/Transcriptions/RadioDotNet-87.txt | 1851 ++++++++--------- input/Radio/Transcriptions/RadioDotNet-88.txt | 1632 +++++++-------- input/Radio/Transcriptions/RadioDotNet-96.txt | 1386 ++++++------ 19 files changed, 12134 insertions(+), 5697 deletions(-) create mode 100644 input/Radio/Transcriptions/RadioDotNet-118.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-119.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-120.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-121.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-122.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-123.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-124.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-125.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-126.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-127.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-128.txt create mode 100644 input/Radio/Transcriptions/RadioDotNet-129.txt diff --git a/input/Radio/Transcriptions/RadioDotNet-105.txt b/input/Radio/Transcriptions/RadioDotNet-105.txt index 0bbe2c9..b70b72c 100644 --- a/input/Radio/Transcriptions/RadioDotNet-105.txt +++ b/input/Radio/Transcriptions/RadioDotNet-105.txt @@ -1,756 +1,756 @@ -0.00 11.64 SPEAKER_01 Здравствуйте, уважаемые слушатели, в эфире Радио.нет и выпуск номер 105. -11.64 15.08 SPEAKER_01 В студии, как всегда, постоянные ведущие – Анатолий Кулаков. -15.08 16.20 SPEAKER_00 И Игорь Лабутин. -16.20 17.20 SPEAKER_01 Всем привет! -17.20 36.76 SPEAKER_01 За нашими спинами гордые банда наших помогаторов, а именно… Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Павел, Лазарев Илья, Шевченко Антон, Ольга Бонаренко, Сергей Краснов, Константин Ушаков, Андрей Фазлеев, Дмитрий Павлов, Постарнаков Андрей, Дмитрий Сорокин и Александр Ерыгин. -36.76 39.24 SPEAKER_01 Спасибо, друзья, а также всем, кто нас поддерживает. -39.24 45.08 SPEAKER_01 Очень приятно иметь такую шикарную поддержку нашего творчества. -45.08 52.80 SPEAKER_01 Ну что ж, прошлый выпуск у нас получился какой-то аномально огромный, постараемся больше так сильно не напрягать наших слушателей. -52.80 54.36 SPEAKER_01 Постоянно жалуются на какие-то большие выпуски. -54.36 57.20 SPEAKER_01 Сегодня попробуем пробежаться быстренько по темам. -57.20 62.84 SPEAKER_00 Да, компенсируем, сделаем сегодня маленький коротенький выпуск, но это мы сейчас вначале так говорим, посмотрим, что будет к концу. -62.84 73.56 SPEAKER_00 Давай-давай, пойдем, у нас новостей особо нет, ну в смысле, у Майкрософта, понятное дело, релиз вышел, новых релизов пока не было, поэтому пойдем по разным статьям. -73.56 81.24 SPEAKER_01 Ну да, пока Майкрософт отдыхает, он в принципе наплодил очень много интересных фич, которые вполне могут обсуждать и другие авторы. -81.24 94.08 SPEAKER_01 И вот другие авторы решили взяться за обсуждение транзакций, даже не транзакций, локов, для обсуждения локов, реализованных в Entity Framework, поэтому есть прекрасная статейка, которую мы с вами сегодня затронем. -94.08 116.20 SPEAKER_01 Статейка называется "Оптимистик лок против пессимистик лок ин дотнет", в общем под названием все звучит довольно широко и оптимистично, но на самом деле кейс получился довольно-таки узкий, ну и посмотрим по дороге тогда, не хочу сейчас рассусоливать, пойдемте посмотрим что такое оптимистик и пессимистик лок в разрезе Entity Framework в нашем случае. -116.20 119.32 SPEAKER_01 Итак, откуда вообще пошла проблема? -119.32 160.44 SPEAKER_01 Ну как известно, не было бы никаких проблем с параллелизмом, конкуренцией, если бы у нас был всегда один поток и мы бы работали всегда в одном workflow данных, то есть раньше, наверное, когда-то так даже и было, у нас была какая-то база данных, приложение в нее писало, приложение в нее читало и все в принципе было хорошо, но потом кто-то придумал многопоточность и мы пошли писать в эту базу данных из нескольких потоков и уже база данных стала как-то немножко поднапряжней, потом кто-то придумал сервер клиент приложения и в сервер пошли писать не просто многопотоков, а еще много клиентов в многопотоков и база данных вообще могла становиться очень-очень плохо. -160.44 181.44 SPEAKER_01 А база данных, как известно, это центр обычно самых главных, то есть главный источник всех данных, которые есть в приложении, в большинстве случаев это так и поэтому хочется, чтобы данные там всегда оставались консистентными и непротиворечимыми, поэтому необходимо было каким-то образом, какими-то механизмами обеспечивать непротиворечивость данных. -181.44 215.30 SPEAKER_01 Противоречивость могла возникнуть, когда, опять же, несколько потоков или несколько клиентов начинают писать одни и те же данные, вот представьте у вас есть какая-то один бакет или одна строчка в таблице и один клиент пишет туда статус номер один, а второй пишет статус номер два, нечто же произойдет, а неизвестно что произойдет, в зависимости от реализации, иногда данные покарабкаться, иногда выиграет последний, а данные предыдущего клиента потеряются, в общем, может быть все что угодно, поэтому придумали механизмы борьбы с конкарнси, которые позволяют вот эту самую консистентность обеспечить. -215.30 224.50 SPEAKER_01 Итак, автор утверждает, что у нас есть только два способа борьбы с конкарнси, это pessimistic log и optimistic log. -224.50 257.54 SPEAKER_01 Ну, естественно, на самом деле это не так, существует огромное подможество алгоритмов, которые помогают писать одновременно в одну и ту же область данных, то есть какую-то конкарнси делать, или структур или еще чего-то, например там multiversion concurrency control, который используется в постгре, или conflict-free replicated data types, более известный как CRDT, в общем, много способов существует, кроме локов для того, чтобы работать с параллельным потоком данных, с конкурентным потоком данных. -257.54 269.50 SPEAKER_01 Но локи действительно это самый, наверное, узнаваемый, примитивный и максимально используемый подход, максимально используемый механизм, поэтому как раз сосредоточимся на локах. -269.50 282.58 SPEAKER_01 Итак, все примеры будут запускаться на Entity Framework, под капотом будет SQL-сервер, но в принципе это не особо важно, потому что Entity Framework обеспечивает довольно хороший такой уровень абстракции, под который вы можете зарядить любую базу данных. -282.58 285.70 SPEAKER_01 В данном случае, конечно же, про реалиционно идет речь. -285.70 289.94 SPEAKER_01 Итак, разберемся для начала с pessimistic lock. -289.94 296.90 SPEAKER_01 Pessimistic lock - это когда несколько процессов пытаются модифицировать один и тот же ресурс параллельно. -296.90 301.34 SPEAKER_01 Pessimistic lock решает эту проблему с помощью эксклюзивного доступа. -301.34 323.30 SPEAKER_01 То есть он позволяет взять лок на этом ресурсе какому-то одному процессу, который пришел к нему первым, и до тех пор, пока этот лок не будет отпущен первым процессом, все остальные процессы, которые придут с претензией на взятие этого ресурса, они будут ждать в очереди и ждать, пока лок отпустится. -323.30 332.86 SPEAKER_01 Как только лок отпускается первым клиентом, второй клиент берет этот лок, заходит, начинает модифицировать и все остальные ждут, пока он отпустится. -332.86 339.46 SPEAKER_01 То есть, по сути, мы выстраиваем все наши параллельные процессы, все наши параллельные изменения в такую своеобразную очередь. -339.46 347.18 SPEAKER_01 Но у этого подхода, кажется, все хорошо, выстроили в очередь, все стоят, все ждут своей очереди, по одному меняют. -347.18 350.78 SPEAKER_01 В принципе, плюсы тут очевидны, но у этого подхода есть и минусы. -350.78 355.70 SPEAKER_01 Во-первых, как только мы их начинаем выстраивать в очередь, то у нас появляется ожидание. -355.70 357.66 SPEAKER_01 Таким образом, появляется замедление. -357.66 372.50 SPEAKER_01 То есть программы, которые используют pessimistic lock, они обычно, у них обычно вот это место, где сосредоточен сам лок, является bottleneck, то есть они в этом месте начинают медленнее работать, потому что ждут, пока другие потоки освободят им занятый ресурс. -372.50 375.42 SPEAKER_01 Другая распространенная проблема с этим алгоритмом - это deadlock. -375.42 389.74 SPEAKER_01 Если вам нужно взять несколько локов на различные записи, то тут очень важно соблюдать правильный порядок, иначе можно взять локи в таком порядке, что первый и второй клиент никогда друг друга не дождутся, то есть никогда ресурс не освободят. -389.74 397.98 SPEAKER_01 Таким образом, мы получаем, что в принципе алгоритм рабочий, но у него есть какие-то понятные минусы. -397.98 399.90 SPEAKER_01 Как его реализовать в Entity Framework? -399.90 401.70 SPEAKER_01 На самом деле, достаточно просто. -401.70 420.58 SPEAKER_01 Этот подход авторы предлагают реализовать с помощью serializable isolation level в Entity Framework, то есть мы открываем транзакцию с этим уровнем доступа, запрашиваем компонент из базы данных, изменяем каким-то образом его поля, сохраняем все изменения, коммитим транзакцию, и в принципе все хорошо. -420.58 431.22 SPEAKER_01 Если вдруг в этот момент пришел какой-нибудь параллельный поток, который пытается проделать все то же самое, у него выкинется exception соответствующий. -431.22 453.82 SPEAKER_01 Таким образом, мы под этим уровнем транзакции можем модифицировать данные в гарантии того, что никакой другой поток, никакой другой клиент не промодифицирует те же самые куски вместе с нами, те же самые таблицы вместе с нами, и таким образом получим своеобразный пессимистик лог. -453.82 461.42 SPEAKER_01 Но здесь есть небольшие, я бы даже сказал, большие проблемы, минусы у этого уровня. -461.42 470.22 SPEAKER_01 Во-первых, serializable уровень может заблокировать больше записей, чем мы его попросили. -470.22 477.44 SPEAKER_01 Это связано с низкоуровневой реализацией того, как база данных хранит свои записи и каким образом она ставит локи. -477.44 488.54 SPEAKER_01 Также он приводит к уменьшению производительности, потому что приходится брать дополнительные какие-то расходы на поддержку такого высокого, самого мощного уровня сериализации. -488.54 494.22 SPEAKER_01 И он одновременно уменьшает риск дедлоков. -494.22 499.08 SPEAKER_01 В принципе, дедлоков тут может быть как-то немножко поменьше. -499.08 506.64 SPEAKER_01 Данный уровень также предусматривает ручную обработку всяких эксепшенов, которые при этом могут вывалиться. -506.64 516.56 SPEAKER_01 Потому что как только к вам придет второй поток, который начнет модифицировать те же самые данные, которые сейчас находятся под транзакцией, то обычно база данных выкидывает исключения. -516.56 525.48 SPEAKER_01 Поэтому каждый кусок кода, который хочет использовать данный уровень транзакции, он обязан уметь обрабатывать соответствующие исключения. -525.48 529.10 SPEAKER_01 И на это исключение обычно делается какой-то повтор. -529.10 531.48 SPEAKER_01 Но при этом код довольно сильно усложняется, понимаете? -531.48 539.36 SPEAKER_01 Потому что каждая модификация обрастает какими-то непонятными эксепшен, хендлерами, какими-то повторами, какими-то ретрайвами, еще чем-то. -539.36 545.32 SPEAKER_01 В общем, код превращается в довольно-таки сложный для поддержки, для чтения. -545.32 552.08 SPEAKER_01 Но на самом деле кажется, что авторы реализуют вот этот pessimistic log как-то довольно странно. -552.08 565.52 SPEAKER_01 Ну потому что про их же определение pessimistic лока параллельный поток, который пришел модифицировать ожиданные, должен ожидать, пока первый закончит, а потом выстроится в очередь, а потом начать что-то свое писать. -565.52 572.96 SPEAKER_01 Если мы используем уровень serializable у транзакции, то она вам выбросит исключения, никакого ожидания не будет. -572.96 581.32 SPEAKER_01 И обязанность на том, чтобы подождать и снова попытаться, уже стоит на вашем приложении, что не так уж удобно, как обычный, например, pessimistic log. -581.32 585.16 SPEAKER_01 Как бы вы могли в голове себе представить пессимистичный лог? -585.16 597.00 SPEAKER_01 Это то, что каждый из вас, наверное, ощущает, когда вызывает стандартный кейворд в C# - log, ставит этот лог на какой-то ресурс, пишет безопасный код внутри и закрывает скоб. -597.00 598.00 SPEAKER_01 Все. -598.00 601.20 SPEAKER_01 Он гарантирует, что никто туда больше никогда не войдет. -601.20 609.88 SPEAKER_01 Поэтому здесь нет никаких исключений, здесь нет никакой заботы о каких-то там параллельных вхождениях, еще чего-то. -609.88 612.84 SPEAKER_01 В общем случае, мы просто ставим лог и забываем о всех проблемах. -612.84 614.52 SPEAKER_01 Вот хотелось бы чего-то именно такого. -614.52 615.52 SPEAKER_01 Здесь же нет. -615.52 626.04 SPEAKER_01 Здесь какие-то появляются эксепшены, ретраи, не забыть взять, не забыть отпустить, не забыть, что может быть залочатся какие-то другие записи, которые вы не ожидаете лочить. -626.04 630.44 SPEAKER_01 В общем, как-то слишком сложное решение. -630.44 635.32 SPEAKER_01 Можно было бы предложить более похожее что-то на то, что мы хотим. -635.32 636.60 SPEAKER_01 Это, например, advisory log. -636.60 644.12 SPEAKER_01 В PostgreSQL есть такая штука как advisory log, который в принципе очень сильно похож на тот лог, который есть в C#. -644.12 647.56 SPEAKER_01 Можно его взять, можно его отпустить, это буквально одна операция. -647.56 653.20 SPEAKER_01 Естественно, она не поддерживается Entity Framework, поэтому вам ее нужно как-то реализовать кастомно, но реализуется она довольно просто. -653.20 657.48 SPEAKER_01 И в интернете полно уже схем, как это сделать. -657.48 660.64 SPEAKER_01 Другой подход - это, например, можно сделать select for update. -660.64 669.44 SPEAKER_01 Если вам нужен какой-то пессимистичный лог в рамках довольно понятного и ограниченного количества данных, то может быть select for update вам подойдет еще даже больше. -669.44 674.68 SPEAKER_01 Можно еще сделать пессимистичный лог с помощью ручной таблицы. -674.68 677.64 SPEAKER_01 То есть у вас есть таблица, в которой вы записываете логи. -677.64 685.36 SPEAKER_01 И когда вы берете лог, вы в этой таблице делаете update и говорите, что я вот такой вот обработчик, такой вот хендлер взял лог. -685.36 690.84 SPEAKER_01 И все другие клиенты, которые к вам приходят, они должны сначала update в этой таблице смочь сделать. -690.84 692.64 SPEAKER_01 Если не могут сделать, значит ждут. -692.64 696.08 SPEAKER_01 Если могут, значит запись свободна и пошли дальше модифицировать. -696.08 697.32 SPEAKER_01 Такие тоже вещи существуют. -697.32 701.36 SPEAKER_01 В общем, способов сделать пессимистичный лог их довольно таки много. -701.36 706.20 SPEAKER_01 И serializable isolation level, наверное, не самый первый, который мне пришел бы в голову. -706.20 708.46 SPEAKER_01 В общем, непонятно, почему авторы сюда полезли. -708.46 710.32 SPEAKER_01 Но, в общем, это так. -710.32 713.56 SPEAKER_01 Итак, с пессимистичным логом мы разобрались. -713.56 719.40 SPEAKER_01 То есть это лог, который сначала ставится на ресурс, потом ресурс модифицируется и после этого лог отпускается. -719.40 723.76 SPEAKER_01 Его проблемы как раз таки в основном в том, что он оказывается bottleneck. -723.76 728.56 SPEAKER_01 То есть пока ресурс модифицируется, то есть под логом может быть не только модификация ресурсов. -728.56 734.16 SPEAKER_01 Например, сама модификация ресурсов довольно таки может быть и быстрой, но обычно под лог засовывают чего-то еще. -734.16 740.88 SPEAKER_01 Ну, например, загрузить данные, проверить эти данные, проанализировать, что это те данные, которые нам нужны. -740.88 750.40 SPEAKER_01 Взять новый модификатор, заапдейтить данные, потом может быть запустить какой-то верификатор, потом может еще что-то сделать. -750.40 754.76 SPEAKER_01 В общем, и вот эти дополнительные накладные расходы, на которых в принципе лог-то на самом деле и не нужен был. -754.76 756.48 SPEAKER_01 Лог нужен был только на сам апдейт записи. -756.48 762.64 SPEAKER_01 И вот они приводят к вот этим дополнительным расходам, которые возникают при пессимистичных логах. -762.64 765.64 SPEAKER_01 Этих минусов более-менее лишен оптимистичный лог. -765.64 771.40 SPEAKER_01 Вместо того, чтобы брать лог на ресурс, пессимистичный лог делает другую штуку. -771.40 779.76 SPEAKER_01 Он во время сохранения самой записи определяет, а была ли версия записи, которую мы сохраняем, точно такая же, которая лежит в базе данных. -779.76 787.48 SPEAKER_01 Ну то есть, по факту, не успел ли кто-то другой модифицировать ее, пока мы что-то там, какую-то магию с ней творили, каким-то образом ее изменяли. -787.48 798.36 SPEAKER_01 И если вдруг система детектирует, что да, запись в этот момент поменялась, она только в этот момент выбрасывает исключение, что типа, чувак, давай сделать что-нибудь другое, твоя запись была изменена. -798.36 811.20 SPEAKER_01 Но если никаких конфликтов других не было, ну то есть параллельно никто эту запись изменить не смог, то транзакция проходит практически с той же скоростью, с теми же накладными расходами, которые были бы и абсолютно без нее. -811.20 813.24 SPEAKER_01 Это безусловный плюс оптимистик логов. -813.24 816.16 SPEAKER_01 Теперь давайте же разберемся, каким образом их реализовать в Entity Framework. -816.16 820.36 SPEAKER_01 Во-первых, нам понадобится дополнительная колонка, которая обозначает версию. -820.36 831.08 SPEAKER_01 Глядя на эту колонку, Entity Framework будет сам трекать то, какой версии данные были закружены, то, какой версии данные сейчас сохраняются в базу данных и сам будет каким-то образом на это реагировать. -831.08 836.84 SPEAKER_01 То есть с каждой записью, которую вы считаете с базы данных, он плюс считает вот эту колонку с версией. -836.84 846.92 SPEAKER_01 Для того, чтобы это сделать, вам необходимо в вашу модельку добавить новое полик, который называется, допустим, Raw Virgin, и навесить на него специальный Entity Framework атрибут, который называется Timestamp. -846.92 857.88 SPEAKER_01 Это специальный атрибут, который рассказывает Entity Framework как раз таки, что и нужно включить автоматическую обработку concurrency-чеков, и она начинает автоматически это делать. -857.88 863.28 SPEAKER_01 Безусловно, можно это сделать не с помощью Attribute, а с помощью Fluent API, но смысл остается тот же самый. -863.28 867.52 SPEAKER_01 Что произойдет, например, если вдруг у вас выполняется метод. -867.52 868.52 SPEAKER_01 Как вы можете это симулировать? -868.52 878.88 SPEAKER_01 Например, перед изменением своей записи, вы сначала запись загружаете в память, в это время загружается, естественно, вместе с вашей Entity и версия. -878.88 886.36 SPEAKER_01 Затем можно выполнить сырой запрос, для того, чтобы Entity Framework его не заметил, который обновляет эти данные, которые хранятся в вашей базе данных. -886.36 892.16 SPEAKER_01 После этого вы меняете у своей Entity необходимые вам поля и пытаетесь сохранить. -892.16 906.00 SPEAKER_01 В данный момент вы получите db_update_concurrency_exception, Entity Framework сам узнает, то есть определит вот этот конфликт, что у вас теперь raw_version поменялось, и выбросит вам exception. -906.00 909.60 SPEAKER_01 В этот момент вы должны подумать, что с этим exception вам делать. -909.60 911.68 SPEAKER_01 В большинстве случаев вы хотите просто-напросто заретраиться. -911.68 929.16 SPEAKER_01 Если же вы хотите не такой большой магии по контролированию вот этого поля version, то есть у нас Entity Framework сам его загружает, сам его при сохранении проверяет, сам его инкрементирует, если уже не было конфликтов, в общем, это он делает все сам. -929.16 939.44 SPEAKER_01 Если вы хотите более ручное управление, более гибкое управление, то существует небольшая альтернатива нашему таймстэмпу, который называется Concurrency Check. -939.44 947.88 SPEAKER_01 Этот атрибут точно также нужно нацепить над каким-нибудь новым полем типа version и можете дальше использовать его абсолютно так же, как и при ведущем варианте. -947.88 952.00 SPEAKER_01 С одним единственным исключением, Entity Framework не будет вам это поле автоматически инкрементировать. -952.00 959.20 SPEAKER_01 Если вы хотите сказать, сообщить, что версия вашей Entity поменялась, значит, вы должны это сказать вручную, сообщить вручную. -959.20 965.44 SPEAKER_01 И если вдруг он обнаружит конфликт, то у вас будет точно такой же db.concurrency.exception. -965.44 975.88 SPEAKER_01 Нужно сказать, что при этом, если у вас включены логики Entity Framework, то там подробно будет описано, какой SQL-запрос это преобразуется, какой конфликт был вызван, почему был вызван. -975.88 983.12 SPEAKER_01 Поэтому в логах много всего пишется, если вы хотите, то отладку обязательно включите для того, чтобы посмотреть, что там, собственно, происходит под капотом. -983.12 984.96 SPEAKER_01 Вот таких есть два подхода. -984.96 1000.08 SPEAKER_01 Опять же, к optimistic log у меня тоже есть большие вопросы, потому что реализация, то есть мы никак не можем работать с optimistic логом, кроме эксцепшенов в Entity Framework. -1000.08 1001.08 SPEAKER_01 И это довольно-таки плохо. -1001.08 1009.72 SPEAKER_01 Потому что любой человек, который хоть раз в жизни в SQL реализовал optimistic логи на чистом SQL, он, естественно, никакие эксцепшены не бросает и ничего не делает. -1009.72 1011.88 SPEAKER_01 Как реализуется нормальный optimistic лог? -1011.88 1017.76 SPEAKER_01 Вы обновляете запись и в апдейте пишите условие vaversion = 1. -1017.76 1028.76 SPEAKER_01 Таким образом, когда вы обновляете эту запись и запись в базе данных находится под версией 1, у вас количество измененных элементов будет 1. -1028.76 1036.76 SPEAKER_01 Если же вы обновляете запись и в это время уже параллельный поток какой-то увеличил эту версию, то количество измененных элементов будет 0. -1036.76 1046.64 SPEAKER_01 Таким образом, анализируя количество измененных элементов после вот этого апдейта, вы можете определить, была ли успешна ваша optimistic транзакция, даже не транзакция, а апдейт. -1046.64 1047.64 SPEAKER_01 Оптимистик апдейт. -1047.64 1049.40 SPEAKER_01 Был ли он успешен или неуспешен. -1049.40 1056.40 SPEAKER_01 Таким образом, просто-напросто вернув количество измененных записей, можно, анализируя это количество, обойтись без всяких эксцепшенов. -1056.40 1063.24 SPEAKER_01 Можно просто сделать нормальный анализ и немножко сэкономить себе там перформансы и удобства, не используя эксцепшены. -1063.24 1069.72 SPEAKER_01 В Entity Framework такой штуки очень долго не было, потому что как раз-таки не было апдейта с условиями. -1069.72 1080.20 SPEAKER_01 Недавно появился апдейт, в который мы можем вставить where, то есть, по сути, вставить условия, и вы можете сделать свой нормальный оптимистик апдейт теперь без всяких эксцепшенов. -1080.20 1083.92 SPEAKER_01 Почему-то, опять же, в никаких примерах этого не сообщают, не дают. -1083.92 1087.12 SPEAKER_01 И говорят нам, что мы обязаны сидеть на каких-то только db-конкуренции эксцепшенах. -1087.12 1095.72 SPEAKER_01 В общем, если вы не любите эксцепшены, то вот это тоже подход очень хороший, и он работает, и, в принципе, сейчас его в EFI можно легко заиспользовать. -1095.72 1098.40 SPEAKER_01 Ну и так, с чем же мы пришли? -1098.40 1100.88 SPEAKER_01 У нас есть, в принципе, три варианта. -1100.88 1103.04 SPEAKER_01 Один пессимистик и два оптимистик лока. -1103.04 1106.12 SPEAKER_01 Посмотрим же, кто из них лучше и кого нужно использовать. -1106.12 1109.16 SPEAKER_01 Ну, на самом деле, нет однозначного ответа, как всегда. -1109.16 1121.96 SPEAKER_01 Все зависит от вашего способа, от того, насколько часто у вас конфликты, какой у вас большой уровень конкуренции, от перформанса вашего приложения и прочих таких факторов. -1121.96 1130.80 SPEAKER_01 Например, пессимистик лок, наверное, хорош, потому что он может работать без образования конфликтов. -1130.80 1134.16 SPEAKER_01 То есть никаких у вас, по сути, конфликтов в данных не будет. -1134.16 1141.48 SPEAKER_01 Все апдейтеры будут выстраиваться в очередь, а когда есть очередь, писатель получается по факту один, и конфликтов нет. -1141.48 1142.48 SPEAKER_01 Это бесспорный плюс пессимистик локов. -1142.48 1153.60 SPEAKER_01 Также он, если он реализован, допустим, с помощью каких-то механизмов, которые позволяют затронуть вам несколько записей. -1153.60 1161.52 SPEAKER_01 То есть не одну версию в одной сущности вам нужно поменять, а в вашей транзакции, допустим, участвуют несколько таблиц. -1161.52 1164.98 SPEAKER_01 В общем, здесь тоже пессимистик лок, в принципе, довольно хорошо себя показывает. -1164.98 1172.44 SPEAKER_01 Из минусов – это образование bottle neck, то есть то место, где стоит ваша очередь, оно как раз будет тормозить во всем вашем приложении. -1172.44 1175.64 SPEAKER_01 Ну и, возможно, дедлоков, куда же без этого. -1175.64 1180.84 SPEAKER_01 Оптимистик локи в плане минусов намного лучше, потому что у них есть свои проблемы. -1180.84 1188.20 SPEAKER_01 Если брать оптимистик лок, то безусловным его плюсом является в том, что нет никакой блокировки. -1188.20 1194.92 SPEAKER_01 В лучшем случае вы пройдете обновление, даже не заметив его, в худшем случае у вас будет ретрай. -1194.92 1199.32 SPEAKER_01 Поэтому при большой конкурентности данный способ более предпочтителен. -1199.32 1210.60 SPEAKER_01 Если мы берем вариант с raw version, то здесь Entity Framework на себя полностью берет автоверсионирование, то есть слежка за версией, закачивание версии, модификация версии. -1210.60 1213.36 SPEAKER_01 Все это берет на себя Entity Framework, что достаточно таки удобно. -1213.36 1219.72 SPEAKER_01 Из минусов у вас могут возникнуть конфликты, и вам нужно думать, как эти конфликты обработать. -1219.72 1222.72 SPEAKER_01 Не всегда повтор – это самое лучшее решение. -1222.72 1225.36 SPEAKER_01 Тут зависит уже конкретно от вашего кейса. -1225.36 1231.64 SPEAKER_01 И из минусов, если вы неправильно обработаете конфликт, вы можете потерять данные, что тоже в предыдущем случае было бы невозможно. -1231.64 1238.68 SPEAKER_01 Это тоже такой очень большой минус оптимистик лока, которым приходится расплачиваться за производительность. -1238.68 1251.32 SPEAKER_01 И оптимистик лок с concurrency токеном, в принципе, наследует все плюсы оптимистик лока, но плюсы, и также дополнительным плюсом он дает вам более гибкое управление версиями. -1251.32 1266.28 SPEAKER_01 Очень сложно придумать, зачем это могло бы пригодиться на практике, но, наверное, если у вас какая-то изощренная система типа совместного онлайн-редактирования одного документа несколькими пользователями или что-то в этом духе, то, наверное, ручное управление вам зачем-то может быть нужно. -1266.28 1274.32 SPEAKER_01 Ну и из минусов, конфликты вы точно также должны управлять вручную и каким-то образом их разруливать. -1274.32 1297.08 SPEAKER_01 Такой небольшой обзорчик, в принципе, мы так кратко с верхнего уровня познакомились, как это реализовано в Entity Framework и что с этим можно сделать, но, в принципе, держите в уме, что реализации оптимистик и пессимистик лока можно сделать на SQL и на Entity Framework гораздо больше и они будут обладать более такими гибкими и удобными свойствами, чем те, которые представлены в статье. -1297.08 1323.32 SPEAKER_00 Вообще, в общем, полезно изучать те инструменты, с которыми вы работаете, не думать, что Entity Framework все решит за вас, хотя, не знаю, 90%, наверное, проблема, если не 95% для некоторых проектов он решает, но для тех самых оставшихся 5% или 10% нужно действительно хорошо знать, за какими инструментами пойти в базу быть той адвайзери локи или еще что-нибудь и в каких ситуациях что нужно применять, а тут… -1323.32 1349.72 SPEAKER_01 Наверное, смотри, этим как раз и отличается хороший программист от плохого, потому что плохой он остановится где-то на уровне Entity Framework и не понимая то, как работает SQL, что там происходит под капотом, он сильно много хорошего сделать не сможет, а хороший программист он всегда понимает на уровень дальше, т.е. он знает, как работает SQL, он знает, что от него ожидать, он знает, каким образом на чистом SQL реализовать те или иные паттерны и тогда он их сможет грамотно использовать в высокоуровневом фреймворке. -1349.72 1367.08 SPEAKER_00 Я тут даже, наверное, сказал не хороший-плохой, а скорее опытный и неопытный, т.е. ты можешь быть хорошим, но пока еще неопытным программистом, но вот когда ты обретешь этот опыт работы напрямую с SQL, понимание, когда какой лок применить, ты хотя бы в этой части становишься уже опытным. -1367.08 1373.16 SPEAKER_01 Согласен, да, но просто тебе нужно хотеть этот опыт обрести, тебе не нужно останавливаться на этом уровне. -1373.16 1374.16 SPEAKER_00 Это правда. -1374.16 1388.00 SPEAKER_00 Ну давайте будем становиться более опытными программистами в разных областях и погрузимся в ту часть, в которую мы на самом деле довольно давно не ныряли, а именно ивенты, ETV, dotnet monitor и вот это вот все. -1388.00 1457.68 SPEAKER_00 Потому что вышла статья Кристофа Назаре, а как вы знаете, эта фамилия обычно ассоциируется со всякими низкоуровневыми штуками, профайлерами, garbage-коллектором и прочим таким интересным контентом, и он не подвел в этот раз, он написал toolzoo, toolzoo называется dotnet.txt, это такой очень кастомный command-line профайлер, который выполняет довольно узкую задачу, а именно он берет ваше приложение и пока оно работает, он логирует на каждый внешний вызов вашего приложения, что произошло, ну в смысле что произошло, на какой уровень мы сходили, какой был код ответа, но это все неинтересно и в общем-то это вы можете узнать какими-то другими способами, а вот что более интересно, это внутрянка дотнета, а именно сколько времени потратилось на DNS, сколько времени потратилось на установление соединений, сколько времени потратилось на любые security штуки, там tls-handshake, либо еще что-то, и возможно сколько времени потратилось на всякие редиректы до тех пор, пока мы собственно не начали качать непосредственно контент того, чего вы там запрашивали, а что-то по клиентам. -1457.68 1473.52 SPEAKER_00 Это может быть полезно для понимания, где ваше приложение тормозит, если, например, вы видите по какой-то статистике, там не знаю, в каких-нибудь графаниях, в каких-нибудь трейсах, что почему-то внешние вызовы выполняются долго, и вам нужно понять, что там происходит более точно. -1473.52 1492.64 SPEAKER_00 Но сама статья, она не про то, зачем вам это может быть надо, а про то, как это реализовать, и это, конечно же, как обычно, для программистов наиболее интересная часть, потому что вот это все, почему там и так далее, это может быть скучновато, а вот как это работает внутри, это может быть интересно, особенно в контексте нашего подкаста, где мы в том числе рассказываем, как это все устроено. -1492.64 1503.08 SPEAKER_00 Итак, надо вспомнить, что и Runtime, и BaseClassLibrary, и PCL, они генерят довольно большое количество ивентов. -1503.08 1519.56 SPEAKER_00 Ивенты эти генерятся разными способами, у нас есть механизм ETV, Event Tracing for Windows, у нас есть механизм просто ивентов, которые потом вы можете, они кросс-платформенные, можно словить дотнет-монитором, например, и посмотреть на них. -1519.56 1540.08 SPEAKER_00 И если вы посмотрите в документацию Microsoft, то там будет написано довольно много разных ивентов, в статье у Кристофа приведены эти ссылочки, но там просто написано, что, мол, когда HTTP-реквест начинается, эмитится вот такой-то ивент, а когда HTTP-реквест заканчивается, эмитится вот такой-то ивент, в смысле названия. -1540.08 1558.56 SPEAKER_00 Но, таким образом, вы можете понять, сколько это тот же самый HTTP-реквест длился, но нет никакого описания о какой payload у этих ивентов, и поэтому понять, собственно, что был за URL в этом HTTP-реквесте, это на самом деле требует некоторого исследования. -1558.56 1566.12 SPEAKER_00 Поэтому первая часть — это то, как понять, о какой вообще payload у этих ивентов, ну, благо дотнет у нас сейчас кросс-платформенный, поэтому надо смотреть в код. -1566.12 1585.56 SPEAKER_00 И в коде мы можем заметить, что все классы, ну или по крайней мере те, которые нас сейчас интересуют для той области в сетевом стеке, которые нас сейчас интересуют, для того, чтобы имитить эти ивенты, они все наследуются от класса EventSource и имеют суффикс телеметрии. -1585.56 1587.88 SPEAKER_00 Это очень удобно для поиска. -1587.88 1602.72 SPEAKER_00 Дальше можно убедиться, что, как и положено по документации, все они декорированы атрибутом EventSource, в котором написано то самое имя провайдера, который вы можете найти в документации, и GUID, который нам там может чуть позднее понадобиться. -1602.72 1613.60 SPEAKER_00 Также там есть публичные методы, которые используются для того, чтобы вызывать генерацию этих ивентов, но в публичных методах ничего интересного нет, потому что они делегируют свою работу приватным методом. -1613.60 1633.16 SPEAKER_00 А приватные методы, они делегируют все это в метод writeEvent обычно, который внутри как раз собирает структурку под названием eventData, дополняет ее нужными полями, и после этого вызывает уже writeEventCore, это из базового класса из EventSource, который, собственно, и пишет все, что нужно. -1633.16 1644.96 SPEAKER_00 И вот как раз, если посмотреть в эти writeEvent методы, которые потом вызовут writeEventCore, то можно посмотреть, что же складывается в eventData. -1644.96 1660.40 SPEAKER_00 Кристоф это, соответственно, сделал, для нужных нам ивентов описал в табличках, где нам искать урлы, где нам искать там то, сё, пятое, десятое, поэтому я прям сейчас не буду перечислять, понятное дело, бинарный payload того, как это все там разложено, не так это сейчас принципиально. -1660.40 1683.68 SPEAKER_00 Важно то, что если вам вдруг зачем-то, вы знаете, что о, мою проблему можно решить, посмотрев, возможно, на нужные какие-то ивенты от BCL или Runtime, но вы нигде не можете найти описание, какие же там данные, можно просто посмотреть в код, вот таким способом найти вызовы writeEventCore, найти перед этим, как собирается eventData и узнать, что же там лежит. -1683.68 1698.80 SPEAKER_00 Понятно, что это может быть немножко непереносимо, понятно, что это может меняться с версиями, но в конце концов вы же отложите проблему вашу конкретно на конкретном дотнете, а не пишете универсальный тул для всего, ну и скорее всего, признаться, вряд ли они будут сильно меняться со временем. -1698.80 1708.72 SPEAKER_00 Итак, ну мы поняли, какие ивенты нам нужны, мы примерно поняли, что в них лежит, теперь надо понять, как этим всем работать, профайлер-то надо написать, чтобы он всё это слушал. -1708.72 1728.48 SPEAKER_00 Для этого делаем следующее, у нас есть nuget-пакет, который называется TraceEvent, а также есть еще nuget-пакет Microsoft Diagnostics NetCore Client, который позволяет, там есть класс под названием EventPipeClient, который позволяет подключиться к приложению и послушать все эти ивенты. -1728.48 1736.32 SPEAKER_00 Напомню, что они все через пайпы для кроссплатформенности засылаются в клиента. -1736.32 1767.80 SPEAKER_00 Дальше вы создаете SessionConfiguration, передаете список провайдеров, вызываете CollectTracing метод, он, собственно, стартует трейсинг и возвращает вам некий ридер, но ридер он бинарный, то есть это просто бинарный протокол, вы просто получите бинарный поток данных, который не очень интересно читать, точнее, читать-то может интересно, но неудобно разбирать и работать с ним практически, поэтому для этого вам нужен еще EventPipeEventSource класс, которым передается этот ридер, и оттуда вы уже получаете нормальные объекты. -1767.80 1772.00 SPEAKER_00 Ну как получаете, на них надо подписаться, но сейчас об этом чуть позднее. -1772.00 1780.36 SPEAKER_00 Для того, чтобы создать сессию, вам нужно туда передать список провайдеров, значит, что такое провайдеры? -1780.36 1797.16 SPEAKER_00 Провайдеры - это те самые имена или гуиды провайдеров, кого вы хотите слушать, потому что можно, конечно, передать и слушать все, но это будут, ну если не миллионы, то тысячи ивентов, и зачем вам это, если вы точно знаете, какие вам нужны? -1797.16 1836.24 SPEAKER_00 Вы вроде выяснили, что нам нужны там провайдеры из namespace.system.net.что-нибудь, ну там DNS, security, там их несколько в статье перечислены, все они будут перечислять, но если их добавить, то вы на самом деле не получите идеальной картинки, потому что вам будут приходить, допустим, HTTP request started, HTTP request stopped, но у нас же приложение многопоточное, как мы говорили при обсуждении прошлой статьи, и много параллельных внешних запросов могут быть, то есть ваши несколько там обработчиков ваших запросов могут одновременно отправлять запросы на внешние сервисы. -1836.24 1849.04 SPEAKER_00 И связать события про то, что request started и request stopped на самом деле не так просто, учитывая то, что у нас весь стэк асинхронный, как правило, это все может приходить из совершенно разных потоков, и как-то это нужно связывать. -1849.04 1856.00 SPEAKER_00 Для того, чтобы это все связывать в event вот этой инфраструктуре, существует понятие activity_id. -1856.00 1865.40 SPEAKER_00 Activity_id это некоторая строчка на самом деле, ну то есть точнее это на самом деле число, но вы можете ее считать строчкой. -1865.40 1869.32 SPEAKER_00 Я, кстати, не помню, как она в апишке выглядит, event source. -1869.32 1875.40 SPEAKER_00 В perfu просто это строчка обычно, ну допустим, в общем, потому что их в дерево можно объединять в итоге, потому что там собирается строка. -1875.40 1887.92 SPEAKER_00 Но по-моему все-таки activity_id это число, которое как раз навешивается при старте и стопе событий, которые связаны друг с другом, и для этого оно прокидывается везде. -1887.92 1900.44 SPEAKER_00 Но вот для того, чтобы оно все работало и все правильно прокидывалось, внезапно нужно еще в провайдере обязательно подписаться на специальный System Tracing Tasks TPL Event Source. -1900.44 1907.84 SPEAKER_00 Вот если вы на него подпишетесь, даже если вы не будете слушать ничего, у вас будет корректный activity_id везде. -1907.84 1909.52 SPEAKER_00 Вот такая вот особенность. -1909.52 1913.40 SPEAKER_00 Видимо считается, что если вам таски не нужны, то и activity_id вам не нужно. -1913.40 1920.44 SPEAKER_00 А так вы получите правильный activity_id из тасочков, из нужного провайдера. -1920.44 1943.20 SPEAKER_00 После того, как вы все это сделаете, дальше вы у этого event source говорите "хочу подписаться", можно подписываться на какие-то суперспецифичные штуки, но как правило проще всего подписаться на событие all_events, просто стандартная синтаксис mc# подписки, там source.all_events+=on_events. -1943.20 1953.32 SPEAKER_00 Внутри on_events вы будете получать событие, когда приходит любой из ивентов из тех провайдеров, на которые вы подписались. -1953.32 1969.12 SPEAKER_00 Но для того, чтобы дальше разобраться, а что это за ивент, потому что там же бинарный payload, и в on_event вам приходят в общем-то только некоторые метаинформации и бинарный payload этого ивента, вам нужно понять откуда этот ивент. -1969.12 1971.48 SPEAKER_00 И вот именно тут пригодятся гуиды. -1971.48 1994.60 SPEAKER_00 Вам нужно для… в классах провайдера вам нужно будет эти самые гуиды сравнивать, то есть вы берете… имени не приходят в ивенте, насколько я помню, приходят только гуиды провайдера, поэтому вы у каждого провайдера, который вы перечислили, спрашиваете гуид и сравниваете его с тем гуидом в ивенте, который пришел. -1994.60 1999.32 SPEAKER_00 И как только вы нашли совпадение, значит это ваш ивент, который вы ждете. -1999.32 2013.72 SPEAKER_00 Точнее, не то, что ваш, вы понимаете, от какого провайдера пришел гуид, вы понимаете какой это ивент, ну потому что ивент-код там есть, и тогда вы можете разобрать наконец-таки payload бинарный, децерализовать его и что-то с ним сделать. -2013.72 2021.16 SPEAKER_00 Например, посчитать те самые дельты по времени, сколько у нас занял DNS-запрос, сколько заняла security, вот это все. -2021.16 2058.92 SPEAKER_00 Такая вот история, то есть если вдруг вы думаете или вы уверены, что вы хотите попробовать какую-то вашу внутреннюю кухню, то есть вы видите какое-то странное поведение и вы по ивентам не хотите лазать по какому-нибудь перфью или еще что-нибудь в таком духе и хотите получить совсем супер детальную диагностику, то вы можете реализовать эту конструкцию, причем в принципе слушать можно же и внутри самого приложения, самого себя, вам никто не мешает прямо внутри приложения встроить такую диагностику самого себя, слушать это все и репортить наружу, например в виде каких-нибудь прометеусовских метрик. -2058.92 2069.88 SPEAKER_00 И тогда будет видно, что например у вас там тормозит, ну допустим, DNS или еще что-нибудь. -2069.88 2090.12 SPEAKER_00 Теперь вот есть такой достаточно понятная, хорошо написанная статья, которая позволит вам легко это сделать либо в своем приложении, либо в стороннем, либо взять просто готовый tool, он инсталится как global tool, как обычно это делается через command line и можно им пользоваться, благо что он command line и поэтому по идее он работает даже внутри контейнера, если очень интересно. -2090.12 2091.12 SPEAKER_00 Такие дела. -2091.12 2105.72 SPEAKER_01 Слушай, полезная штука, мне кажется, что она еще больше станет полезной, если ее включат в какой-нибудь стандартный профайлер, который там все пользуются, и чтобы она показывала вот эти все вещи, которые происходят именно в совокупности с другим вашим приложением. -2105.72 2113.20 SPEAKER_01 Потому что иногда, да, очень часто вот это место может быть bottleneck и не всегда понятно, что же там происходит внутри одного запроса. -2113.20 2135.52 SPEAKER_00 Ну вот я так понимаю, что таких супер детальных метрик можно напридумывать огромное количество, благо этих провайдеров там сотни, как я понимаю, ну ивентов как минимум точно, хотя по-моему провайдеров там за сотню точно, и я боюсь, что если мы начнем это все запихивать в профайлер какой-нибудь, то получится это. -2135.52 2140.96 SPEAKER_00 Ты Perf.U видел, да, скрин такой с миллионом галочек, эдитбоксов и прочего. -2140.96 2143.36 SPEAKER_00 То есть это будет какой-то очень сложный инженерный тул. -2143.36 2153.20 SPEAKER_00 Я не говорю, что они не нужны, и наверное, например, если мы говорим про Perf.U, если вы под виндой, то на Perf.U существует возможность сделать кастом вьюшки так называемые. -2153.20 2163.24 SPEAKER_00 То есть вы можете напрограммировать длл, которую Perf.U будет уметь загружать, скармливать ей, собственно, трейс этих ивентов этой вьюшки, а вьюшка может выводить, что хочет. -2163.24 2166.92 SPEAKER_00 То есть технически можно сделать такую вьюшку даже прям на базе Perf.U. -2166.92 2191.36 SPEAKER_00 Я никогда не пробовал такое делать, но вроде бы видел, что такое делают, вроде там есть какое-то extensibility, и соответственно это можно сделать на Perf.U, но Perf.U довольно ограниченный, в том смысле, что на Windows Only, и видимо поэтому Кристоф решил сделать это в виде такого отдельного онлайн-тула, которое причем на живую, прям на работающем приложении позволяет это делать. -2191.36 2198.60 SPEAKER_01 Ну, ты прав, если там все навалить как в Perf.U, наверное, это будет неюзабельно, в общем случае, по крайней мере. -2198.60 2214.88 SPEAKER_01 Но если сюда подключить какой-нибудь разум, который все-таки будет тебе данные места группировать, и если вдруг они будут выбиваться по статистике из нормального там какого-нибудь распределения, то есть если будет видно, что они занимают существенное время или выполняются дольше, чем обычно, вот тогда их детализировать уметь. -2214.88 2220.12 SPEAKER_01 Ну, без того, чтобы залезть в детали, он бы тебе просто показал как обычные запросы, и все. -2220.12 2234.72 SPEAKER_00 Ну, наверное, может быть, когда-нибудь это в трейсинг куда-нибудь влезет, то есть можно, допустим, будет включить опцию, у нас же сейчас уже спаны для всяких внешних вызовов отправляются нормально через OpenTelemetry, поставить галочку, и он тогда тебе будет это бить на микроспаны. -2234.72 2240.12 SPEAKER_00 Типа вот тут я сходил в DNS, тут я в Security, тут Connection, а тут, значит, вот он ушел, ушел наконец-таки наружу. -2240.12 2242.12 SPEAKER_00 Может быть так. -2242.12 2245.44 SPEAKER_01 Ну, хорошо, хорошо, пойдем к следующей теме. -2245.44 2249.76 SPEAKER_01 Хочется поговорить с вами о том, что не так с Яндекс.Клаудфанкшнами. -2249.76 2252.64 SPEAKER_01 Вот прям нормальная такая статья, прям сразу с наезда. -2252.64 2257.68 SPEAKER_01 Сразу видно, что автор опубликовал статью на Хабре, и это Андрей Порожняков. -2257.68 2272.56 SPEAKER_01 Андрей Порожняков рассказывает нам, как он попробовал Клаудфанкшены, и, в принципе, статья в основном не про Клаудфанкшены, а статья про NativeOut, поэтому если вам интересен NativeOut, а особенно как запустить его в Клаудфанкшенсах, то милости просим. -2272.56 2278.36 SPEAKER_01 Давайте немножко посмотрим на тот опыт, который возник у автора, тем более, что в некоторых местах он довольно-таки уникальный. -2278.36 2286.72 SPEAKER_01 Итак, как я уже сказал, Андрей решил в Клаудфанкшен запустить .NET и посмотреть, а что ж там такого с ними интересного происходит. -2286.72 2289.28 SPEAKER_01 Что такое функции, прежде всего? -2289.28 2298.72 SPEAKER_01 Ну, это функция как услуга, это один из компонентов без серверных вычислений, да, все мы на слуху уже давно имеем у себя Serverless какие-то вычисления, Serverless-функции. -2298.72 2305.12 SPEAKER_01 На самом деле это не тогда, когда у вас нет сервера, это тогда, когда вы просто об этом сервере не заботитесь, а о нем заботится кто-то другой. -2305.12 2314.28 SPEAKER_01 То есть ваша функция лежит на сервере и в этой функции описано на обычном C# коде то, что она должна делать. -2314.28 2316.60 SPEAKER_01 Запускается эта функция по неким событиям. -2316.60 2320.36 SPEAKER_01 Событиями могут быть все, что угодно, то есть очень много разных событий есть. -2320.36 2327.64 SPEAKER_01 Самым частым из них это HTTP-запрос, то есть если на какой-то определенный уровень приходит HTTP-запрос, то запускается ваша функция. -2327.64 2337.24 SPEAKER_01 Безусловно, она может проанализировать какие аргументы перед вашим HTTP-запросом и прочее-прочее, но не сильно отличается от ваших контроллеров, допустим. -2337.24 2341.44 SPEAKER_01 Может быть не такая навороченная, но в целом именно вид именно такой. -2341.44 2350.64 SPEAKER_01 А также событиями могут выступать какой-нибудь планировщик, который по времени запускает эту функцию или появление задачи в очереди задач, в какой-нибудь queue. -2350.64 2356.88 SPEAKER_01 Если задача появилась, то эта задача тоже может обрабатываться с помощью такой же в Cloud Function. -2356.88 2363.64 SPEAKER_01 Плюсы здесь в основном в том, что вам не нужно держать постоянно запущенным какой-то хостинг, какой-то сервер. -2363.64 2375.32 SPEAKER_01 Допустим, вы делаете какое-то маленькое приложение, которому нужно сжимать картинки, и таких картинок у вас там, допустим, раз в неделю вы бы пофотографировали, выложили там 10 картинок в ваш блог и все. -2375.32 2388.84 SPEAKER_01 Для того, чтобы сжать там, допустим, 10 картинок раз в неделю, хостить целый сервер, оставлять его включенным и ждать пока вы к нему пришлете запросы на изменение размеров, это довольно расточительно. -2388.84 2391.12 SPEAKER_01 Тогда вот на помощь приходят такие функции. -2391.12 2397.40 SPEAKER_01 Если к функциям не обращаются, они просто гаснут и вы не платите абсолютно за то время, пока они не используются. -2397.40 2399.48 SPEAKER_01 Ну, по крайней мере, у большинства операторов. -2399.48 2404.56 SPEAKER_01 А вот как только они вам понадобились, вы платите только за те 10 картинок, которые вы сжали. -2404.56 2410.72 SPEAKER_01 Во все остальное время функции, опять же, после сжатия выключаются, лежат и ничего не кушают, времени не требуют, ресурсы не потребляют. -2410.72 2412.04 SPEAKER_01 Что довольно-таки удобно. -2412.04 2421.44 SPEAKER_01 То есть, если у вас есть какие-то небольшие операции, которые случаются редко, то функции это один из хороших выборов, вам его нужно обязательно рассмотреть. -2421.44 2427.56 SPEAKER_01 Такие провайдеры, то есть, такая концепция функций естественно не Яндексом изобретена. -2427.56 2437.48 SPEAKER_01 Есть AWS Lambda, Microsoft Azure Functions, Google Cloud Functions и практически у всего облачного этого провайдера, у любого они есть. -2437.48 2440.00 SPEAKER_01 Но мы сосредоточимся именно на Яндексах. -2440.00 2443.92 SPEAKER_01 У Яндекс фанкшинов поддерживаются различные среды выполнения. -2443.92 2449.64 SPEAKER_01 Нас интересует именно .NET, .NET на данный момент поддерживается восьмой, шестой и триодин. -2449.64 2453.88 SPEAKER_01 В принципе, я думаю, из любых этих вариантов вам обязательно должен подойти. -2453.88 2457.04 SPEAKER_01 Создаются Яндекс.Функции очень просто. -2457.04 2469.16 SPEAKER_01 В удобном интерфейсе вы можете создать файл, и в этом файле вам необходимо будет написать класс, который называется Handler, и у этого класса Handler должна быть функция, которая называется FunctionHandler. -2469.16 2478.72 SPEAKER_01 И в этой уже как FunctionHandler, которая может принимать какие-нибудь аргументы, вы можете творить все, что угодно, например, вернуть строку Hello World. -2478.72 2483.80 SPEAKER_01 Дальше вы на чистом C# можете делать абсолютно любые вещи, которые вам приходят в голову. -2483.80 2488.20 SPEAKER_01 Допустим, посмотрим на то, как же ведет себя вот такой простенький Hello World. -2488.20 2493.92 SPEAKER_01 Если мы его запустим, то предсказуемо он нам ответит той строкой, которую мы в него захардкодили. -2493.92 2495.16 SPEAKER_01 Что здесь можно заметить? -2495.16 2505.84 SPEAKER_01 Если запускать его несколько раз, то время выполнения функции будет меньше при запуске несколько раз подряд одновременно, чем если бы мы запускали его в редких случаях. -2505.84 2509.60 SPEAKER_01 Это как раз демонстрирует тот концепт, который я упомянул выше. -2509.60 2519.40 SPEAKER_01 Если функция не используется, то весь инстанс, все виртуальная машина вашей функции, она гасится и не потребляет никаких ресурсов. -2519.40 2529.12 SPEAKER_01 Как только функцию вы захотели использовать первый раз, снова поднимается эта виртуальная машина, туда загружается ваше приложение, компилируется и начинает работать, то есть начинает выполняться. -2529.12 2544.48 SPEAKER_01 Если вы выполняете ваши запросы очень быстро, то виртуальная машина не гасится, поэтому ваши запросы выполняются быстрее, чем после холодного старта, то есть после вот такого первого запроса на пробуждение. -2544.48 2564.64 SPEAKER_01 Чтобы вы понимали разницу, то уже поднятый, прогретый экземпляр отвечает вам за одну миллисекунду, а вот холодный старт, первый запрос отвечает вам за 150 миллисекунд, то есть естественно в этот ответ входит не только сама работа функции, но и поднятие всей инфраструктуры, всего инвармента для вашей функции. -2564.64 2572.32 SPEAKER_01 Итак, что же входит в этот наш прогретый экземпляр, который может отвечать нам за одну секунду, за одну миллисекунду, извините. -2572.32 2593.08 SPEAKER_01 Естественно за одну миллисекунду ничего там такого быстрого сделать невозможно, то есть невозможно запустить ваше приложение и прогнать JIT и обработать хендлер, поэтому естественно JIT по идее должен был уже отработан, то есть ваше приложение должно уже висеть в памяти, и просто ваш хендлер вызывается несколько раз, при каждом запросе вызывается ваш хендлер. -2593.08 2609.48 SPEAKER_01 Но тут интересно задаться вопросом, а если ваше приложение уже поднято, то это значит, что по сути все данные, которые висят в этом приложении, допустим, которые в статическом контексте у этого приложения хранятся, то все данные они сохраняются. -2609.48 2629.84 SPEAKER_01 То есть любой другой запрос может иметь доступ к данным предыдущего запроса, что немножко противоречит самой концепции функций, потому что функции это по идее такие атомарные единицы работы, которые никаким образом не могут иметь некого непредсказуемого состояния. -2629.84 2641.92 SPEAKER_01 То есть состояние, которое вы явно не сохранили или явно где-нибудь не загрузили, и поэтому они не должны пересекаться, то есть их данные не должны пересекаться с другими параллельными запросами, которые идут к этим же функциям. -2641.92 2643.36 SPEAKER_01 Проведем следующий эксперимент. -2643.36 2652.64 SPEAKER_01 Если мы создадим статическое поле, каунтер, допустим, и начнем в хендлере этот каунтер увеличивать и сделаем несколько запросов подряд. -2652.64 2657.88 SPEAKER_01 Если бы функция была чистая и красивая, то этот каунтер всегда был бы 0. -2657.88 2664.72 SPEAKER_01 Но в нашем случае, когда мы начинаем делать несколько запросов подряд, мы видим, что каунтер увеличивается. -2664.72 2678.40 SPEAKER_01 Каунтер увеличивается, а это значит, что у нас действительно работает одно и то же приложение между разными запросами, и естественно, у этого приложения одни и те же статические свойства, которыми может доступиться абсолютно любой запрос, который придет в этот хендлер. -2678.40 2690.24 SPEAKER_01 Автор сначала подумал, что на самом деле класс хендлер создается каждый раз при входящем запросе, ну как у нас делают контроллеры обычно при входящем запросе, а просто статические свойства, естественно, в приложении никуда не выгружаются. -2690.24 2701.12 SPEAKER_01 Поэтому он убрал статик-модификатор из этого каунтера и вызвал еще несколько запросов, и несколько запросов продолжили увеличить счетчик. -2701.12 2702.36 SPEAKER_01 Что это значит? -2702.36 2710.32 SPEAKER_01 Это значит, что не просто класс хендлер не создается повторно, а класс хендлер используется один и тот же. -2710.32 2717.60 SPEAKER_01 То есть вы можете шарить даже в приватных свойствах класса хендлер, шарить какое-то состояние между запросами. -2717.60 2721.32 SPEAKER_01 То есть класс хендлер будет один и метод будет вызываться много-много раз. -2721.32 2726.64 SPEAKER_01 Это, в принципе, можно рассчитывать как и плюс, и как и минус. -2726.64 2745.88 SPEAKER_01 То есть из плюсов то, что вы в памяти держите какое-то состояние, а минус это в том, что вы на это состояние рассчитывать не можете, потому что как только функция выгрузится из памяти, а сделать она это может абсолютно любую секунду, то вы все это состояние потеряете, и если вы на это вдруг рассчитывали почему-то, то ваши ожидания обломятся. -2745.88 2749.40 SPEAKER_01 Поэтому в идеальной картине мира, естественно, это рассчитывать никогда нельзя. -2749.40 2752.92 SPEAKER_01 Но так как разработчики не идеальны, то просто так запретить нельзя. -2752.92 2756.52 SPEAKER_01 Поэтому хотелось бы, чтобы здесь была какая-то гарантия. -2756.52 2767.36 SPEAKER_01 Иначе на плечи разработчиков ложится такое время, как очищение ресурсов, и оно усугубится, если начнут использоваться ресурсы, например, Unmanaged. -2767.36 2776.96 SPEAKER_01 То есть подключение к базам данных, какие-то сетевые соединения, какое-нибудь сочтение, запись файла, какие-нибудь работы с хендлерами напрямую, в общем, все это очень сложно. -2776.96 2787.88 SPEAKER_01 И намного легче было бы, если бы все-таки вот этого расшаренного стейта не было, если бы весь стейт чистился, как положено в чистых функциях, и весь стейт заново загружался, как положено в чистых функциях. -2787.88 2790.60 SPEAKER_01 Что же мы можем придумать? -2790.60 2802.92 SPEAKER_01 К сожалению, в том конспекте, про который мы говорим сейчас, то есть в environment.net, в environment.cloud.function мы ничего придумать не можем, потому что они именно так работают. -2802.92 2805.40 SPEAKER_01 Они загружают .NET-приложение и просто держат его в памяти. -2805.40 2815.00 SPEAKER_01 Имея такой концепт, у нас руки связаны, мы никак очищать весь стейт не можем, как бы чистить все статические поля, которые существуют в приложении, это просто что-то невероятное. -2815.00 2825.92 SPEAKER_01 Ну и к тому же, там у нас не только статик, там уже у нас есть и какой-нибудь синхронизейшн контекст и какие-то неявные еще переменные, в общем, все не почистишь, так оно не работает. -2825.92 2831.52 SPEAKER_01 Единственный вариант - это гасить приложение полностью и запускать его заново, как только приходит новый год запроса. -2831.52 2834.24 SPEAKER_01 То есть запускать приложение на каждый запрос. -2834.24 2840.32 SPEAKER_01 Звучит якобы безумно, потому что это кажется, что все будет очень долго, но посмотрим, посмотрим. -2840.32 2841.32 SPEAKER_01 Попробуем. -2841.32 2842.56 SPEAKER_01 Запускать приложение на каждый запрос. -2842.56 2846.12 SPEAKER_01 Через .NET Environment яндекс функции мы такое сделать не можем. -2846.12 2850.52 SPEAKER_01 Значит, нам нужен свой Environment чистый и красивый. -2850.52 2857.08 SPEAKER_01 Мы нашли такой Environment с помощью Environment, который называется Bash, то есть запускается который-либо из скриптик. -2857.08 2858.08 SPEAKER_01 Что мы сделали? -2858.08 2861.60 SPEAKER_01 Мы скомпилировали .NET приложение, которое будет у нас вызываться каждый раз. -2861.60 2864.56 SPEAKER_01 Ну и естественно, в будущем мы хотим сделать так, чтобы оно вызывалось быстро. -2864.56 2868.24 SPEAKER_01 Как же нам это сделать быстро? -2868.24 2880.04 SPEAKER_01 Ну, во-первых, нам нужно все это положить в self-content, запустить стриминг и таким образом мы сможем подойти к тому, что сможем использовать native-out публикацию. -2880.04 2890.64 SPEAKER_01 Благодаря native-out публикации у нас весь код компилируется прямо в момент билда вашего приложения, а не в момент запуска, как это происходит обычно при JIT-компиляции. -2890.64 2896.24 SPEAKER_01 Таким образом, в момент именно билда весь ваш код будет преобразован в машинные команды. -2896.24 2906.48 SPEAKER_01 И когда приложение будет запускаться, то на старте не будет тратиться никакое время в JIT. -2906.48 2908.68 SPEAKER_01 Ну, сказано, сделано. -2908.68 2912.36 SPEAKER_01 Взяли баш-среду, написали скриптик, который вызывает наше приложение. -2912.36 2917.92 SPEAKER_01 Наше приложение мы скомпилировали заранее на локальной среде, зная целевую схему. -2917.92 2918.92 SPEAKER_01 Это можно сделать. -2918.92 2925.56 SPEAKER_01 Сохранили в Яндекс.ОбжектСтор и функция наша скачивает из Яндекс.ОбжектСтора приложение и запускает. -2925.56 2929.24 SPEAKER_01 Запускает дотнетное приложение как свое собственное. -2929.24 2945.44 SPEAKER_01 Так как мы использовали базовый образ баш, в нем уже не установлен дотнет-рантайм, именно поэтому нам сюда же подходит и селф-контейнт, потому что селф-контейнт таскает вместе с собой дотнет-окружение вместе с тем экзешником, в который он скомпилирован. -2945.44 2949.32 SPEAKER_01 Ну, и некий вагон, естественно, тоже как наследник от селф-контейнта. -2949.32 2956.68 SPEAKER_01 Поэтому у нас все дотнет-окружение таскается с собой, весь дотнет-код переведен в машинный код, и мы рассчитываем, что это будет работать быстро. -2956.68 2958.64 SPEAKER_01 Давай же посмотрим, как же оно будет работать. -2958.64 2977.36 SPEAKER_01 Вместе с NativeAuto Андрей также притащил обычное селф-контейнт приложение, то есть, у которого есть внутри себя весь полный дотнет-рантайм, у которого отработал тримминг, но не была доделана вот эта фаза компиляции или в нативный код. -2977.36 2978.36 SPEAKER_01 Вот. -2978.36 2979.36 SPEAKER_01 У нас есть три кандидата. -2979.36 2987.84 SPEAKER_01 При холодном старте Яндекс.Функция загружается примерно за 216 миллисекунд и выполняется. -2987.84 3001.28 SPEAKER_01 Селф-контейнт приложение выполняется за 100 миллисекунд, то есть, быстрее, чем Яндекс.Функция, а NativeAuto за 28 миллисекунд, то есть, в 10 раз быстрее холодный старт у приложения на NativeAuto. -3001.28 3010.52 SPEAKER_01 Это как раз-таки показатель того же, что в Яндекс.Дотнет-окружении у нас происходит JIT-компиляция нашего приложения, а в NativeAuto нет. -3010.52 3012.00 SPEAKER_01 Вот как раз выигрыш в 10 раз. -3012.00 3013.00 SPEAKER_01 Неплохо. -3013.00 3017.76 SPEAKER_01 Далее мы пробуем провести тот же самый эксперимент на горячем экземпляре. -3017.76 3022.58 SPEAKER_01 Здесь уже Яндекс.Функция выполняется за 1,2 миллисекунды, то есть, в оптимальное время. -3022.58 3032.60 SPEAKER_01 Селф-контейнт приложения 51 миллисекунда, то есть, здесь уже возможно JIT конкретно вот этого хендлера, который мы выполняем, играет свою роль. -3032.60 3037.04 SPEAKER_01 И NativeAuto 3 миллисекунды, где-то в 2 раза дольше, чем Яндекс.Окружение. -3037.04 3039.08 SPEAKER_01 В принципе, не критично. -3039.08 3042.04 SPEAKER_01 Что отдельно может порадовать, так это используемая память. -3042.04 3045.92 SPEAKER_01 Вот здесь используется 43 мегабайта против яндексовских 87. -3045.92 3050.74 SPEAKER_01 То есть, по памяти NativeAuto ест в 2 раза меньше, что тоже прекрасно. -3050.74 3056.04 SPEAKER_01 Этого автору показалось мало, и он начал унижать Яндекс дальше. -3056.04 3058.60 SPEAKER_01 Каким образом можно унизить Яндекс больше всего? -3058.60 3061.08 SPEAKER_01 Конечно же, заставить его гуглить. -3061.08 3073.64 SPEAKER_01 Поэтому мы взяли наш Hello World приложение, которое в принципе не показывает практически ничего, кроме времени ответа и времени прогрева, и написали более или менее интерпрайс приложения, которое перекладывает JSON. -3073.64 3087.92 SPEAKER_01 Наш Яндекс.Гугл приложение принимает на вход строку, идет в Google Search API, из Search API достает первые 10 результатов и возвращает пользователю заголовки с ссылками. -3087.92 3097.00 SPEAKER_01 То есть, здесь у нас участвует сериализация, децерализация, HTTP подходы, HTTP походы, парсинг входящих параметров, исходящих параметров. -3097.00 3104.28 SPEAKER_01 То есть, идет какая-то нормальная работа, а не сказать, что там какой-нибудь CPU Intensity в большой, но вполне интерпрайс, почему бы и нет. -3104.28 3108.20 SPEAKER_01 И на вот этом интерпрайсе попробуем перемерить наши показатели. -3108.20 3115.96 SPEAKER_01 Естественно, социальный контент нам больше неинтересен, он показывает что-то промежуточное, не то, не сё, а вот Яндекс с NetAuth вполне могут подраться. -3115.96 3120.00 SPEAKER_01 Итак, холодный старт вот этого большого жирного нашего интерпрайса приложения. -3120.00 3130.72 SPEAKER_01 У Яндекса занял больше секунды, NetAuth показал 583 миллисекунды, ну то есть в два раза быстрее, уже не в 10, а в 2, ну допустим. -3130.72 3151.68 SPEAKER_01 И прогретый экземпляр у Яндекса, вызов метода из прогретого экземпляра у Яндекса занял 354 миллисекунды и у NetAuth 486 миллисекунд, ну то есть совсем не сильно он отстал, так буквально процентиков на 30 отстал NetAuth, при этом со стартом в два раза больше. -3151.68 3174.04 SPEAKER_01 Итак, что же мы получаем, если вот кратко смотреть на эти результаты, то Яндекс, среда выполнения Яндекс функций дает лучшее время выполнения для уже разогретых для подготовленных экземпляров, но почему-то все еще больше, чем у NetAuth, но при этом достаточно долго отрабатывает холодные старты. -3174.04 3184.32 SPEAKER_01 У NetAuth лучшее время при холодном старте, прямо значительно лучшее, но почему-то несколько проигрывает в горячем экземпляре, то есть в прогретом, в подготовленном экземпляре. -3184.32 3188.36 SPEAKER_01 И вот здесь, наверное, довольно интересный вопрос, почему проигрывает-то? -3188.36 3202.92 SPEAKER_01 На самом деле, понятно, что JIT на старте не выполняется и понятно, почему оно выигрывает, но если у вас два приложения поднятых, то есть .NET на одно приложение поднято и NetAuth на приложение поднято, то дальше дело техники просто вызвать функцию и все. -3202.92 3212.04 SPEAKER_01 И для того, чтобы устранить некие вопросы, которые у нас возникли во время прочтения данной статьи, мы в эфир позвали ее автора, прямо вот непосредственно Андрея Порожнякова. -3212.04 3213.04 SPEAKER_01 Привет, Андрей! -3213.04 3217.48 SPEAKER_01 Да, всем привет, спасибо, что позвали, я готов дать разъяснения. -3217.48 3228.28 SPEAKER_01 Смотри, хорошая статья, но вот первое, что сразу бросается в глаза, это почему NetAuth все-таки медленнее стандартного .NET окружения на прогретом экземпляре? -3228.28 3236.16 SPEAKER_01 Казалось бы, они должны быть или одинаковыми, ну или NetAuth, раз он настолько оптимизированный, красивый и такое, должен быть даже быстрее. -3236.16 3238.12 SPEAKER_01 Откуда вот эта медленность? -3238.12 3242.84 SPEAKER_01 Да, хороший вопрос, на самом деле, начну немножко издалека. -3242.84 3257.28 SPEAKER_01 Смотри, в случае, когда мы используем в Яндекс.Функциях холодный старт, то приложение у нас каждый раз запускается заново, если мы работаем с JIT, вот, и происходит JIT-компиляция. -3257.28 3261.20 SPEAKER_01 Вот за счет этого холодный старт, он достаточно долго отрабатывает. -3261.84 3278.84 SPEAKER_01 Для подготовленного экземпляра, как я уже описал в статье, мы видим, что существует уже поднятый хост с приложением, которое скомпилировано, вот, и, собственно, это доказывается тем, что как раз там вылезает вот этот сайд-эффект, данные от одного запроса могут быть доступны другому запросу. -3278.84 3289.04 SPEAKER_01 Вот, это нам говорит о том, что хост с .NET-приложением, он поднят, вот, и мы, собственно, функции каждый раз вызывая, уже стреляем в этот поднятый хост. -3289.04 3306.60 SPEAKER_01 Вот, и вот для JIT-а из-за этого холодный старт сильно отличается по времени работы от подготовленного экземпляра, потому что, в первом случае, у нас поднят хост, запущено приложение, там, весь EL-код уже переведен в машинные команды, все, бери да отрабатывай. -3306.60 3310.60 SPEAKER_01 А в случае с холодным стартом все это нужно делать каждый раз. -3310.60 3319.60 SPEAKER_01 Вот, ну, и, собственно, когда мы говорим про AVT, у нас уже холодный старт от подготовленного экземпляра отличается фактически не сильно. -3319.60 3326.12 SPEAKER_01 Мы в первом и в втором случае полностью запускаем собранные AVT-приложения, там, из бар-скрипта. -3326.12 3338.56 SPEAKER_01 В случае с подготовленным экземпляром у нас разве что само окружение уже поднято, то есть, да, там, Linux какое-то, какой-то Linux-окружение, на котором приложение выполняется, оно поднято. -3338.56 3341.56 SPEAKER_01 Но, кстати, Яндекс.Функция его довольно быстро и так поднимает. -3341.56 3343.56 SPEAKER_01 Вот, поэтому разница небольшая. -3343.56 3351.64 SPEAKER_01 И вот почему у нас получается, отвечая, да, на вопрос, почему AVT медленнее в подготовленном экземпляре, чем JIT. -3351.64 3359.80 SPEAKER_01 У меня есть три, ну, как, не только предположения, три фактора, которые совершенно точно на это влияют. -3359.80 3372.32 SPEAKER_01 Во-первых, когда мы работаем с JIT-компиляцией, с встроенной .NET-средой, когда мы стреляем в подготовленный экземпляр, он, приложение на нем уже запущено. -3372.32 3377.44 SPEAKER_01 В случае с AVT, приложение нужно запустить, это все равно какой-то ресурс занимает. -3377.44 3384.88 SPEAKER_01 Нужно выделить память, ну, из вашего скрипта запускается приложение каждый раз заново, на это какие-то ресурсы тратятся. -3384.88 3385.88 SPEAKER_01 Вот. -3385.88 3409.16 SPEAKER_01 И вот это, я думаю, влияет, причем достаточно сильно, потому что, да, AVT у нас обгоняет JIT при старте, за счет того, что отсутствует необходимость компиляции, но в случае с подготовленным экземпляром у нас мало того, что там JIT уже скомпилирован, так он еще и запущен, а здесь нам нужно приложение запускать, поэтому вот какой-то ресурс на это тратится, я думаю, существенно. -3409.16 3428.16 SPEAKER_01 Во-вторых, что еще влияет, почему встроенный JIT, .NET-шески, в Яндекс.Функциях быстрее, это то, что в принципе вообще у нас AVT так работает, что он генерирует универсальный набор инструкций для какой-то указанной среды, которую мы вот указали, в Runtime Identifier. -3428.16 3432.64 SPEAKER_01 Мы там можем указать Linux x64, там Windows x64 и так далее. -3432.64 3433.64 SPEAKER_01 Вот. -3433.64 3444.68 SPEAKER_01 Такой подход, он не учитывает много особенностей какого-то конкретного окружения, то есть генерируется максимально универсальный набор инструкций для Linux x64, например. -3444.68 3461.92 SPEAKER_01 А .NET, современный JIT, встроенный в .NET, он более умный, он смотрит, где он запущен, да, он там понимает гораздо больше особенностей среды, это не просто там Linux x64, а еще какие-то особенности архитектуры и так далее. -3461.92 3466.00 SPEAKER_01 И он более оптимальный набор инструкций будет генерировать под эту среду. -3466.00 3467.00 SPEAKER_01 Вот. -3467.00 3485.68 SPEAKER_01 Но здесь стоит отметить, что .NET можно настраивать в ряде случаев, я вот этим не занимался, то есть можно там указать в csproj файле там набор атрибутов, если мы точно знаем, ну, некоторые особенности той среды, на которой он будет выполняться, то может быть вот здесь можно чуть-чуть соптимизировать. -3485.68 3495.32 SPEAKER_01 Я этим не занимался, но может быть небольшое ускорение здесь можно получить за счет того, что мы сразу укажем там какие-то наборы инструкций. -3495.32 3500.40 SPEAKER_01 Ты имеешь в виду инструкции именно процессора, который используется? -3500.40 3501.40 SPEAKER_01 Да-да-да. -3501.40 3508.60 SPEAKER_01 То есть мы должны понимать, ну, для этого нужно, конечно, знать архитектуру того, где Яндекс.функции запускает твое приложение. -3508.60 3510.00 SPEAKER_01 Я вот так глубоко не копал. -3510.00 3519.92 SPEAKER_01 Ну, так как у них там все равно виртуальные машины запускаются, то есть эта архитектура, скорее всего, у них не сильно меняется между запуском функций, то есть там какая-то виртуальная машина, которая подразумевает конкретный процессор, который она эмулирует. -3519.92 3523.24 SPEAKER_01 Ну и, наверное, эта информация более-менее стабильная, то есть на нее можно рассчитывать. -3523.24 3531.52 SPEAKER_01 Ну, я надеюсь, что да, скорее всего, да, то есть в эту сторону можно покопать и можно, может быть, чуть-чуть ускорить за счет этого. -3531.52 3543.00 SPEAKER_01 Но, тем не менее, я этим не занимался, я там указал условно максимально универсальное средоуполнение, Linux x64, и довольствовался тем, что мне AUT легенерирует. -3543.00 3567.80 SPEAKER_01 Ну и третий, третий фактор, который влияет, это, опять же таки, G в современном .NET-е, он имеет ряд оптимизаций в рантайме непосредственно, то есть когда приложение запущено, оно работает и, ну, условно говоря, в рантайме может перекомпилироваться, могут перекомпилироваться определенные участки кода по-другому, более оптимально в процессе работы. -3567.80 3579.20 SPEAKER_01 AUT, конечно, ничего такого не умеет, то есть вот как он сгенерировал машинные команды на этапе компиляции, так они будут выполняться, ничего там перекомпилироваться уже не будет, там никакой перекомпиляции нет. -3579.20 3592.84 SPEAKER_01 Вот, поэтому я думаю, что за счет этого еще тоже может определенный прирост производительности, ну, получаться, если GIT компилирует код, и приложение работает достаточно долго, то есть подготовленный экземпляр висит какое-то время. -3592.84 3619.96 SPEAKER_01 Угу, и смотри, мне кажется, что самым существенным — это первый пункт должен быть, да, то есть накладные расходы как раз на вызов, на загрузку самого приложения, на загрузку его с памяти, на выделение памяти, на загрузку с диска, на выделение памяти и так далее, а ты не знаешь, не смотрел ли, может быть, у других провайдеров, клауд-провайдеров есть какие-то, не знаю, хосты для нативных приложений, которые вот его уже загрузили, осталось там по какому-нибудь C-коду дернуть, правильный метод и все. -3619.96 3623.48 SPEAKER_01 Вот что-нибудь такое не видел, не встречал, есть ли решение этой проблемы принципиальной? -3623.48 3636.68 SPEAKER_01 Во-первых, я не считаю это проблемой, то есть если мы посмотрим на метрики в статье, то да, NativeUIT проигрывает по времени подготовленному экземпляру со встроенным дотнетом, но на мой взгляд проигрывает не сильно. -3636.68 3637.68 SPEAKER_01 Вот. -3637.68 3644.36 SPEAKER_01 И скорее всего, если поднять, ну то есть мы говорим о том, что приложение будет запущено и оно будет висеть какое-то время. -3644.36 3651.76 SPEAKER_01 Здесь у нас есть опасность попасть, ну получить тот же тайт-эффект, от которого я в статье и пытался избавляться. -3651.76 3655.20 SPEAKER_01 Если приложение уже запущено, оно может сохранять какие-то данные. -3655.20 3662.76 SPEAKER_01 И если данные можно сохранить внутри приложения в каких-то переменных, значит их можно шарить между запросами. -3662.76 3671.80 SPEAKER_01 А это уже нарушает один из основных принципов FaaS архитектуры, то, что вызовы должны быть изолированы вокруг. -3671.80 3672.80 SPEAKER_01 Вот. -3672.80 3673.80 SPEAKER_01 Ну да, да. -3673.80 3688.88 SPEAKER_01 Ну, да, я отвечаю на твой вопрос, я не смотрел, где можно прямо вот, чтобы у какого-то облачного провайдера было кто-то именно заточенное под native-UT приложение .NET, я вообще не думаю, что такое можно найти. -3688.88 3689.88 SPEAKER_01 Вот. -3689.88 3698.32 SPEAKER_01 Тут в Яндекс.Функциях, я не нашел в интернете абсолютно никаких следов, что кто-то когда-то в Яндекс.Функциях пытался хотя бы запускать native-UT приложение. -3698.32 3704.92 SPEAKER_01 Возможно, я сделал первый, может быть, даже до сих пор единственный, ну, видимо, людям это пока не очень нужно. -3704.92 3706.60 SPEAKER_01 Может быть, кому-то это решение поможет. -3706.60 3711.52 SPEAKER_01 Да, в любом случае, опыт прекрасный, поэтому хорошо, что ты его зафиксировал в виде отдельной статьи. -3711.52 3718.60 SPEAKER_01 Ну, я с тобой согласен, что если все-таки копать в переиспользование одного хаста, который будет запускать, это полностью уходит от цели статьи. -3718.60 3719.60 SPEAKER_01 Отлично. -3719.60 3737.04 SPEAKER_01 Так, давай напоследок, смотри, мы еще сошлемся на твой доклад, но ты в статье описал, что, в принципе, если вам этот подход понравился, то перед вами стоит ограничение, да, ограничение самого IoT, то есть вы не все, не весь ваш код сможете превратить, запаковать вот таким вот образом. -3737.04 3753.44 SPEAKER_01 Можешь назвать кратко вот три, не знаю, самых существенных ограничения, которые чаще всего встречаются в приложении, которые, с помощью которых, из-за которых невозможно будет таким образом упаковать ваше приложение и опубликовать в виде Яндекс-функции? -3753.44 3771.36 SPEAKER_01 Да, смогу назвать, на самом деле, у Native IoT собственных ограничений как таковых нет, но есть ограничения связанные с стримингом, то есть стриминг используется, есть ограничения связанные с публикацией, ну, с сингл-файл публикейшн. -3771.36 3772.36 SPEAKER_01 Вот. -3772.36 3779.80 SPEAKER_01 И все они перетекли к нам в наследование, если мы хотим собирать Native IoT приложение, то придется эти ограничения учитывать. -3779.80 3806.00 SPEAKER_01 Вот, могу дать такой универсальный совет, скорее всего, если кто-то будет писать приложение сразу под Native IoT, то придется учитывать, что JSON-сериализация, вот, часть всего, я вижу на проекте, который я пытался переводить уже готовый на Native IoT, или если пишут с нуля, то первое, что стоит учитывать, что нужно использовать source-генераторы для JSON-сериалайзеров. -3806.00 3807.00 SPEAKER_01 Вот. -3807.00 3816.76 SPEAKER_01 Это вот такое, ну, не то чтобы ограничение, а особенность разработки, да, то есть если это не учесть, если оставить JSON-сериализацию в рантайме, то оно в Native IoT не заработает. -3816.76 3817.76 SPEAKER_01 Вот. -3817.76 3822.72 SPEAKER_01 И если нужно там определенный атрибут добавлять, у меня в докладе это есть, как этим пользоваться. -3822.72 3823.72 SPEAKER_01 Вот. -3823.72 3830.44 SPEAKER_01 Поэтому это вот, ну, не только прям ограничение, но это, наверное, да, в каком-то смысле это какие-то дополнительные source-генераторы. -3830.44 3835.50 SPEAKER_01 То есть всю JSON-сериализацию нужно учесть и описать в виде source-генерации. -3835.50 3846.72 SPEAKER_01 А так, ну, не все поддерживается, да, то есть не получится развернуть какое-нибудь полноценное там Blazor или Razor Pages приложение, пока что не получится. -3846.72 3850.92 SPEAKER_01 То есть есть, опять же, такие… Ну, если мы говорим о функциях, наверное, это не так страшно. -3850.92 3872.56 SPEAKER_01 Да, в функциях, я вот даже так не могу навскидку сказать, чего может не хватить, если используем какие-то дополнительные решения, ну, то есть какие-то даже известные, там, видите, ну, GetPackets, условно, какой-нибудь медиатор, я не знаю, хочет ли кто-то в функциях использовать медиатор, мне кажется, функция это что-то такое быстрое, что отработало, один раз умерло, там, до следующего вызова. -3872.56 3873.56 SPEAKER_01 Вот. -3873.56 3876.32 SPEAKER_01 Ну, вот медиатор прям, он условно поддерживается в Native IoT. -3876.32 3877.32 SPEAKER_01 Там коктейлить придется. -3877.32 3878.32 SPEAKER_01 Ну, и да. -3878.32 3881.92 SPEAKER_01 Ну, хорошо, смотри, сервизатор, который ты назвал, это уже прекрасно. -3881.92 3884.00 SPEAKER_01 Ну, об остальном, я думаю, мы посмотрим в докладе. -3884.00 3885.00 SPEAKER_01 Хорошо. -3885.00 3888.16 SPEAKER_01 Спасибо, что помог разобраться. -3888.16 3892.92 SPEAKER_01 Так, я напомню, что с нами был Андрей Порожняков, автор статьи, которую мы обсуждаем. -3892.92 3893.92 SPEAKER_01 Спасибо большое. -3893.92 3894.92 SPEAKER_01 До новых встреч, Андрей. -3894.92 3896.44 SPEAKER_01 Да, спасибо, что позвали. -3896.44 3897.44 SPEAKER_01 Всем пока. -3897.44 3898.44 SPEAKER_01 Пока. -3898.44 3902.08 SPEAKER_01 Так, отлично, отлично, что Андрей нам все прояснил. -3902.08 3903.24 SPEAKER_01 Давайте подведем итоги. -3903.24 3904.76 SPEAKER_01 Итак, что же получается? -3904.76 3924.00 SPEAKER_01 Что если вы готовы принять на себе риски, когда ваше состояние в ваших функциях может смешиваться, вы понимаете, что вы или все контролируете, или для вас это не страшно, а также если для вас время холодного старта не особо критично, то, наверное, можно выбрать чистые Яндекс-функции с дотнет-окружением. -3924.00 3936.26 SPEAKER_01 Если же вы хотите все-таки, чтобы никакого состояния не смешивалось и ваши функции были наичистейшие, то вы можете использовать NativeOut в виде запускаемого файла. -3936.26 3945.64 SPEAKER_01 Здесь еще нужно иметь в виду, что действительно у NativeOut есть ограничения, то есть не любое приложение вы прям можете взять и прекомпилировать в NativeOut. -3945.64 3949.72 SPEAKER_01 Его необходимо или немножко подготовить, или может быть даже это совсем невозможно. -3949.72 3963.00 SPEAKER_01 Какие именно ограничения связаны с NativeOut, как его готовить и какие тонкости на этом пути вас могут встретить, вы можете посмотреть в прекрасном докладе Андрея Порожнякова «NativeOut. Возможности и ограничения», который мы упоминали выше. -3963.00 3976.04 SPEAKER_01 Если же вам интересно, как работают Яндекс-клаундфункшены под капотом, то есть шикарный доклад, который Максим Шошин делал на spb.net, который называется «Серверлесс под капотом клаундфункшенов». -3976.04 3996.44 SPEAKER_01 Макс работает в Яндексе и непосредственно участвовал в разработке клаундфункшенов, поэтому он красиво на картинках показывает, как же это все там работает, вся эта магия с виртуальными машинами, с засыпанием, с прогревом, с амортизацией, в общем, очень интересно, поэтому вот эти два доклада обязательно гляньте, если тема клаундфункшенов и аота вам интересна. -3996.44 4008.40 SPEAKER_00 Ну прям монументально, статья оказалась всего-то что не так, краткий ответ сначала думал, что все не так, но оказалось все гораздо сложнее и интереснее, действительно. -4008.40 4021.48 SPEAKER_00 Ну непонятно, насколько как бы хочется прям вкладываться в NativeOut для того, чтобы получить выигрыш, особенно если прогретые функции работают быстрее, ну да, надо смотреть. -4021.48 4025.76 SPEAKER_00 Потому что NativeOut все-таки требует некоторого приседания для того, чтобы все под ним заработало. -4025.76 4033.12 SPEAKER_01 С другой стороны, видишь, не талия, это прекрасная техническая задачка, на которую можно потратить выходные, а потом хвастаться перед пацанами. -4033.12 4041.68 SPEAKER_01 Ну или на первую неделю в NativeOut, ну или месяц, а потом еще баги отлавливать пару месяцев, да, это все тонкости. -4041.68 4096.12 SPEAKER_00 Да, ладно, давай пойдем дальше, дальше у нас, наверное, будет не очень профильная для нас статья, ну даже не статья, а это вышедший Technology Radar, он на самом деле вышел довольно давно, мне кажется, выходит он 2 раза в год, если я ничего не путаю, и я его проглядел, казалось бы, ну что там интересного может быть, все же будут говорить про LLM, и я в общем не ошибся, если мы посмотрим в раздел техники, напоминаю, что Technology Radar это такая штука, которая выпускается компанией ThoughtWorks, и там рассказано, грубо говоря, там все технологии, нетехнологии, в общем там 4 раздела под названием Technics, Platforms, Tools и Languages and Frameworks, и в каждом из разделов различные технологии, софт, подходы, языки и прочее разделены на 4 части. -4096.12 4109.56 SPEAKER_00 Adopt, это значит можно использовать, все нормально, Tryout — пробуйте, но присматривайтесь, и Hold — лучше пока прекратить использовать, если вы используете. -4109.56 4143.08 SPEAKER_00 И в разделе Technics, то есть всякие разные техники, не знаю, подходы, сложно на русском перевести каким-то одним словом сейчас сходу, там действительно прям засилье LLM-ок во всех разделах, то есть в трайле 6 из 8 пунктов про LLM, в ASS 5 из 7 пунктов про LLM, и даже в Hold пробрался LLM, где сказано, не надо заменять парное программирование парным программированием с AI, это пока не то. -4143.08 4153.12 SPEAKER_00 Это был неожиданный вывод, то есть пока ты читаешь, ты такой, и тут LLM, и тут LLM, и тут Tools для LLM, и тут надо LLM, и тут LLM, и тут в Hold, а вот для парного программирования не надо. -4153.12 4160.00 SPEAKER_01 То есть как раз та ситуация, когда ты технологию еще даже не начал использовать, а другие уже закончили -4160.00 4161.00 SPEAKER_00 использовать. -4161.00 4164.08 SPEAKER_00 Типа того, то есть как бы живой человек пока лучше. -4164.08 4183.88 SPEAKER_00 В Platforms я ничего интересного не нашел, там какие-то такие очень супер специфичные интерфразные какие-то платформы либо опять же все, что относящиеся к AI, а вот секция Tools она в принципе интересна, я планирую в нее заглянуть, посмотреть, ну в смысле я в нее уже заглянул, и даже какие-то кусочки из нее использую или пробовал. -4183.88 4201.00 SPEAKER_00 Значит в секции Adopt, то есть в секции давайте уже пора применять можно, мы разрешаем, или мы советуем, находится такой тул под названием Bruna, мы его уже упоминали по-моему в кратко разном в каком-то из выпусков с полгодика назад, когда он вышел, это замена Postman. -4201.00 4215.48 SPEAKER_00 Если вы пользуетесь Postman, Postman сейчас стал супертяжелый Postman, по-моему больше не разрешает никакого Local Only разработки, там нужно обязательно логиниться в их клауд, или что-то в таком духе, когда я давно уже не пользуюсь, но что-то такое слышалось. -4215.48 4226.32 SPEAKER_00 Это если вдруг у вас по какой-то причине нет интернета, то он там будет страдать и не запускаться, по крайней мере была такая версия у меня, которая без интернета не запускалась. -4226.32 4262.52 SPEAKER_00 В общем, кому-то это тоже надоело, и товарищ написал опенсурсный клиентик Bruna, там у него есть какие-то кусочки платных функций, которые не опенсурсные, но даже в бесплатном варианте он вполне себе функционален, активно очень дорабатывается, поэтому если вы пользовались Postman, можно посмотреть на альтернативы, я сейчас в основном пользуюсь клиентом Insomnia, который, если я правильно помню, по-моему тоже Electron, плюс кусочек .NET, мне казалось там был раньше, по крайней мере, вот, но на Bruna тоже поглядываю, он у меня стоит вторым, и в принципе более-менее работает. -4262.52 4268.96 SPEAKER_00 Значит, в разделе Trial тоже есть штука, которую я либо пробовал, либо планирую попробовать. -4268.96 4290.88 SPEAKER_00 Во-первых, это тулл, не знаю, на комплект туллов под названием Devbox, они называют это Isolated Environments Without Docker, то есть если вы хотите каким-то образом изолировать всякие разные ваши инвайорменты друг от друга, ну там, не знаю, .NET 5, .NET 8 или 9, без использования докера и чего-либо. -4290.88 4315.00 SPEAKER_00 В общем-то, идея не нова, таких штук существует довольно много и разных, .NET сам по себе довольно неплохо умеет изолироваться, у нас, как известно, SDK ставится каждый в свою папочку, такие же туллы существуют для Java, для Python, в Python, мне кажется, это наиболее развито со всякими их VN и прочими штуками, а здесь тулл, который вроде как для всего. -4315.00 4321.56 SPEAKER_00 Там у них на сайте указано, по-моему, типа 15 разных языков и он, мол, для всех умеет работать. -4321.56 4324.40 SPEAKER_00 Планирую посмотреть, попробовать, может быть, действительно что-то удобное. -4324.40 4327.32 SPEAKER_01 То есть ты не знаешь, как он внутри работает, да, как он изоляции добивается? -4327.32 4328.32 SPEAKER_01 Не смотрел. -4328.32 4329.32 SPEAKER_00 Гарантирует? -4329.32 4330.32 SPEAKER_00 Да, не смотрел. -4330.32 4369.44 SPEAKER_00 Ну, гарантировать там вряд ли, я думаю, что, скорее всего, там ничего более креативного, чем сим линками правильно разделять туллы и так далее, не придумали особо, понятное дело, просто вопрос, что оно делает это все единообразно для всех, потому что вот у меня там стоит, допустим, несколько версий Python, мне нужно помнить все команды, чтобы управлять ими, отдельно у меня стоит, ох, как его зовут, sdkman для управления версиями джавы, для .NET, понятно, у меня есть .NET tool, и в каждом из них нужно помнить свой синтаксис, как выбрать текущий, как поставить нужный, как посмотреть, какие доступны. -4369.44 4372.64 SPEAKER_00 Если это все будет сделано одним туллом, в принципе, будет удобно. -4372.64 4383.28 SPEAKER_00 Я планирую посмотреть, попробовать, мне приходится переключаться между разными технологиями, и если он будет выполнять свою задачу, будет хорошо, хотя бы даже в рамках одного моего ноутбука. -4383.28 4397.60 SPEAKER_00 Я не говорю про то, чтобы делать там стандартом на всю команду и вот это все, это как бы ладно, пусть остаются PyEnv, ну, допустим, если это про Python мы говорим, но даже хотя бы локально будет, может быть, полезно. -4397.60 4431.44 SPEAKER_00 Вторая штука – это продукт под названием divtastic, это open-source продукт, MIT лицензия, div differ, который умеет вроде как структурный div с учетом синтаксиса исходников, я бы сказал, то есть он умеет понимать синтаксис исходников и, соответственно, как-то показывает диффы более оптимально, нежели чем обычные дифферы, которые просто трочки сравнивают, не зная, что такое синтаксис. -4431.44 4483.96 SPEAKER_00 Пока выглядит, что вроде как командлайновский, и я так понимаю, что его главное предназначение это как раз таки, ну, либо для тех, кто фанат командлайн, да, и живет в командлайне, либо его иногда удобно использовать, настроить в качестве git div tool, я иногда действительно пользуюсь git div в командлайне, чтобы быстренько посмотреть, что я там собираюсь коммитить, и приятно будет, если это будет не, ну, как-то действительно красиво расцвечено, он цветами всё это рисует в консольке, если терминал поддерживает вот это всё, вот именно поэтому я его хочу попробовать прикрутить именно как div tool, чисто иногда смотреть в консольке, так, я обычно использую что-то стороннее и более развесистое, гуёвое, когда мне нужно особенно какие-то three-way merges делать, вот это всё, тут понятно, что одним простым диффом не обойдёшься. -4483.96 4493.08 SPEAKER_01 Да, я смотрю сейчас по документации, что это действительно больше он div, как раз действительно git tool, командлайновый без merge. -4493.08 4495.52 SPEAKER_01 Ну, без merge, это уже другой инструмент. -4495.52 4517.88 SPEAKER_00 Ну, это другой инструмент, но быстренько проглядеть, что же вы там собираетесь закоммитить, если вы, например, пользуетесь командлайновым git, а я знаю людей, которые именно коммитят git, то есть всякие там rebases, ну, сложные короче workflow делают всё-таки в UI, а базовую работу, да, там, checkout, бранчи посвечить, коммиты сделать, пуши сделать, вот из командлайн, я тоже, наверное, как-то так делаю, -4517.88 4518.88 SPEAKER_01 будет полезно. -4518.88 4522.44 SPEAKER_01 Я как раз наоборот, в rebase, в UI боюсь, я в rebase только командлайн не делаю. -4522.44 4524.36 SPEAKER_01 Ну и всё остальное тоже командлайн. -4524.36 4527.48 SPEAKER_01 Кстати, программинг-лэнгвич, который поддерживается, C# есть. -4527.48 4528.48 SPEAKER_01 Да, да, да. -4528.48 4529.48 SPEAKER_01 Наверное, будет удобно. -4529.48 4540.64 SPEAKER_01 Меня больше удивляет, почему это привлекло внимание почему-то техрадара, ну то есть утилиток миллиард, ну то есть любой студент пишет div, tool, zoo, и она консольная, и она примитивная, ну то есть при чём здесь техрадар-то, как она туда попала? -4540.64 4541.64 SPEAKER_00 Интересный вопрос, несомненно. -4541.64 4553.08 SPEAKER_00 Ну нет, у них 21 тысяча звёздочек, то есть видимо это хороший какой-то на репозитории, в гитхабе, то есть в общем так-то… -4553.08 4560.08 SPEAKER_01 Просто функциональность элементарная, ну что такое, посмотреть div в командной строке, ну это нужно, я не знаю, раз в день это максимально просто. -4560.08 4562.60 SPEAKER_01 Ну, может быть, потому что это написано на расте? -4562.60 4570.08 SPEAKER_01 Это можно сравнить с кубернетосом, который, допустим, тоже в техрадаре существует, то есть они где-то одного уровня tool, zoo, да, кубернетос, и диффер консольный. -4570.08 4575.08 SPEAKER_00 Один на год, другой на расте, ну что там, разницы-то никакой. -4575.08 4580.64 SPEAKER_00 Дальше, следующий из разряда – это терминал. -4580.64 4582.92 SPEAKER_00 Каким терминалом ты пользуешься, Анатолий? -4582.92 4587.92 SPEAKER_00 У меня коньему и фар, не, ну для терминала коньему. -4587.92 4598.16 SPEAKER_00 Ну, ты, соответственно, под виндой, я сейчас живу на маке, на маке у меня iTerm, iTerm2, который не стандартный терминал, а чуть-чуть более развесистый терминал. -4598.16 4600.40 SPEAKER_00 А техрадар рекомендует использовать варп. -4600.40 4616.88 SPEAKER_00 Это, ну правда, тебе не подойдет, у них виндовой версии еще нет пока, но уже в техрадаре, прикинь, то есть они тоже как-то очень активно развиваются, это тоже написано на расте, может, в этом причина, может, они из-за раст все, вот. -4616.88 4623.40 SPEAKER_01 Может, может, там этот фаулер перевел на раст всю свою компанию, теперь радуются любые фанюрки. -4623.40 4624.40 SPEAKER_00 Возможно, возможно. -4624.40 4638.24 SPEAKER_00 Я не знаю, что там происходит, потому что действительно там варп, ну действительно, выглядит прикольно, там, по-моему, не было квейк-режима, и это для меня сразу минус. -4638.24 4643.28 SPEAKER_01 Так, а как им, возможно, пользоваться-то они, по-американски? -4643.28 4651.68 SPEAKER_00 Не, ну кто-то, например, я видел, и в принципе иногда я так делаю, бывает такой, что моя терминалка просто на отдельном десктопе лежит, то есть я туда переключаюсь. -4651.68 4668.40 SPEAKER_00 Ну что на винде, что на макетах делал, просто кладешь его на отдельный десктоп, и туда-сюда переключаешься, просто свайпом вправо-вправо, ну не свайпом, как-то с клавиатурой там, я не помню, виндус, не виндус, вправо, там, короче, какая-то магическая комбинация клавиш, я уже забыл, переключение -4668.40 4669.40 SPEAKER_01 между десктопами. -4669.40 4674.56 SPEAKER_01 Ну да, да, я точно так же на макетках, типа переключаюсь на виртуальный второй экран, в принципе удобно, конечно, -4674.56 4675.56 SPEAKER_00 но. -4675.56 4713.16 SPEAKER_00 Ну в общем вот, и туда же текстовый редактор z, опять же, текстовых редакторов миллион, sublime, z, какие еще есть, наверняка еще какие-то есть, вот, я имею в виду таких, которые кроссплатформенные везде, понятно, что если мы берем каждую платформу, там много кого будет, еще notepad++, да, для винды и прочее, но z тоже написан на расте, и когда я третий продукт увидел, который написан на расте, у меня закрывалось подозрение, что видимо раст как-то их немножко проплатил, ну не проплатил наверное, но как-то что-то вот оно есть такое. -4713.16 4714.88 SPEAKER_01 Мельчает как-то, радар мельчает. -4714.88 4717.72 SPEAKER_00 Да, да, да, это меня тоже удивило. -4717.72 4722.64 SPEAKER_00 Дальше, ну не то, что интереснее, languages and frameworks, чтобы понимали масштаб. -4722.64 4749.92 SPEAKER_00 Там много всего очень узкоспецифичного, типа там граф QL опять появился в разделе trial, по-моему, если я правильно помню, как ни странно, но в adopt есть testcontainers, и тут, наверное, я соглашусь, testcontainers, технология хорошая, но опять же, сравниваем, да, масштаб testcontainers и command-line-differ, ну как бы да, берете, пользуйтесь testcontainers. -4749.92 4762.96 SPEAKER_00 А вот в trial, наверное, это редкий случай, но в trial затесалась дотнетная библиотека, причем это даже не tool, и не какой-то продукт, а это гитхабовская просто библиотечка. -4762.96 4767.20 SPEAKER_00 Библиотечка называется CAP, ну C-A-P, как CAP-теорема. -4767.20 4768.64 SPEAKER_00 Может, кстати, поэтому она так называется? -4768.64 4773.84 SPEAKER_00 Мы тут с тобой перед выпуском обсуждали, почему так называется, потому что распределенный система. -4773.84 4787.96 SPEAKER_01 Безусловно, да, безусловно, навеяно именно этим, но просто, знаешь, как CAP-теорема, это такая богатая абстракция, за которой кроется тонны научных статей, и вот одна из статей может вылиться в отбокс, но как бы слишком абстрактно названо. -4787.96 4820.24 SPEAKER_00 Ну, библиотечка, да, значит, это дотнетный нугет-пакет, который имеет там 6500 звездочек, 1500 форков, почти, ну, не то чтобы прям миллионы, но довольно много, и написано, что это distributed transaction solution in microservice based on eventual consistency, also an event bus with outbox pattern, короче, это и event bus тебе, и outbox, и eventual consistency там, и короче, чертовступе. -4820.24 4844.64 SPEAKER_00 Смысл в том, что, ну, основная идея, это, конечно, то, что эта библиотека будет работать в качестве outbox, тут прям написано, что вот CAP implements the outbox pattern described in the eShop eBook, но это классическая книжка Microsoft, внутренняя по архитектуре, модельный пример, eShop, он контейнер, и вот это все. -4844.64 4857.12 SPEAKER_00 И для того, чтобы это все поиспользовать, вы просто его ставите, dotnetcore.cap пакет называется, он тут поддерживает огромное количество очередей, надо напомнить, что такое outbox. -4857.12 4866.68 SPEAKER_00 Outbox - это когда вы вместе с основной транзакцией записи в вашу базу пишете в вашу же базу сообщение, которое надо отослать, а потом какой-то worker это сообщение таки отсылает куда-нибудь там, в какую-нибудь кавку, рэббит и еще кого-нибудь. -4866.68 4877.92 SPEAKER_00 Тут поддерживается и кавка, и рэббит, и эйджер, и амазон, и нац, и редис, и пульсар, а в качестве баса - сиквел, и майсиквел, и позгрей, и монго, ну и тут много чего еще. -4877.92 4884.36 SPEAKER_00 Короче, тут довольно простой интерфейс, если вам нужен outbox и вам лениво его писать самому, то пожалуйста. -4884.36 4890.60 SPEAKER_00 Причем он судя по всему, судя по тому, что тут есть всякие атрибутики капсабскрайб и вот это все, он еще и подписываться на что-то умеет. -4890.60 4898.84 SPEAKER_00 То есть он может и по архитектурной схеме, он, короче, может стоять на двух сторонах вашего outbox'а, в смысле и на отправляющей, и на принимающей стороне. -4898.84 4901.04 SPEAKER_00 В общем, интересно. -4901.04 4908.12 SPEAKER_01 Интересно, что по языкам здесь есть Vue и JavaScript, то есть у него еще какая-то и красивая мордочка, видимо, -4908.12 4909.12 SPEAKER_00 есть. -4909.12 4941.04 SPEAKER_00 Да, там есть дэшборд в отдельном пакете, не бойтесь, вы не затащите никакой vue.js в ваш бэкэнд, то есть это отдельный пакет, кап.дэшборд, если я правильно помню, называется, который позволяет, видимо, посмотреть, как это все живет, работает, может, какую-то статистику я не смотрел, но библиотечка интересная, я про нее не слышал раньше, мы как-то outbox всегда руками писали, но надо посмотреть, может, действительно полезно, если оно отлажено, работает, звездочек много, issues'ов не так много открытых, это значит, что либо никто не пользуется, но по звездочкам вроде пользуются, либо значит, автор хорошо, молодец, быстро закрывает, фиксит все. -4941.04 4954.68 SPEAKER_00 Так что вот такое вот внезапное отвлечение, наверное, на техрадар, который в этот раз мы довольно редко, мне кажется, последний раз перед этим мы смотрели на 28-ой что ли, то есть это получается года полтора-два назад, что это был 31-ый. -4954.68 4965.00 SPEAKER_01 Да, там что-то попадалось такое про dotnet, хотя непонятно, как они, если все везде любят раст, как они эту библиотечку с outbox'ом запихнут в свое приложение. -4965.00 4992.64 SPEAKER_00 Ну, непонятно, непонятно, у меня такое ощущение, что, ну, собственно, это не ощущение, мне кажется, то, как техрадары строятся, то есть они же компания, да, они же консультанты, то есть вот они поработали полгода, ну вот за полгода у них было много раста, вероятно, и, наверное, им попался какой-нибудь dotnet-ный проект, в котором они либо увидели эту библиотеку, либо ее заюзали, потому что им нужен был outbox, посмотрели, что это хорошо и решили, что это надо рекомендовать. -4992.64 4999.48 SPEAKER_00 Ну, тоже метод, даже просто их, по сути, список, чего они рекомендуют, это не то, что там вся индустрия обязана пользоваться. -4999.48 5001.60 SPEAKER_00 Просто хорошая практика. -5001.60 5020.40 SPEAKER_01 Ну, безусловно, нужно слушателям понимать, что это какой-то опыт определенный одной компании, это никаким образом не влияет ни на индустрию, ни на другие компании, ни на популярность библиотек, ни на что, просто компания довольно авторитетная и интересная, которая впервые выдумала этот самый техрадар, и за ней таким образом по интуиции все до сих пор следят. -5020.40 5052.00 SPEAKER_00 Ну и надо сказать, что вообще сама по себе идея хорошая, то есть если вы достаточно крупная компания, в которой есть там развесистый стек, то такую штуку полезно регулярно делать внутри компании самим, чтобы смотреть, следить за актуальным стеком, обновлять, иметь некоторые рекомендации, что мы используем, что не используем, чтобы знать, на каких версиях каких продуктов вы живете, ну или фреймворков, библиотек, какие подходы вы используете, и все такое прочее, чтобы идти в ногу со временем или наоборот не слишком его опережать. -5052.00 5055.04 SPEAKER_01 Да, так и есть. -5055.04 5069.08 SPEAKER_01 Так, чтобы нам идти в ногу со временем, не поверишь, у нас вторая статья с Хаббера, то как бы не дожидались мы целый год, а тут прям две сразу, ну, наверно авторы просыпаются после лета, загорелые, вдохновленные. -5069.08 5094.04 SPEAKER_01 И вторую статью с Хаббера мы нашли, которую написал Александр Кузнецов, называется она "Тюнинг запросы в EF-корс с помощью интерсепторов", а статья не то чтобы глубокая или мега страшная, просто она очень полезная, потому что как раз-таки не все разработчики знают о том, на что способен их Entity Framework, и поэтому могут упускать много возможностей, которые уже встроены в их фреймворк. -5094.04 5122.64 SPEAKER_01 На самом деле, Entity Framework очень мощный механизм, и с каждым новым релизом в нем добавляется еще множество-множество всего, поэтому если вдруг вы захотите каким-то образом в вашем приложении очень глубоко использовать этот фреймворк, то стоит, наверное, сесть и разобраться в нем, то есть по Entity Framework прям отдельно очень много книг даже выходит, и в книгах там тоже раскрываются такие аспекты, о которых рядовой разработчик наверняка никогда бы не узнал в своей жизни, если бы не пошел специально это копать. -5122.64 5155.80 SPEAKER_00 А еще, я тебя перебью, извини, что хорошо и полезно знать внутренности, чтобы не было некоторых неправильного понимания, наверное, вот так скажу, потому что когда я видел заголовок этой статьи, я сначала продумал про интерсепторы, которые фичи языка, и долго думал, каким образом фичи языка, которые, помните, интерсепторы, когда вы можете заинтерсептировать вызов произвольной функции с помощью source-генератора, сгенерив специальный атрибут со ссылкой на номер строки, и думаю, как так интересно, запросы-то приятные, чего-нибудь будут. -5155.80 5160.08 SPEAKER_00 Сейчас мы будем там что-нибудь переписывать в source-генераторах запросы. -5160.08 5179.64 SPEAKER_00 Ну вот, чтобы вы знали, чтобы вы так не путали, нужно знать, что внутри F-Core свои интерсепторы, и терминология очень полезна, когда вы работаете, ну, короче, да, когда вы работаете с каким-то фреймворком, знать вообще, что в нем бывает, чтобы вот так вот не путаться. -5179.64 5184.00 SPEAKER_01 Да, чтобы понимать вообще, куда это вообще относится, куда коней запрягать. -5184.00 5190.92 SPEAKER_01 В принципе, интерсепторы в Entity Framework'е появились еще до файл-генераторских интерсепторов. -5190.92 5196.08 SPEAKER_01 Грубо говоря, в ASP.NET'е вот эти, те же самые middleware, их тоже можно назвать интерсепторами в своем-то виде. -5196.08 5197.08 SPEAKER_00 Почему бы и нет? -5197.08 5202.24 SPEAKER_00 Ну, по логике, да, просто что по названию я их как-то никогда не пользовал в F-Core, и поэтому я напрочь забыл. -5202.24 5206.80 SPEAKER_00 Только уже когда начинаешь читать статьи, думаешь, а, точно, ну, что-то было такое, но мне как-то никогда не надо было. -5206.80 5208.84 SPEAKER_00 Давай послушаем, зачем это, может быть, надо. -5208.84 5212.40 SPEAKER_01 Ну, и как раз объявимся, что же это такое, чтобы в следующий раз вы их не путали. -5212.40 5214.44 SPEAKER_01 Итак, начнем сначала. -5214.44 5230.40 SPEAKER_01 Entity Framework — это довольно-таки богатый фреймворк, и он обладает богатыми возможностями по преобразованию вашей объектно-ориентированной модели, ваших DTO-шек, ваших объектных доменных сущностей в язык запросов, так, когда вы запрашиваете каких-нибудь юзеров и так далее. -5230.40 5241.48 SPEAKER_01 И иногда бывает таким образом, что вам не хватает этих запросов, потому что, как ни крути, Entity Framework — это некое среднее, это пересечение между всеми базами данных. -5241.48 5248.44 SPEAKER_01 Если мы берем любую базу данных, то в общем случае она будет мощнее, чем Entity Framework, у нее будет больше возможностей, она больше всего будет уметь. -5248.44 5256.72 SPEAKER_01 Но так как Entity Framework пытается объединить под своим крылом множество датабайс-провайдеров, он выбирает всю середину, которая есть. -5256.72 5267.84 SPEAKER_01 Поэтому иногда вы хотите чего-то, что Entity Framework не поддерживает, а конкретная база данных, которая используется в вашем приложении, это поддерживает, и как-то кажется странным терять эту возможность. -5267.84 5272.36 SPEAKER_01 И чтобы решить эту проблему, есть несколько вариантов. -5272.36 5277.04 SPEAKER_01 Наверное, самый популярный — это писать SQL-запросы напрямую. -5277.04 5279.00 SPEAKER_01 Entity Framework это позволяет. -5279.00 5282.88 SPEAKER_01 Второй вариант — это использовать хранимые процедуры. -5282.88 5290.68 SPEAKER_01 Еще не ясно, что из этого хуже, но опять же, если вы спускаетесь на такой низкий уровень, то с этим имеется куча проблем. -5290.68 5310.28 SPEAKER_01 Это, наверное, тема для другой отдельной статьи, почему сырые SQL-запросы — это плохо, но как показала практика, большинство компаний используют именно ORM в нашей инфраструктуре, как раз потому, что они поняли все плюсы ORM и не хотят лезть во все минусы ручного написания запросов и тем более хранимых процедур. -5310.28 5318.80 SPEAKER_01 Поэтому у нас есть третий выход, который избавляет нас от того, чтобы писать вручную SQL-код и каким-то образом сопровождать хранимые процедуры. -5318.80 5321.08 SPEAKER_01 Третий выход — это как раз-таки интерсепторы. -5321.08 5336.84 SPEAKER_01 Интерсепторы — это некие перехватчики, которые помогают вам немножко расширить функциональность, ту, которая идет из коробки к Entity Framework, немножко расширить функциональность благодаря тому, что вы в вашем приложении обладаете знаниями конкретной базы данных, которые вы используете. -5336.84 5343.12 SPEAKER_01 То есть Entity Framework сама это сделать не может, а вы можете, потому что вы знаете, что у вас за база данных под капотом. -5343.12 5346.96 SPEAKER_01 Давайте же разберемся на примере, каким же образом это сделать. -5346.96 5352.16 SPEAKER_01 Автору понадобилась необходимость добавить специальный оператор forUpdate. -5352.16 5357.72 SPEAKER_01 В PostgreSQL такой оператор поддерживается, а в Entity Framework не поддерживается. -5357.72 5359.00 SPEAKER_01 Что такое forUpdate? -5359.00 5361.24 SPEAKER_01 Это достаточно такая простая штука. -5361.24 5386.48 SPEAKER_01 Например, если мы хотим выбрать некое подмножество каких-то записей для того, чтобы их в будущем изменить, добавляя специальное окончание forUpdate, мы сообщаем базе данных, что эти записи заблокированы для другого запроса forUpdate, который попытается их изменить. -5386.48 5391.60 SPEAKER_01 Это немножко похоже на пессимистичную блокировку, которую мы обсуждали с вами несколько статей ранее. -5391.60 5396.42 SPEAKER_01 То есть это такая своеобразная блокировка берется на все эти записи. -5396.42 5410.80 SPEAKER_01 И пока мы эти записи этим forUpdate не отпустили, то есть по сути, пока мы не закрыли транзакцию, в которой вызван этот forUpdate, другой select forUpdate эти записи взять не сможет. -5410.80 5414.40 SPEAKER_01 Таким образом, мы получаем вот такой пессимистичный лог. -5414.40 5423.80 SPEAKER_01 Записи мы с forUpdate забираем, изменяем, сохраняем, закрываем транзакцию, и следующий клиент, уже следующий поток, следующий concurrency какой-то агент уже может дальше работать с этими записями. -5423.80 5430.32 SPEAKER_01 Итак, вроде все понятно, концепция простая, и на уровне кода она реализуется точно так же, все довольно просто. -5430.32 5435.24 SPEAKER_01 Естественно, необходимо добавить специальные ключевые слова forUpdate в конец запроса, в конец запроса селекта. -5435.24 5441.68 SPEAKER_01 Да, то есть вы получаете select, rollie, valise, from users, forUpdate, и все, в этом принципе и все, что нам нужно сделать. -5441.68 5448.52 SPEAKER_01 Итак, попробуем же научить Entity Framework добавлять вот такой префикс в конечный запрос, который он генерирует в базу данных. -5448.52 5453.48 SPEAKER_01 На самом деле кажется, что это довольно сложно, потому что Entity Framework большой, мощный, много всего умеет. -5453.48 5463.56 SPEAKER_01 Но на самом деле он большой и мощный не только потому, что много всего умеет, но и потому, что в нем очень хорошо продуманы различные точки расширения, которые вы можете делать из своего приложения. -5463.56 5467.00 SPEAKER_01 Поэтому данное расширение тоже работает довольно просто. -5467.00 5476.20 SPEAKER_01 И точек расширения таких очень много, да, интерсепторы это всего лишь одна из таких точек, но нам она лучше всего подходит. -5476.20 5477.20 SPEAKER_01 Что же такое интерсепторы? -5477.20 5484.32 SPEAKER_01 Это специальный промежуточный код, который позволяет вам модифицировать запрос до того, как этот запрос уйдет в базу данных. -5484.32 5489.44 SPEAKER_01 Для того, чтобы нам создать такой интерсептор и подключить его и использовать, нам необходимо сделать три шага. -5489.44 5492.20 SPEAKER_01 Ну, во-первых, это объявить сам класс интерсептора и наполнить его какой-то логикой. -5492.20 5497.00 SPEAKER_01 Во-вторых, зарегистрировать интерсептор в нашем датабейс-контексте. -5497.00 5503.88 SPEAKER_01 И в-третьих, это понять тот момент, а когда нужно этот интерсептор применить, то есть в какой момент он должен сработать. -5503.88 5509.76 SPEAKER_01 Если же вы хотите, чтобы он применялся на каждый ваш запрос, то в принципе последний пункт вам не нужен. -5509.76 5514.68 SPEAKER_01 Но обычно вы хотите, чтобы он применялся не на каждый запрос. -5514.68 5519.00 SPEAKER_01 В нашем случае, в For Update, мы не хотим его добавлять, например, к делитам. -5519.00 5521.68 SPEAKER_01 Более того, мы не хотим его добавлять ко всем селектам. -5521.68 5529.12 SPEAKER_01 Мы хотим его добавлять только к селектам, которые мы пометили каким-то специальным атрибутом для того, для For Update. -5529.12 5536.44 SPEAKER_01 То есть у нас уже какое-то маленькое подмножество запросов должно попадаться, попадать под наш интерсептор. -5536.44 5545.52 SPEAKER_01 Начнем с самого сложного пункта, это как раз таки с понимания того, какие запросы мы должны модифицировать с помощью нашего интерсептора. -5545.52 5554.00 SPEAKER_01 В самых простейших случаях, например, как в нашем, мы можем воспользоваться таким прикольным методом, как tag_div. -5554.00 5561.92 SPEAKER_01 У любого iQueryable интерфейса есть метод tag_div, который принимает в качестве параметра обычную строчку. -5561.92 5566.72 SPEAKER_01 И все, что он делает, это раскладывает эту строчку в SQL-комментарий. -5566.72 5568.64 SPEAKER_01 Это, например, полезно для диагностики. -5568.64 5577.68 SPEAKER_01 Когда вы посылаете какой-то запрос в базу данных, то Quantity Framework вам пишет в логах, какой запрос он сделал. -5577.68 5586.36 SPEAKER_01 И, например, в логах вы можете с помощью метода tag_div добавить какой-то понятный для вас комментарий. -5586.36 5591.44 SPEAKER_01 Например, указать какой-нибудь Trace ID, из-за которого породился этот SQL-запрос. -5591.44 5595.44 SPEAKER_01 Или добавить текущего пользователя, который инициировал этот SQL-запрос. -5595.44 5598.44 SPEAKER_01 В общем, какую-то добавочную интересную информацию. -5598.44 5601.08 SPEAKER_01 То есть обычный комментарий к SQL. -5601.08 5611.24 SPEAKER_01 В нашем же случае, в принципе, мы можем проанализировать этот tag_div, то есть, что этот комментарий мы туда добавили, и каким-то образом в интерсепторе, допустим, на это среагировать. -5611.24 5615.28 SPEAKER_01 Таким образом, мы можем написать метод расширения, который называется for_update. -5615.28 5617.40 SPEAKER_01 Этот метод расширения будет iQueryable. -5617.40 5626.56 SPEAKER_01 И в этом методе расширения, в его реализации мы просто добавим tag, который в качестве параметра принимает строчку for_update. -5626.56 5630.00 SPEAKER_01 То есть это какой-то специальный ключ для нашего будущего интерсептора. -5630.00 5632.80 SPEAKER_01 Мы его просто передаем iQueryable, и все. -5632.80 5637.56 SPEAKER_01 И больше, в принципе, никаких задач нам делать не нужно. -5637.56 5638.56 SPEAKER_01 Дальше. -5638.56 5639.92 SPEAKER_01 Как же этот метод расширения использовать? -5639.92 5640.92 SPEAKER_01 Очень просто. -5640.92 5645.44 SPEAKER_01 Вызываете у вашего DB-контекста метод users, допустим, если вы хотите выбрать всех пользователей. -5645.44 5650.00 SPEAKER_01 Определяете какие-нибудь там условия, where user_id = id. -5650.00 5651.00 SPEAKER_01 Пишите .for_update. -5651.00 5657.80 SPEAKER_01 В этот момент вызывается наш метод расширения, и под капотом добавляет специальный SQL-комментарий. -5657.80 5660.36 SPEAKER_01 Теперь перейдем к написанию самого интерсептора. -5660.36 5670.92 SPEAKER_01 Для того, чтобы написать свой интерсептор, нам нужно пронаследоваться от стандартного интерфейса или базового класса DBCommandInterceptor и перекрыть всего лишь на всего один метод. -5670.92 5673.16 SPEAKER_01 В нашем случае это reader_executing. -5673.16 5682.60 SPEAKER_01 Как раз этот интерсептор, этот метод вызывается как раз в тот момент, когда мы подготавливаем запрос для чтения из базы данных. -5682.60 5684.64 SPEAKER_01 Что же мы можем здесь сделать? -5684.64 5695.12 SPEAKER_01 На данном этапе у нас существует некий объект DBCommand, у которого есть common_text, и этот common_text содержит полный SQL-запрос, тот, который сейчас пойдет в базу данных. -5695.12 5705.56 SPEAKER_01 Автор предлагает нам просто-напросто взять этот common_text с помощью метода contains, понять, есть ли в нем тот SQL-оператор, который мы поставили, то есть в нашем случае contains for_update. -5705.56 5711.36 SPEAKER_01 И если вдруг он есть, мы просто в конец текста добавляем ключевые слова for_update. -5711.36 5714.52 SPEAKER_01 Вот, в принципе, вся реализация, буквально в три строчки. -5714.52 5734.60 SPEAKER_01 Ну, тут предположение довольно смелое, то есть, действительно, метод contains я бы, наверное, заменил все-таки на ends_with, потому что если мы будем обновлять в базе данных фамилию юзера, и эта фамилия будет называться --for_update, то данный интерсептор тоже нам что-нибудь нехорошее сделает. -5734.60 5754.16 SPEAKER_01 Ну и также, то есть нужно проверить прежде всего, что этот for_update, компилятор где-нибудь должен, for_update комментарий должен быть где-нибудь там внизу или в самом верху, в общем, как-то более подстраховаться, наверное, или, может быть, стоит уже как-то синтаксически проанализировать, именно семантически, то есть проанализировать данный запрос, а не просто contains-ом полагаться. -5754.16 5759.48 SPEAKER_01 Но в общем случае, в принципе, подход рабочий, почему бы и нет. -5759.48 5766.28 SPEAKER_01 Если все остальные условия вас не пугают, то пожалуйста, то есть мы просто добавляем ключевой текст в конец нашего запроса. -5766.28 5771.16 SPEAKER_01 И самое последнее, что нам осталось сделать, это просто-напросто зарегистрировать наш интерсептор. -5771.16 5772.16 SPEAKER_01 То есть это тоже элементарно. -5772.16 5787.96 SPEAKER_01 В наследнике db_context, вашем application db_context, при регистрации провайдера, при указании там, где вы ему указываете connection string, вы просто вызываете ключевое слово add_interceptor и туда передаете ваш новый созданный красивый испеченный интерсептор. -5787.96 5796.64 SPEAKER_01 Теперь во время каждого запроса ваш интерсептор будет вызываться, и он сам будет определять, хочет он этот запрос модифицировать, если хочет, то как он его будет модифицировать. -5796.64 5801.44 SPEAKER_01 Итак, интерсепторы довольно такая полезная, мощная, интересная штука. -5801.44 5808.76 SPEAKER_01 И если бы их не было, то вам бы пришлось больше писать чистого скейтс-кода или чистых хранимых процедур. -5808.76 5817.40 SPEAKER_01 Ну, в общем, в любом случае, вы бы спустились в этот низкоуровневый мир, и вам бы навалилась большая тонна проблем после этого. -5817.40 5829.08 SPEAKER_01 Интерсепторы же помогают остаться вам все-таки в менеджмент мире, все-таки остаться на каких-то ORM-ках, управлять вашими сущностями, как вы к этому привыкли, и при этом расширять функциональность до прямо низкоуровневых протоколов. -5829.08 5832.92 SPEAKER_01 Также стоит отметить, что существует множество разных интерсепторов. -5832.92 5857.92 SPEAKER_01 Кроме command-интерсептора, который мы рассмотрели, есть connection-интерсепторы, которые позволяют управлять коннекциями, то есть соединениями с базой данных, есть transaction-интерсепторы, которые позволяют там джонглировать транзакциями в различных их семантических значениях, в общем, много красивых интересных интерсепторов, которые позволяют не только там расширять, допустим, все электронные апдейты и делиты, и менять типы, и в общем, много-много всего интересного можно с ними поделать. -5857.92 5873.56 SPEAKER_01 Поэтому если вдруг вам нужно немножко подрегулировать entity-framework для того, чтобы он генерил какие-то новые скейт-запросы, или каким-то образом транзакции обрабатывал по-особому, или логировал все коннекции, в общем, то посмотрите в сторону интерсепторов, довольно богатый и мощный механизм. -5873.56 5907.12 SPEAKER_00 Единственный момент, который я хочу отметить, что если вы будете использовать интерсепторы вот с тем подходом, как показано в статье, то есть через теги, то вы можете, надо внимательно посмотреть, чтобы не потерялась еще одна полезная возможность, потому что вот эти самые теги интересно и полезно использовать, чтобы каким-то образом отличать запросы друг от друга, то есть у нас, например, одно время использовались вот эти конструкции with text, они явно были написаны, туда дописывался комментарий по сути о том, что это за запрос, кратко. -5907.12 5918.92 SPEAKER_00 Тогда у вас в логах или в SQL-серверных логах или еще где-то просто видны эти названия запросов, даже если у вас запрос отрезан в конце, вам все равно по первому комментарию видно, что это был за запрос. -5918.92 5931.72 SPEAKER_00 И вот если вы теги начинаете использовать для таких интерсепторов, то нужно будет внимательно посмотреть, чтобы вы правильно их находили и нужные теги заменяли на дописывание запроса в нужном месте. -5931.72 5932.72 SPEAKER_00 Вот. -5932.72 5933.72 SPEAKER_01 Это просто. -5933.72 5946.12 SPEAKER_01 Ну, текущая реализация, кажется, твоему примеру не противоречит, она, ну, мы можем много использовать тегов, и она их, ну, и она ключевое слово, этот ключевой строков update просто в конец записывает, поэтому все остальные теги останутся на месте. -5946.12 5951.80 SPEAKER_00 Ну да, да, главное, чтобы не было конфликта с чем-нибудь еще. -5951.80 5952.80 SPEAKER_00 Вот. -5952.80 5958.32 SPEAKER_00 Хорошо, давай пойдем напоследок расскажем у нас кратко о разном. -5958.32 5966.88 SPEAKER_00 Тут накопилось немножечко статей, не статей, и начнем мы с tools, опять же. -5966.88 5989.48 SPEAKER_00 Мы, наверное, давно уже не касались всяких разных дампов для дотнета, того, как это все собирать, как это все анализировать, но если вы этим занимались, вы наверняка знаете такой tool procdump из комплекта sysinternals, отличных тулов от Марка Русиновича, которые позволяют на винде творить много чего полезного. -5989.48 6023.88 SPEAKER_00 У нас были доклады на dotnext давно уже про то, что некоторые из этих тулов, прокмон, например, перенеслись на линукс, и у них существует линукс-версия, так вот теперь появилась версия procdump для macOS, то есть если вы вдруг запускаете ваше дотнет-приложение на macOS, и вам хочется собрать дампы, напомню, что procdump он умеет собирать очень умно, его можно настроить до первого исключения или до конкретного, или еще как-то, или по памяти собрать вам дамп, или по времени, в общем, полезная штука, теперь она есть на macOS, можно пользоваться. -6023.88 6024.88 SPEAKER_00 Дальше. -6024.88 6081.36 SPEAKER_00 Есть библиотечка, у нас, кстати, это, наверное, один из немногих выпусков, где вы еще ни разу не сказали слово dotnetspire, исправляемся, появилась библиотека, называется dotnetspire-community-toolkit, видимо, это те интегрейшены, то есть те самые расширения для dotnetspire, которые не нашли или по какой-то причине не были включены в основной комплект dotnetspire, я напомню, что основные интегрейшены живут в самом репозиторе dotnetspire, но здесь живут другие, и там, в частности, там живет всякие джаваскриптовые штуки типа bana, dno, gotem живет, java со спрингом, node.js, ollama, rust, в общем, всякие, если вы хотите вот такие штуки подключить к вашему ispire-проекту, вам в этот самый dotnetspire-community-toolkit возможно в этом что-то найдете. -6081.36 6082.36 SPEAKER_00 Далее. -6082.36 6113.00 SPEAKER_00 У нас есть в дотнете командлайновый способ создать новый проект из шаблончика, называется dotnetnew, дальше можно выбрать какой шаблон вам нужен, и что-то там сделать, но был запрос, я не знаю откуда, что нам нужен новый interactive CLI tool, то есть в dotnetnew, как правило, вы практически все передаете командлайн, там он вам спрашивает пару вопросов, но в целом обычно большую часть всего передаете командлайн. -6113.00 6136.28 SPEAKER_00 Здесь же это теперь interactive новый tool появился, называется dotnetscaffold, пока это превьюшка, устанавливается как обычно global tool, сейчас поддерживает пока ispire.net core, webapp, webapi и dotnetspire с blazor, то есть если вы хотите какой-то более такой wizard-стайл создания новых приложений из шаблонов, посмотрите в сторону dotnetscaffold, возможно вам понравится. -6136.28 6141.08 SPEAKER_01 При том из командной строки, не просто там wizard какой-нибудь с кнопочками, а командно-строковый wizard. -6141.08 6147.24 SPEAKER_00 Interactive CLI tool, прям подчеркнуто, то есть это как бы ньюайны, да, все в командной строчке. -6147.24 6174.28 SPEAKER_01 Опять же, немножко страшно, странно, да и страшно тоже, потому что обычно в языках scaffold это немножко другое, это штука, которая помогает тебе, например, у существующего приложения добавить, допустим, контроллер, который протянется в модельку и который зарегистрируется в базу данных и который сгенерит миграцию, вот это scaffold, а то, что мы создаем что-то с нуля, это уже больше какой-то действительно new, и лучше бы они там dotnet.new как-нибудь расширили, добавили бы и флажок interactive или что-нибудь в этом духе. -6174.28 6179.72 SPEAKER_00 Ну может потом переименуют и сделают его view, а scaffold за view, не знаю, посмотрим. -6179.72 6221.20 SPEAKER_00 Дальше, мы уже сегодня обсуждали статью Кристофа Назара про то, как сделать собственный профайлер узкоспециализированный, есть такой товарищ Александр Мютл, он периодически делает какие-то доклады, ну и вообще низкоуровневый товарищ про dotnet, он тоже сделал свой собственный профайлер, он доступен только на Windows, потому что он работает на Event Tracing for Windows, ему был нужен, я так понимаю, некоторый аналог perfview в каком-то смысле в более красивом виде, плюс который умеет работать одновременно и с ядерными функциями, и с нативным кодом, и с managed, короче, все вместе. -6221.20 6295.44 SPEAKER_00 В итоге он написал профайлер, который в качестве UI, ну чтобы не париться, использует профайлер из Firefox, то есть на самом деле он просто генерит некоторые трейсы в формате, который умеет понимать профайлер.firefox.com, это всякие там, как раз там будут, как они называются, flame graph и вот это все, короче, все умеется, там довольно неплохой UI, вот, он умеет профайлер в смысле категоризировать функции, что это dotnet, dotnet.jit, dotnet.garbage.collector, native, kernel, как-то умеет трекать память, умеет понимать где когда срабатывал JIT с точки зрения compile time и какую функцию он в этот момент компилировал, знает ивенты от garbage.collector, всякие allocation ticks и прочее, при этом довольно легковесный, как написано, ну он генерит всего несколько мегабайт за 10 секунд работы, вот, но единственное, что требует восьмого дотнета или позднее, ставится через dotnet global tool install, если вам нужен какой-то очень развесистый профайлер, точнее не столько развесистый, сколько профайлер, который хорошо умеет с нативным кодом и внутрянкой дотнета работать, вот возможно, а перфю вы боитесь по какой-то причине или непонятно, как с ним работать, вот посмотрите на эту штуку, может вам понравится. -6295.44 6317.52 SPEAKER_00 И последнее от меня, это забавный сайтик, я на него возлагал, ну как не сайтик, это очередной гитхаб репозиторий, такие встречаются практически для разных технологий, это build with maui, мы с тобой много раз про мауи говорили, про то, что ну что-то как-то развивается непонятно как, непонятно как, а есть ли какие-то продукты, которые на нем написаны. -6317.52 6318.52 SPEAKER_00 Ну в общем, короче, я нашел. -6318.52 6320.52 SPEAKER_01 Да, это хороший список, ну-ка, сколько там продуктов -6320.52 6321.52 SPEAKER_00 нахуй? -6321.52 6324.44 SPEAKER_00 Там 27 приложений, я не знаю ни одного. -6324.44 6328.84 SPEAKER_00 Это хороший показатель того, что нахуй никому этот мауи не нужен. -6328.84 6339.08 SPEAKER_00 Ну то есть, там они довольно узкоспециализированы, то есть там типа, какое-то приложение для что-то типа трекинга сна или что-то в таком духе, какое-то приложение для скалолазания. -6339.08 6362.20 SPEAKER_00 Ну то есть, конечно, очень узкоспециализированные приложения для ios и андроида в основном, там с указанием количества скачиваний, некоторые даже довольно неплохо скачиваются, там на десятки тысяч идет речь, но десятки тысяч в разрезе как бы плеймаркета и апстора ios, это мне кажется очень немного, надо сказать, там действительно какое-то узкоспециализированное. -6362.20 6373.16 SPEAKER_00 То есть, в общем, они есть, но их как-то очень пока мало и ничего суперизвестного я там не нашел, даже, ладно, супер, уберем приставку, ничего хоть как-то известного мне я не нашел. -6373.16 6374.16 SPEAKER_00 Такие дела. -6374.16 6375.16 SPEAKER_00 Да, жалко мауи, жалко. -6375.16 6376.16 SPEAKER_01 Ну что, пойдем дальше? -6376.16 6396.36 SPEAKER_01 Я хотел еще в коротко-разном немножко упомянуть парочку докладов, потому что у нас как бы есть рубрика «Прослушано», в которой мы обсуждаем о том, о чем поговорили другие подкасты, другие люди, а свои, собственно, лекции те, которые мы курируем и делаем, мы почему-то никогда не освещаем. -6396.36 6403.28 SPEAKER_01 Мне кажется, это несправедливо, поэтому вот с сотой, сотого митапа уже, мне кажется, мы начнем это делать. -6403.28 6404.28 SPEAKER_01 О чем я говорю? -6404.28 6427.92 SPEAKER_01 Мы в том числе участвуем в группе, которая тренирует докладчиков на .NET.RU всякие митапы, в частности на SPB.NET митап, и в этом году у SPB.NET митапа случился сотый выпуск, то есть мы уже сто раз собирались, и на каждом из этих митапов читаются уникальные, классные, интересные доклады, которые авторы сами изобретают, сами исследуют, сами рассказывают, сами готовят. -6427.92 6431.40 SPEAKER_01 Именно поэтому они такие аутентичные и довольно занимательные. -6431.40 6438.88 SPEAKER_01 В частности, чтобы вы понимали, о чем я говорю, и могли бы, может быть, тоже расширить свой кругозор, если вдруг тема вам интересна. -6438.88 6448.84 SPEAKER_01 На сотом выпуске на юбилейном у нас выступил Дмитрий Нестрюк, который рассказал про разработку с использованием искусственного интеллекта, как раз то, на чемся хайпит последние годы весь мир. -6448.84 6469.20 SPEAKER_01 Вот Дмитрий проанализировал, насколько это разработчикам полезно или не полезно, как это можно использовать в своей работе, куда это движется, и, в общем, такой практически философский доклад получился на весь митап, то есть на три часа почти, с рассуждениями о том, как это можно применять и куда нужно смотреть. -6469.20 6478.60 SPEAKER_01 Дальше есть доклад, вышел за запись Евгения Пешкова, это о синхронности не только о синковой, в котором Женя как раз таки рассказала, что еще можно знать про синхронность. -6478.60 6485.68 SPEAKER_01 И если вам так же точно интересно, о чем Женя Пешков внутри про синхронность мог рассказать, то обязательно посмотрите. -6485.68 6489.64 SPEAKER_01 У него доклады всегда свежие, интересные и полны каких-нибудь новых мыслей. -6489.64 6500.20 SPEAKER_01 Станислав Сидристый у нас был с рассказом о том, как писать плагины к сервисам и как сделать безопасное расширение функциональности в нашем 21-м веке. -6500.20 6520.68 SPEAKER_01 Когда-то в свое время, мне кажется, любое приложение обязательно выпускалось с помощью плагинов, более того, если мы делали какой-нибудь DI-контейнер, который подключал компоненты, то если у такой DI-контейнера не была возможность динамически в рантайме сканить диск и находить там какие-то сборки, подключать эти сборки в виде плагинов, то это считался плохой DI-контейнер. -6520.68 6543.68 SPEAKER_01 К счастью, те времена уже довольно-таки давно прошли, плагины уже не так популярны, как раньше, то есть каждый разработчик не мечтает сделать свою плагинную систему, но все-таки плагины никуда не делись и некоторым системам их все еще делать нужно, все еще поддерживать нужно, а после того, как Microsoft обрубил поддержку апдоменов .NET Core, может быть, для некоторых неочевидно, а как же, собственно, их делать. -6543.68 6552.08 SPEAKER_01 Оказывается, есть современные техники, как делать классные, хорошие, изолированные плагины, которые хорошо в рантайме подгружаются, более того, даже выгружаются. -6552.08 6555.96 SPEAKER_01 В общем, обязательно посмотрите доклад Станислава Сидористова, если вам это интересно. -6555.96 6572.84 SPEAKER_01 Андрей Порожняков рассказывал у нас про nativeout, тот доклад, который сегодня как раз-таки уже был отрекламирован, если вам вдруг интересен nativeout, интересно, откуда он берет такую шикарную производительность относительно основного большого .NET, а также какие подводные камни с ним связаны, в общем, в докладе Андрея вы все это увидите. -6572.84 6577.20 SPEAKER_01 Дмитрий Георгов рассказывал нам про использование AWP в .NET. -6577.20 6588.76 SPEAKER_01 В общем, здесь тоже тема довольно узкая, но достаточно интересно, если аспект на ориентированное программирование тоже каким-то образом вас касается, то доклад Дмитрия расскажет вам про много вещей, о которых вы даже не знали. -6588.76 6604.68 SPEAKER_01 Александр Гальдебаев рассказывал про Aspire in Action, поэтому Aspire Aspire, если вдруг вы до сих пор не знаете, что это, как это, с чем это едят, то, наверное, самый большой и самый глубокий обзор из лекций на русскоязычном языке, который есть, представлен в этом докладе. -6604.68 6651.56 SPEAKER_01 Виктор Греков читал доклад про анализ дампов, с чего начать, поэтому если вы вдруг боитесь дампов или профайлеров, про которые мы сегодня уже не раз упоминали, не знаете, что это такое, зачем они используются и в какое место их засовывать, то вот как раз доклад Виктора продемонстрирует вам о том, что это достаточно хороший инструмент, и он удобен для, может быть, каждодневного даже использования, он удобен для того, чтобы просто посмотреть, как ваша программа работает, что в ней происходит, и в критический момент, когда настанет день ЖО, вы уже будете знать, каким образом пользоваться дампером, пользоваться профайлером, куда копать, где лезть, и вообще научитесь как профессионал использовать весь свой инструмент разработчика в таком шикарном ключе, как анализ дампов или анализ профайлеров. -6651.56 6665.76 SPEAKER_01 Я напомню, что все эти доклады можно будет найти на ютубе в группе dotnet.ru, также все ссылочки у нас будут в шоу-ноутах, поэтому заходите, смотрите, комментируйте, лайкайте, а мы будем вас знакомить с будущими докладами, которые продолжим делать. -6665.76 6691.92 SPEAKER_01 Я напомню, что митапы у нас проводятся во многих городах, в частности, в СПБ, в Санкт-Петербурге мы делаем регулярно каждый месяц, если вы вдруг будете проездом в нашей культурной столице, то посмотрите, может быть, как раз в даты вашего посещения мы будем делать очередной митап, все они бесплатные, интересные, поэтому заходите на огонек, мы всегда рады посетителям других городов, ну и если вы из Петербурга и почему-то никогда не были у нас в гостях, тоже приходите, будем рады каждому. -6691.92 6700.60 SPEAKER_00 А если вы хотите что-нибудь рассказать, то мы точно будем рады, заходите, с удовольствием поможем и дадим возможность выступить. -6700.60 6704.48 SPEAKER_01 Ну вот так хорошо и подкаст провели, да, и себя порекламировали. -6704.48 6705.48 SPEAKER_01 Да, куда ж без этого. -6705.48 6706.48 SPEAKER_01 Это все митапы. -6706.48 6726.32 SPEAKER_00 Ну да, значит, на этом мы, наверное, будем на сегодня завершать, мы попробовали сделать короткий выпуск у меня на тайминге 1 час 47, что получится после монтажа я не знаю, но больше полутора часов мы точно, видимо, получим подкаст, так что да, наши планы, как всегда, не оправдываются, но как с любыми оценками в программировании, надо умножать. -6726.32 6733.04 SPEAKER_01 Мы подкаст завершать не будем, а будем еще тренироваться и тренироваться, то есть там есть куда расти, перспективы большие. -6733.04 6780.92 SPEAKER_00 Чтобы наши оценки совпадали с реальными ситуациями к концу подкаста, но тем не менее, за сегодня мы обсудили, какие у нас бывают подходы к оптимистичным и пессимистичным блокировкам и какие, может быть, альтернативы можно рассмотреть, посмотрели, как сделать довольно низкоуровневый такой полупрофайлер, чтобы понять какие-то внутренности того, как работает в данном конкретном случае HttpClient, порассуждали на тему, что не так с дотнетом в Яндекс.Клаудфункшнз и какой подход выбрать, если вы хотите размещать там дотнет-приложения, посмотрели кратенько на Technology Radar 31 выпуск, поразбирались с тем, как тюнить запросы в EF Core с помощью интерсепторов, ну и кратенько пробежались по всяким разным мелким тулам и статьям. -6780.92 6784.56 SPEAKER_00 На этом, кажется, 105-й выпуск подошел к концу. -6784.56 6785.56 SPEAKER_01 Кажется да. -6785.56 6795.56 SPEAKER_01 В общем, всем до новых встреч, подписывайтесь на наши каналы, ставьте комментарии, там лайки, репосты, скинуться на апельсины и кефир можно на Boosty, в общем, все вы знаете. -6795.56 6796.56 SPEAKER_01 До новых встреч, пока. +0.00 11.64 "Анатолий Кулаков" Здравствуйте, уважаемые слушатели, в эфире Радио.нет и выпуск номер 105. +11.64 15.08 "Анатолий Кулаков" В студии, как всегда, постоянные ведущие – Анатолий Кулаков. +15.08 16.20 "Игорь Лабутин" И Игорь Лабутин. +16.20 17.20 "Анатолий Кулаков" Всем привет! +17.20 36.76 "Анатолий Кулаков" За нашими спинами гордые банда наших помогаторов, а именно… Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Павел, Лазарев Илья, Шевченко Антон, Ольга Бонаренко, Сергей Краснов, Константин Ушаков, Андрей Фазлеев, Дмитрий Павлов, Постарнаков Андрей, Дмитрий Сорокин и Александр Ерыгин. +36.76 39.24 "Анатолий Кулаков" Спасибо, друзья, а также всем, кто нас поддерживает. +39.24 45.08 "Анатолий Кулаков" Очень приятно иметь такую шикарную поддержку нашего творчества. +45.08 52.80 "Анатолий Кулаков" Ну что ж, прошлый выпуск у нас получился какой-то аномально огромный, постараемся больше так сильно не напрягать наших слушателей. +52.80 54.36 "Анатолий Кулаков" Постоянно жалуются на какие-то большие выпуски. +54.36 57.20 "Анатолий Кулаков" Сегодня попробуем пробежаться быстренько по темам. +57.20 62.84 "Игорь Лабутин" Да, компенсируем, сделаем сегодня маленький коротенький выпуск, но это мы сейчас вначале так говорим, посмотрим, что будет к концу. +62.84 73.56 "Игорь Лабутин" Давай-давай, пойдем, у нас новостей особо нет, ну в смысле, у Майкрософта, понятное дело, релиз вышел, новых релизов пока не было, поэтому пойдем по разным статьям. +73.56 81.24 "Анатолий Кулаков" Ну да, пока Майкрософт отдыхает, он в принципе наплодил очень много интересных фич, которые вполне могут обсуждать и другие авторы. +81.24 94.08 "Анатолий Кулаков" И вот другие авторы решили взяться за обсуждение транзакций, даже не транзакций, локов, для обсуждения локов, реализованных в Entity Framework, поэтому есть прекрасная статейка, которую мы с вами сегодня затронем. +94.08 116.20 "Анатолий Кулаков" Статейка называется "Оптимистик лок против пессимистик лок ин дотнет", в общем под названием все звучит довольно широко и оптимистично, но на самом деле кейс получился довольно-таки узкий, ну и посмотрим по дороге тогда, не хочу сейчас рассусоливать, пойдемте посмотрим что такое оптимистик и пессимистик лок в разрезе Entity Framework в нашем случае. +116.20 119.32 "Анатолий Кулаков" Итак, откуда вообще пошла проблема? +119.32 160.44 "Анатолий Кулаков" Ну как известно, не было бы никаких проблем с параллелизмом, конкуренцией, если бы у нас был всегда один поток и мы бы работали всегда в одном workflow данных, то есть раньше, наверное, когда-то так даже и было, у нас была какая-то база данных, приложение в нее писало, приложение в нее читало и все в принципе было хорошо, но потом кто-то придумал многопоточность и мы пошли писать в эту базу данных из нескольких потоков и уже база данных стала как-то немножко поднапряжней, потом кто-то придумал сервер клиент приложения и в сервер пошли писать не просто многопотоков, а еще много клиентов в многопотоков и база данных вообще могла становиться очень-очень плохо. +160.44 181.44 "Анатолий Кулаков" А база данных, как известно, это центр обычно самых главных, то есть главный источник всех данных, которые есть в приложении, в большинстве случаев это так и поэтому хочется, чтобы данные там всегда оставались консистентными и непротиворечимыми, поэтому необходимо было каким-то образом, какими-то механизмами обеспечивать непротиворечивость данных. +181.44 215.30 "Анатолий Кулаков" Противоречивость могла возникнуть, когда, опять же, несколько потоков или несколько клиентов начинают писать одни и те же данные, вот представьте у вас есть какая-то один бакет или одна строчка в таблице и один клиент пишет туда статус номер один, а второй пишет статус номер два, нечто же произойдет, а неизвестно что произойдет, в зависимости от реализации, иногда данные покарабкаться, иногда выиграет последний, а данные предыдущего клиента потеряются, в общем, может быть все что угодно, поэтому придумали механизмы борьбы с конкарнси, которые позволяют вот эту самую консистентность обеспечить. +215.30 224.50 "Анатолий Кулаков" Итак, автор утверждает, что у нас есть только два способа борьбы с конкарнси, это pessimistic log и optimistic log. +224.50 257.54 "Анатолий Кулаков" Ну, естественно, на самом деле это не так, существует огромное подможество алгоритмов, которые помогают писать одновременно в одну и ту же область данных, то есть какую-то конкарнси делать, или структур или еще чего-то, например там multiversion concurrency control, который используется в постгре, или conflict-free replicated data types, более известный как CRDT, в общем, много способов существует, кроме локов для того, чтобы работать с параллельным потоком данных, с конкурентным потоком данных. +257.54 269.50 "Анатолий Кулаков" Но локи действительно это самый, наверное, узнаваемый, примитивный и максимально используемый подход, максимально используемый механизм, поэтому как раз сосредоточимся на локах. +269.50 282.58 "Анатолий Кулаков" Итак, все примеры будут запускаться на Entity Framework, под капотом будет SQL-сервер, но в принципе это не особо важно, потому что Entity Framework обеспечивает довольно хороший такой уровень абстракции, под который вы можете зарядить любую базу данных. +282.58 285.70 "Анатолий Кулаков" В данном случае, конечно же, про реалиционно идет речь. +285.70 289.94 "Анатолий Кулаков" Итак, разберемся для начала с pessimistic lock. +289.94 296.90 "Анатолий Кулаков" Pessimistic lock - это когда несколько процессов пытаются модифицировать один и тот же ресурс параллельно. +296.90 301.34 "Анатолий Кулаков" Pessimistic lock решает эту проблему с помощью эксклюзивного доступа. +301.34 323.30 "Анатолий Кулаков" То есть он позволяет взять лок на этом ресурсе какому-то одному процессу, который пришел к нему первым, и до тех пор, пока этот лок не будет отпущен первым процессом, все остальные процессы, которые придут с претензией на взятие этого ресурса, они будут ждать в очереди и ждать, пока лок отпустится. +323.30 332.86 "Анатолий Кулаков" Как только лок отпускается первым клиентом, второй клиент берет этот лок, заходит, начинает модифицировать и все остальные ждут, пока он отпустится. +332.86 339.46 "Анатолий Кулаков" То есть, по сути, мы выстраиваем все наши параллельные процессы, все наши параллельные изменения в такую своеобразную очередь. +339.46 347.18 "Анатолий Кулаков" Но у этого подхода, кажется, все хорошо, выстроили в очередь, все стоят, все ждут своей очереди, по одному меняют. +347.18 350.78 "Анатолий Кулаков" В принципе, плюсы тут очевидны, но у этого подхода есть и минусы. +350.78 355.70 "Анатолий Кулаков" Во-первых, как только мы их начинаем выстраивать в очередь, то у нас появляется ожидание. +355.70 357.66 "Анатолий Кулаков" Таким образом, появляется замедление. +357.66 372.50 "Анатолий Кулаков" То есть программы, которые используют pessimistic lock, они обычно, у них обычно вот это место, где сосредоточен сам лок, является bottleneck, то есть они в этом месте начинают медленнее работать, потому что ждут, пока другие потоки освободят им занятый ресурс. +372.50 375.42 "Анатолий Кулаков" Другая распространенная проблема с этим алгоритмом - это deadlock. +375.42 389.74 "Анатолий Кулаков" Если вам нужно взять несколько локов на различные записи, то тут очень важно соблюдать правильный порядок, иначе можно взять локи в таком порядке, что первый и второй клиент никогда друг друга не дождутся, то есть никогда ресурс не освободят. +389.74 397.98 "Анатолий Кулаков" Таким образом, мы получаем, что в принципе алгоритм рабочий, но у него есть какие-то понятные минусы. +397.98 399.90 "Анатолий Кулаков" Как его реализовать в Entity Framework? +399.90 401.70 "Анатолий Кулаков" На самом деле, достаточно просто. +401.70 420.58 "Анатолий Кулаков" Этот подход авторы предлагают реализовать с помощью serializable isolation level в Entity Framework, то есть мы открываем транзакцию с этим уровнем доступа, запрашиваем компонент из базы данных, изменяем каким-то образом его поля, сохраняем все изменения, коммитим транзакцию, и в принципе все хорошо. +420.58 431.22 "Анатолий Кулаков" Если вдруг в этот момент пришел какой-нибудь параллельный поток, который пытается проделать все то же самое, у него выкинется exception соответствующий. +431.22 453.82 "Анатолий Кулаков" Таким образом, мы под этим уровнем транзакции можем модифицировать данные в гарантии того, что никакой другой поток, никакой другой клиент не промодифицирует те же самые куски вместе с нами, те же самые таблицы вместе с нами, и таким образом получим своеобразный пессимистик лог. +453.82 461.42 "Анатолий Кулаков" Но здесь есть небольшие, я бы даже сказал, большие проблемы, минусы у этого уровня. +461.42 470.22 "Анатолий Кулаков" Во-первых, serializable уровень может заблокировать больше записей, чем мы его попросили. +470.22 477.44 "Анатолий Кулаков" Это связано с низкоуровневой реализацией того, как база данных хранит свои записи и каким образом она ставит локи. +477.44 488.54 "Анатолий Кулаков" Также он приводит к уменьшению производительности, потому что приходится брать дополнительные какие-то расходы на поддержку такого высокого, самого мощного уровня сериализации. +488.54 494.22 "Анатолий Кулаков" И он одновременно уменьшает риск дедлоков. +494.22 499.08 "Анатолий Кулаков" В принципе, дедлоков тут может быть как-то немножко поменьше. +499.08 506.64 "Анатолий Кулаков" Данный уровень также предусматривает ручную обработку всяких эксепшенов, которые при этом могут вывалиться. +506.64 516.56 "Анатолий Кулаков" Потому что как только к вам придет второй поток, который начнет модифицировать те же самые данные, которые сейчас находятся под транзакцией, то обычно база данных выкидывает исключения. +516.56 525.48 "Анатолий Кулаков" Поэтому каждый кусок кода, который хочет использовать данный уровень транзакции, он обязан уметь обрабатывать соответствующие исключения. +525.48 529.10 "Анатолий Кулаков" И на это исключение обычно делается какой-то повтор. +529.10 531.48 "Анатолий Кулаков" Но при этом код довольно сильно усложняется, понимаете? +531.48 539.36 "Анатолий Кулаков" Потому что каждая модификация обрастает какими-то непонятными эксепшен, хендлерами, какими-то повторами, какими-то ретрайвами, еще чем-то. +539.36 545.32 "Анатолий Кулаков" В общем, код превращается в довольно-таки сложный для поддержки, для чтения. +545.32 552.08 "Анатолий Кулаков" Но на самом деле кажется, что авторы реализуют вот этот pessimistic log как-то довольно странно. +552.08 565.52 "Анатолий Кулаков" Ну потому что про их же определение pessimistic лока параллельный поток, который пришел модифицировать ожиданные, должен ожидать, пока первый закончит, а потом выстроится в очередь, а потом начать что-то свое писать. +565.52 572.96 "Анатолий Кулаков" Если мы используем уровень serializable у транзакции, то она вам выбросит исключения, никакого ожидания не будет. +572.96 581.32 "Анатолий Кулаков" И обязанность на том, чтобы подождать и снова попытаться, уже стоит на вашем приложении, что не так уж удобно, как обычный, например, pessimistic log. +581.32 585.16 "Анатолий Кулаков" Как бы вы могли в голове себе представить пессимистичный лог? +585.16 597.00 "Анатолий Кулаков" Это то, что каждый из вас, наверное, ощущает, когда вызывает стандартный кейворд в C# - log, ставит этот лог на какой-то ресурс, пишет безопасный код внутри и закрывает скоб. +597.00 598.00 "Анатолий Кулаков" Все. +598.00 601.20 "Анатолий Кулаков" Он гарантирует, что никто туда больше никогда не войдет. +601.20 609.88 "Анатолий Кулаков" Поэтому здесь нет никаких исключений, здесь нет никакой заботы о каких-то там параллельных вхождениях, еще чего-то. +609.88 612.84 "Анатолий Кулаков" В общем случае, мы просто ставим лог и забываем о всех проблемах. +612.84 614.52 "Анатолий Кулаков" Вот хотелось бы чего-то именно такого. +614.52 615.52 "Анатолий Кулаков" Здесь же нет. +615.52 626.04 "Анатолий Кулаков" Здесь какие-то появляются эксепшены, ретраи, не забыть взять, не забыть отпустить, не забыть, что может быть залочатся какие-то другие записи, которые вы не ожидаете лочить. +626.04 630.44 "Анатолий Кулаков" В общем, как-то слишком сложное решение. +630.44 635.32 "Анатолий Кулаков" Можно было бы предложить более похожее что-то на то, что мы хотим. +635.32 636.60 "Анатолий Кулаков" Это, например, advisory log. +636.60 644.12 "Анатолий Кулаков" В PostgreSQL есть такая штука как advisory log, который в принципе очень сильно похож на тот лог, который есть в C#. +644.12 647.56 "Анатолий Кулаков" Можно его взять, можно его отпустить, это буквально одна операция. +647.56 653.20 "Анатолий Кулаков" Естественно, она не поддерживается Entity Framework, поэтому вам ее нужно как-то реализовать кастомно, но реализуется она довольно просто. +653.20 657.48 "Анатолий Кулаков" И в интернете полно уже схем, как это сделать. +657.48 660.64 "Анатолий Кулаков" Другой подход - это, например, можно сделать select for update. +660.64 669.44 "Анатолий Кулаков" Если вам нужен какой-то пессимистичный лог в рамках довольно понятного и ограниченного количества данных, то может быть select for update вам подойдет еще даже больше. +669.44 674.68 "Анатолий Кулаков" Можно еще сделать пессимистичный лог с помощью ручной таблицы. +674.68 677.64 "Анатолий Кулаков" То есть у вас есть таблица, в которой вы записываете логи. +677.64 685.36 "Анатолий Кулаков" И когда вы берете лог, вы в этой таблице делаете update и говорите, что я вот такой вот обработчик, такой вот хендлер взял лог. +685.36 690.84 "Анатолий Кулаков" И все другие клиенты, которые к вам приходят, они должны сначала update в этой таблице смочь сделать. +690.84 692.64 "Анатолий Кулаков" Если не могут сделать, значит ждут. +692.64 696.08 "Анатолий Кулаков" Если могут, значит запись свободна и пошли дальше модифицировать. +696.08 697.32 "Анатолий Кулаков" Такие тоже вещи существуют. +697.32 701.36 "Анатолий Кулаков" В общем, способов сделать пессимистичный лог их довольно таки много. +701.36 706.20 "Анатолий Кулаков" И serializable isolation level, наверное, не самый первый, который мне пришел бы в голову. +706.20 708.46 "Анатолий Кулаков" В общем, непонятно, почему авторы сюда полезли. +708.46 710.32 "Анатолий Кулаков" Но, в общем, это так. +710.32 713.56 "Анатолий Кулаков" Итак, с пессимистичным логом мы разобрались. +713.56 719.40 "Анатолий Кулаков" То есть это лог, который сначала ставится на ресурс, потом ресурс модифицируется и после этого лог отпускается. +719.40 723.76 "Анатолий Кулаков" Его проблемы как раз таки в основном в том, что он оказывается bottleneck. +723.76 728.56 "Анатолий Кулаков" То есть пока ресурс модифицируется, то есть под логом может быть не только модификация ресурсов. +728.56 734.16 "Анатолий Кулаков" Например, сама модификация ресурсов довольно таки может быть и быстрой, но обычно под лог засовывают чего-то еще. +734.16 740.88 "Анатолий Кулаков" Ну, например, загрузить данные, проверить эти данные, проанализировать, что это те данные, которые нам нужны. +740.88 750.40 "Анатолий Кулаков" Взять новый модификатор, заапдейтить данные, потом может быть запустить какой-то верификатор, потом может еще что-то сделать. +750.40 754.76 "Анатолий Кулаков" В общем, и вот эти дополнительные накладные расходы, на которых в принципе лог-то на самом деле и не нужен был. +754.76 756.48 "Анатолий Кулаков" Лог нужен был только на сам апдейт записи. +756.48 762.64 "Анатолий Кулаков" И вот они приводят к вот этим дополнительным расходам, которые возникают при пессимистичных логах. +762.64 765.64 "Анатолий Кулаков" Этих минусов более-менее лишен оптимистичный лог. +765.64 771.40 "Анатолий Кулаков" Вместо того, чтобы брать лог на ресурс, пессимистичный лог делает другую штуку. +771.40 779.76 "Анатолий Кулаков" Он во время сохранения самой записи определяет, а была ли версия записи, которую мы сохраняем, точно такая же, которая лежит в базе данных. +779.76 787.48 "Анатолий Кулаков" Ну то есть, по факту, не успел ли кто-то другой модифицировать ее, пока мы что-то там, какую-то магию с ней творили, каким-то образом ее изменяли. +787.48 798.36 "Анатолий Кулаков" И если вдруг система детектирует, что да, запись в этот момент поменялась, она только в этот момент выбрасывает исключение, что типа, чувак, давай сделать что-нибудь другое, твоя запись была изменена. +798.36 811.20 "Анатолий Кулаков" Но если никаких конфликтов других не было, ну то есть параллельно никто эту запись изменить не смог, то транзакция проходит практически с той же скоростью, с теми же накладными расходами, которые были бы и абсолютно без нее. +811.20 813.24 "Анатолий Кулаков" Это безусловный плюс оптимистик логов. +813.24 816.16 "Анатолий Кулаков" Теперь давайте же разберемся, каким образом их реализовать в Entity Framework. +816.16 820.36 "Анатолий Кулаков" Во-первых, нам понадобится дополнительная колонка, которая обозначает версию. +820.36 831.08 "Анатолий Кулаков" Глядя на эту колонку, Entity Framework будет сам трекать то, какой версии данные были закружены, то, какой версии данные сейчас сохраняются в базу данных и сам будет каким-то образом на это реагировать. +831.08 836.84 "Анатолий Кулаков" То есть с каждой записью, которую вы считаете с базы данных, он плюс считает вот эту колонку с версией. +836.84 846.92 "Анатолий Кулаков" Для того, чтобы это сделать, вам необходимо в вашу модельку добавить новое полик, который называется, допустим, Raw Virgin, и навесить на него специальный Entity Framework атрибут, который называется Timestamp. +846.92 857.88 "Анатолий Кулаков" Это специальный атрибут, который рассказывает Entity Framework как раз таки, что и нужно включить автоматическую обработку concurrency-чеков, и она начинает автоматически это делать. +857.88 863.28 "Анатолий Кулаков" Безусловно, можно это сделать не с помощью Attribute, а с помощью Fluent API, но смысл остается тот же самый. +863.28 867.52 "Анатолий Кулаков" Что произойдет, например, если вдруг у вас выполняется метод. +867.52 868.52 "Анатолий Кулаков" Как вы можете это симулировать? +868.52 878.88 "Анатолий Кулаков" Например, перед изменением своей записи, вы сначала запись загружаете в память, в это время загружается, естественно, вместе с вашей Entity и версия. +878.88 886.36 "Анатолий Кулаков" Затем можно выполнить сырой запрос, для того, чтобы Entity Framework его не заметил, который обновляет эти данные, которые хранятся в вашей базе данных. +886.36 892.16 "Анатолий Кулаков" После этого вы меняете у своей Entity необходимые вам поля и пытаетесь сохранить. +892.16 906.00 "Анатолий Кулаков" В данный момент вы получите db_update_concurrency_exception, Entity Framework сам узнает, то есть определит вот этот конфликт, что у вас теперь raw_version поменялось, и выбросит вам exception. +906.00 909.60 "Анатолий Кулаков" В этот момент вы должны подумать, что с этим exception вам делать. +909.60 911.68 "Анатолий Кулаков" В большинстве случаев вы хотите просто-напросто заретраиться. +911.68 929.16 "Анатолий Кулаков" Если же вы хотите не такой большой магии по контролированию вот этого поля version, то есть у нас Entity Framework сам его загружает, сам его при сохранении проверяет, сам его инкрементирует, если уже не было конфликтов, в общем, это он делает все сам. +929.16 939.44 "Анатолий Кулаков" Если вы хотите более ручное управление, более гибкое управление, то существует небольшая альтернатива нашему таймстэмпу, который называется Concurrency Check. +939.44 947.88 "Анатолий Кулаков" Этот атрибут точно также нужно нацепить над каким-нибудь новым полем типа version и можете дальше использовать его абсолютно так же, как и при ведущем варианте. +947.88 952.00 "Анатолий Кулаков" С одним единственным исключением, Entity Framework не будет вам это поле автоматически инкрементировать. +952.00 959.20 "Анатолий Кулаков" Если вы хотите сказать, сообщить, что версия вашей Entity поменялась, значит, вы должны это сказать вручную, сообщить вручную. +959.20 965.44 "Анатолий Кулаков" И если вдруг он обнаружит конфликт, то у вас будет точно такой же db.concurrency.exception. +965.44 975.88 "Анатолий Кулаков" Нужно сказать, что при этом, если у вас включены логики Entity Framework, то там подробно будет описано, какой SQL-запрос это преобразуется, какой конфликт был вызван, почему был вызван. +975.88 983.12 "Анатолий Кулаков" Поэтому в логах много всего пишется, если вы хотите, то отладку обязательно включите для того, чтобы посмотреть, что там, собственно, происходит под капотом. +983.12 984.96 "Анатолий Кулаков" Вот таких есть два подхода. +984.96 1000.08 "Анатолий Кулаков" Опять же, к optimistic log у меня тоже есть большие вопросы, потому что реализация, то есть мы никак не можем работать с optimistic логом, кроме эксцепшенов в Entity Framework. +1000.08 1001.08 "Анатолий Кулаков" И это довольно-таки плохо. +1001.08 1009.72 "Анатолий Кулаков" Потому что любой человек, который хоть раз в жизни в SQL реализовал optimistic логи на чистом SQL, он, естественно, никакие эксцепшены не бросает и ничего не делает. +1009.72 1011.88 "Анатолий Кулаков" Как реализуется нормальный optimistic лог? +1011.88 1017.76 "Анатолий Кулаков" Вы обновляете запись и в апдейте пишите условие vaversion = 1. +1017.76 1028.76 "Анатолий Кулаков" Таким образом, когда вы обновляете эту запись и запись в базе данных находится под версией 1, у вас количество измененных элементов будет 1. +1028.76 1036.76 "Анатолий Кулаков" Если же вы обновляете запись и в это время уже параллельный поток какой-то увеличил эту версию, то количество измененных элементов будет 0. +1036.76 1046.64 "Анатолий Кулаков" Таким образом, анализируя количество измененных элементов после вот этого апдейта, вы можете определить, была ли успешна ваша optimistic транзакция, даже не транзакция, а апдейт. +1046.64 1047.64 "Анатолий Кулаков" Оптимистик апдейт. +1047.64 1049.40 "Анатолий Кулаков" Был ли он успешен или неуспешен. +1049.40 1056.40 "Анатолий Кулаков" Таким образом, просто-напросто вернув количество измененных записей, можно, анализируя это количество, обойтись без всяких эксцепшенов. +1056.40 1063.24 "Анатолий Кулаков" Можно просто сделать нормальный анализ и немножко сэкономить себе там перформансы и удобства, не используя эксцепшены. +1063.24 1069.72 "Анатолий Кулаков" В Entity Framework такой штуки очень долго не было, потому что как раз-таки не было апдейта с условиями. +1069.72 1080.20 "Анатолий Кулаков" Недавно появился апдейт, в который мы можем вставить where, то есть, по сути, вставить условия, и вы можете сделать свой нормальный оптимистик апдейт теперь без всяких эксцепшенов. +1080.20 1083.92 "Анатолий Кулаков" Почему-то, опять же, в никаких примерах этого не сообщают, не дают. +1083.92 1087.12 "Анатолий Кулаков" И говорят нам, что мы обязаны сидеть на каких-то только db-конкуренции эксцепшенах. +1087.12 1095.72 "Анатолий Кулаков" В общем, если вы не любите эксцепшены, то вот это тоже подход очень хороший, и он работает, и, в принципе, сейчас его в EFI можно легко заиспользовать. +1095.72 1098.40 "Анатолий Кулаков" Ну и так, с чем же мы пришли? +1098.40 1100.88 "Анатолий Кулаков" У нас есть, в принципе, три варианта. +1100.88 1103.04 "Анатолий Кулаков" Один пессимистик и два оптимистик лока. +1103.04 1106.12 "Анатолий Кулаков" Посмотрим же, кто из них лучше и кого нужно использовать. +1106.12 1109.16 "Анатолий Кулаков" Ну, на самом деле, нет однозначного ответа, как всегда. +1109.16 1121.96 "Анатолий Кулаков" Все зависит от вашего способа, от того, насколько часто у вас конфликты, какой у вас большой уровень конкуренции, от перформанса вашего приложения и прочих таких факторов. +1121.96 1130.80 "Анатолий Кулаков" Например, пессимистик лок, наверное, хорош, потому что он может работать без образования конфликтов. +1130.80 1134.16 "Анатолий Кулаков" То есть никаких у вас, по сути, конфликтов в данных не будет. +1134.16 1141.48 "Анатолий Кулаков" Все апдейтеры будут выстраиваться в очередь, а когда есть очередь, писатель получается по факту один, и конфликтов нет. +1141.48 1142.48 "Анатолий Кулаков" Это бесспорный плюс пессимистик локов. +1142.48 1153.60 "Анатолий Кулаков" Также он, если он реализован, допустим, с помощью каких-то механизмов, которые позволяют затронуть вам несколько записей. +1153.60 1161.52 "Анатолий Кулаков" То есть не одну версию в одной сущности вам нужно поменять, а в вашей транзакции, допустим, участвуют несколько таблиц. +1161.52 1164.98 "Анатолий Кулаков" В общем, здесь тоже пессимистик лок, в принципе, довольно хорошо себя показывает. +1164.98 1172.44 "Анатолий Кулаков" Из минусов – это образование bottle neck, то есть то место, где стоит ваша очередь, оно как раз будет тормозить во всем вашем приложении. +1172.44 1175.64 "Анатолий Кулаков" Ну и, возможно, дедлоков, куда же без этого. +1175.64 1180.84 "Анатолий Кулаков" Оптимистик локи в плане минусов намного лучше, потому что у них есть свои проблемы. +1180.84 1188.20 "Анатолий Кулаков" Если брать оптимистик лок, то безусловным его плюсом является в том, что нет никакой блокировки. +1188.20 1194.92 "Анатолий Кулаков" В лучшем случае вы пройдете обновление, даже не заметив его, в худшем случае у вас будет ретрай. +1194.92 1199.32 "Анатолий Кулаков" Поэтому при большой конкурентности данный способ более предпочтителен. +1199.32 1210.60 "Анатолий Кулаков" Если мы берем вариант с raw version, то здесь Entity Framework на себя полностью берет автоверсионирование, то есть слежка за версией, закачивание версии, модификация версии. +1210.60 1213.36 "Анатолий Кулаков" Все это берет на себя Entity Framework, что достаточно таки удобно. +1213.36 1219.72 "Анатолий Кулаков" Из минусов у вас могут возникнуть конфликты, и вам нужно думать, как эти конфликты обработать. +1219.72 1222.72 "Анатолий Кулаков" Не всегда повтор – это самое лучшее решение. +1222.72 1225.36 "Анатолий Кулаков" Тут зависит уже конкретно от вашего кейса. +1225.36 1231.64 "Анатолий Кулаков" И из минусов, если вы неправильно обработаете конфликт, вы можете потерять данные, что тоже в предыдущем случае было бы невозможно. +1231.64 1238.68 "Анатолий Кулаков" Это тоже такой очень большой минус оптимистик лока, которым приходится расплачиваться за производительность. +1238.68 1251.32 "Анатолий Кулаков" И оптимистик лок с concurrency токеном, в принципе, наследует все плюсы оптимистик лока, но плюсы, и также дополнительным плюсом он дает вам более гибкое управление версиями. +1251.32 1266.28 "Анатолий Кулаков" Очень сложно придумать, зачем это могло бы пригодиться на практике, но, наверное, если у вас какая-то изощренная система типа совместного онлайн-редактирования одного документа несколькими пользователями или что-то в этом духе, то, наверное, ручное управление вам зачем-то может быть нужно. +1266.28 1274.32 "Анатолий Кулаков" Ну и из минусов, конфликты вы точно также должны управлять вручную и каким-то образом их разруливать. +1274.32 1297.08 "Анатолий Кулаков" Такой небольшой обзорчик, в принципе, мы так кратко с верхнего уровня познакомились, как это реализовано в Entity Framework и что с этим можно сделать, но, в принципе, держите в уме, что реализации оптимистик и пессимистик лока можно сделать на SQL и на Entity Framework гораздо больше и они будут обладать более такими гибкими и удобными свойствами, чем те, которые представлены в статье. +1297.08 1323.32 "Игорь Лабутин" Вообще, в общем, полезно изучать те инструменты, с которыми вы работаете, не думать, что Entity Framework все решит за вас, хотя, не знаю, 90%, наверное, проблема, если не 95% для некоторых проектов он решает, но для тех самых оставшихся 5% или 10% нужно действительно хорошо знать, за какими инструментами пойти в базу быть той адвайзери локи или еще что-нибудь и в каких ситуациях что нужно применять, а тут… +1323.32 1349.72 "Анатолий Кулаков" Наверное, смотри, этим как раз и отличается хороший программист от плохого, потому что плохой он остановится где-то на уровне Entity Framework и не понимая то, как работает SQL, что там происходит под капотом, он сильно много хорошего сделать не сможет, а хороший программист он всегда понимает на уровень дальше, т.е. он знает, как работает SQL, он знает, что от него ожидать, он знает, каким образом на чистом SQL реализовать те или иные паттерны и тогда он их сможет грамотно использовать в высокоуровневом фреймворке. +1349.72 1367.08 "Игорь Лабутин" Я тут даже, наверное, сказал не хороший-плохой, а скорее опытный и неопытный, т.е. ты можешь быть хорошим, но пока еще неопытным программистом, но вот когда ты обретешь этот опыт работы напрямую с SQL, понимание, когда какой лок применить, ты хотя бы в этой части становишься уже опытным. +1367.08 1373.16 "Анатолий Кулаков" Согласен, да, но просто тебе нужно хотеть этот опыт обрести, тебе не нужно останавливаться на этом уровне. +1373.16 1374.16 "Игорь Лабутин" Это правда. +1374.16 1388.00 "Игорь Лабутин" Ну давайте будем становиться более опытными программистами в разных областях и погрузимся в ту часть, в которую мы на самом деле довольно давно не ныряли, а именно ивенты, ETV, dotnet monitor и вот это вот все. +1388.00 1457.68 "Игорь Лабутин" Потому что вышла статья Кристофа Назаре, а как вы знаете, эта фамилия обычно ассоциируется со всякими низкоуровневыми штуками, профайлерами, garbage-коллектором и прочим таким интересным контентом, и он не подвел в этот раз, он написал toolzoo, toolzoo называется dotnet.txt, это такой очень кастомный command-line профайлер, который выполняет довольно узкую задачу, а именно он берет ваше приложение и пока оно работает, он логирует на каждый внешний вызов вашего приложения, что произошло, ну в смысле что произошло, на какой уровень мы сходили, какой был код ответа, но это все неинтересно и в общем-то это вы можете узнать какими-то другими способами, а вот что более интересно, это внутрянка дотнета, а именно сколько времени потратилось на DNS, сколько времени потратилось на установление соединений, сколько времени потратилось на любые security штуки, там tls-handshake, либо еще что-то, и возможно сколько времени потратилось на всякие редиректы до тех пор, пока мы собственно не начали качать непосредственно контент того, чего вы там запрашивали, а что-то по клиентам. +1457.68 1473.52 "Игорь Лабутин" Это может быть полезно для понимания, где ваше приложение тормозит, если, например, вы видите по какой-то статистике, там не знаю, в каких-нибудь графаниях, в каких-нибудь трейсах, что почему-то внешние вызовы выполняются долго, и вам нужно понять, что там происходит более точно. +1473.52 1492.64 "Игорь Лабутин" Но сама статья, она не про то, зачем вам это может быть надо, а про то, как это реализовать, и это, конечно же, как обычно, для программистов наиболее интересная часть, потому что вот это все, почему там и так далее, это может быть скучновато, а вот как это работает внутри, это может быть интересно, особенно в контексте нашего подкаста, где мы в том числе рассказываем, как это все устроено. +1492.64 1503.08 "Игорь Лабутин" Итак, надо вспомнить, что и Runtime, и BaseClassLibrary, и PCL, они генерят довольно большое количество ивентов. +1503.08 1519.56 "Игорь Лабутин" Ивенты эти генерятся разными способами, у нас есть механизм ETV, Event Tracing for Windows, у нас есть механизм просто ивентов, которые потом вы можете, они кросс-платформенные, можно словить дотнет-монитором, например, и посмотреть на них. +1519.56 1540.08 "Игорь Лабутин" И если вы посмотрите в документацию Microsoft, то там будет написано довольно много разных ивентов, в статье у Кристофа приведены эти ссылочки, но там просто написано, что, мол, когда HTTP-реквест начинается, эмитится вот такой-то ивент, а когда HTTP-реквест заканчивается, эмитится вот такой-то ивент, в смысле названия. +1540.08 1558.56 "Игорь Лабутин" Но, таким образом, вы можете понять, сколько это тот же самый HTTP-реквест длился, но нет никакого описания о какой payload у этих ивентов, и поэтому понять, собственно, что был за URL в этом HTTP-реквесте, это на самом деле требует некоторого исследования. +1558.56 1566.12 "Игорь Лабутин" Поэтому первая часть — это то, как понять, о какой вообще payload у этих ивентов, ну, благо дотнет у нас сейчас кросс-платформенный, поэтому надо смотреть в код. +1566.12 1585.56 "Игорь Лабутин" И в коде мы можем заметить, что все классы, ну или по крайней мере те, которые нас сейчас интересуют для той области в сетевом стеке, которые нас сейчас интересуют, для того, чтобы имитить эти ивенты, они все наследуются от класса EventSource и имеют суффикс телеметрии. +1585.56 1587.88 "Игорь Лабутин" Это очень удобно для поиска. +1587.88 1602.72 "Игорь Лабутин" Дальше можно убедиться, что, как и положено по документации, все они декорированы атрибутом EventSource, в котором написано то самое имя провайдера, который вы можете найти в документации, и GUID, который нам там может чуть позднее понадобиться. +1602.72 1613.60 "Игорь Лабутин" Также там есть публичные методы, которые используются для того, чтобы вызывать генерацию этих ивентов, но в публичных методах ничего интересного нет, потому что они делегируют свою работу приватным методом. +1613.60 1633.16 "Игорь Лабутин" А приватные методы, они делегируют все это в метод writeEvent обычно, который внутри как раз собирает структурку под названием eventData, дополняет ее нужными полями, и после этого вызывает уже writeEventCore, это из базового класса из EventSource, который, собственно, и пишет все, что нужно. +1633.16 1644.96 "Игорь Лабутин" И вот как раз, если посмотреть в эти writeEvent методы, которые потом вызовут writeEventCore, то можно посмотреть, что же складывается в eventData. +1644.96 1660.40 "Игорь Лабутин" Кристоф это, соответственно, сделал, для нужных нам ивентов описал в табличках, где нам искать урлы, где нам искать там то, сё, пятое, десятое, поэтому я прям сейчас не буду перечислять, понятное дело, бинарный payload того, как это все там разложено, не так это сейчас принципиально. +1660.40 1683.68 "Игорь Лабутин" Важно то, что если вам вдруг зачем-то, вы знаете, что о, мою проблему можно решить, посмотрев, возможно, на нужные какие-то ивенты от BCL или Runtime, но вы нигде не можете найти описание, какие же там данные, можно просто посмотреть в код, вот таким способом найти вызовы writeEventCore, найти перед этим, как собирается eventData и узнать, что же там лежит. +1683.68 1698.80 "Игорь Лабутин" Понятно, что это может быть немножко непереносимо, понятно, что это может меняться с версиями, но в конце концов вы же отложите проблему вашу конкретно на конкретном дотнете, а не пишете универсальный тул для всего, ну и скорее всего, признаться, вряд ли они будут сильно меняться со временем. +1698.80 1708.72 "Игорь Лабутин" Итак, ну мы поняли, какие ивенты нам нужны, мы примерно поняли, что в них лежит, теперь надо понять, как этим всем работать, профайлер-то надо написать, чтобы он всё это слушал. +1708.72 1728.48 "Игорь Лабутин" Для этого делаем следующее, у нас есть nuget-пакет, который называется TraceEvent, а также есть еще nuget-пакет Microsoft Diagnostics NetCore Client, который позволяет, там есть класс под названием EventPipeClient, который позволяет подключиться к приложению и послушать все эти ивенты. +1728.48 1736.32 "Игорь Лабутин" Напомню, что они все через пайпы для кроссплатформенности засылаются в клиента. +1736.32 1767.80 "Игорь Лабутин" Дальше вы создаете SessionConfiguration, передаете список провайдеров, вызываете CollectTracing метод, он, собственно, стартует трейсинг и возвращает вам некий ридер, но ридер он бинарный, то есть это просто бинарный протокол, вы просто получите бинарный поток данных, который не очень интересно читать, точнее, читать-то может интересно, но неудобно разбирать и работать с ним практически, поэтому для этого вам нужен еще EventPipeEventSource класс, которым передается этот ридер, и оттуда вы уже получаете нормальные объекты. +1767.80 1772.00 "Игорь Лабутин" Ну как получаете, на них надо подписаться, но сейчас об этом чуть позднее. +1772.00 1780.36 "Игорь Лабутин" Для того, чтобы создать сессию, вам нужно туда передать список провайдеров, значит, что такое провайдеры? +1780.36 1797.16 "Игорь Лабутин" Провайдеры - это те самые имена или гуиды провайдеров, кого вы хотите слушать, потому что можно, конечно, передать и слушать все, но это будут, ну если не миллионы, то тысячи ивентов, и зачем вам это, если вы точно знаете, какие вам нужны? +1797.16 1836.24 "Игорь Лабутин" Вы вроде выяснили, что нам нужны там провайдеры из namespace.system.net.что-нибудь, ну там DNS, security, там их несколько в статье перечислены, все они будут перечислять, но если их добавить, то вы на самом деле не получите идеальной картинки, потому что вам будут приходить, допустим, HTTP request started, HTTP request stopped, но у нас же приложение многопоточное, как мы говорили при обсуждении прошлой статьи, и много параллельных внешних запросов могут быть, то есть ваши несколько там обработчиков ваших запросов могут одновременно отправлять запросы на внешние сервисы. +1836.24 1849.04 "Игорь Лабутин" И связать события про то, что request started и request stopped на самом деле не так просто, учитывая то, что у нас весь стэк асинхронный, как правило, это все может приходить из совершенно разных потоков, и как-то это нужно связывать. +1849.04 1856.00 "Игорь Лабутин" Для того, чтобы это все связывать в event вот этой инфраструктуре, существует понятие activity_id. +1856.00 1865.40 "Игорь Лабутин" Activity_id это некоторая строчка на самом деле, ну то есть точнее это на самом деле число, но вы можете ее считать строчкой. +1865.40 1869.32 "Игорь Лабутин" Я, кстати, не помню, как она в апишке выглядит, event source. +1869.32 1875.40 "Игорь Лабутин" В perfu просто это строчка обычно, ну допустим, в общем, потому что их в дерево можно объединять в итоге, потому что там собирается строка. +1875.40 1887.92 "Игорь Лабутин" Но по-моему все-таки activity_id это число, которое как раз навешивается при старте и стопе событий, которые связаны друг с другом, и для этого оно прокидывается везде. +1887.92 1900.44 "Игорь Лабутин" Но вот для того, чтобы оно все работало и все правильно прокидывалось, внезапно нужно еще в провайдере обязательно подписаться на специальный System Tracing Tasks TPL Event Source. +1900.44 1907.84 "Игорь Лабутин" Вот если вы на него подпишетесь, даже если вы не будете слушать ничего, у вас будет корректный activity_id везде. +1907.84 1909.52 "Игорь Лабутин" Вот такая вот особенность. +1909.52 1913.40 "Игорь Лабутин" Видимо считается, что если вам таски не нужны, то и activity_id вам не нужно. +1913.40 1920.44 "Игорь Лабутин" А так вы получите правильный activity_id из тасочков, из нужного провайдера. +1920.44 1943.20 "Игорь Лабутин" После того, как вы все это сделаете, дальше вы у этого event source говорите "хочу подписаться", можно подписываться на какие-то суперспецифичные штуки, но как правило проще всего подписаться на событие all_events, просто стандартная синтаксис mc# подписки, там source.all_events+=on_events. +1943.20 1953.32 "Игорь Лабутин" Внутри on_events вы будете получать событие, когда приходит любой из ивентов из тех провайдеров, на которые вы подписались. +1953.32 1969.12 "Игорь Лабутин" Но для того, чтобы дальше разобраться, а что это за ивент, потому что там же бинарный payload, и в on_event вам приходят в общем-то только некоторые метаинформации и бинарный payload этого ивента, вам нужно понять откуда этот ивент. +1969.12 1971.48 "Игорь Лабутин" И вот именно тут пригодятся гуиды. +1971.48 1994.60 "Игорь Лабутин" Вам нужно для… в классах провайдера вам нужно будет эти самые гуиды сравнивать, то есть вы берете… имени не приходят в ивенте, насколько я помню, приходят только гуиды провайдера, поэтому вы у каждого провайдера, который вы перечислили, спрашиваете гуид и сравниваете его с тем гуидом в ивенте, который пришел. +1994.60 1999.32 "Игорь Лабутин" И как только вы нашли совпадение, значит это ваш ивент, который вы ждете. +1999.32 2013.72 "Игорь Лабутин" Точнее, не то, что ваш, вы понимаете, от какого провайдера пришел гуид, вы понимаете какой это ивент, ну потому что ивент-код там есть, и тогда вы можете разобрать наконец-таки payload бинарный, децерализовать его и что-то с ним сделать. +2013.72 2021.16 "Игорь Лабутин" Например, посчитать те самые дельты по времени, сколько у нас занял DNS-запрос, сколько заняла security, вот это все. +2021.16 2058.92 "Игорь Лабутин" Такая вот история, то есть если вдруг вы думаете или вы уверены, что вы хотите попробовать какую-то вашу внутреннюю кухню, то есть вы видите какое-то странное поведение и вы по ивентам не хотите лазать по какому-нибудь перфью или еще что-нибудь в таком духе и хотите получить совсем супер детальную диагностику, то вы можете реализовать эту конструкцию, причем в принципе слушать можно же и внутри самого приложения, самого себя, вам никто не мешает прямо внутри приложения встроить такую диагностику самого себя, слушать это все и репортить наружу, например в виде каких-нибудь прометеусовских метрик. +2058.92 2069.88 "Игорь Лабутин" И тогда будет видно, что например у вас там тормозит, ну допустим, DNS или еще что-нибудь. +2069.88 2090.12 "Игорь Лабутин" Теперь вот есть такой достаточно понятная, хорошо написанная статья, которая позволит вам легко это сделать либо в своем приложении, либо в стороннем, либо взять просто готовый tool, он инсталится как global tool, как обычно это делается через command line и можно им пользоваться, благо что он command line и поэтому по идее он работает даже внутри контейнера, если очень интересно. +2090.12 2091.12 "Игорь Лабутин" Такие дела. +2091.12 2105.72 "Анатолий Кулаков" Слушай, полезная штука, мне кажется, что она еще больше станет полезной, если ее включат в какой-нибудь стандартный профайлер, который там все пользуются, и чтобы она показывала вот эти все вещи, которые происходят именно в совокупности с другим вашим приложением. +2105.72 2113.20 "Анатолий Кулаков" Потому что иногда, да, очень часто вот это место может быть bottleneck и не всегда понятно, что же там происходит внутри одного запроса. +2113.20 2135.52 "Игорь Лабутин" Ну вот я так понимаю, что таких супер детальных метрик можно напридумывать огромное количество, благо этих провайдеров там сотни, как я понимаю, ну ивентов как минимум точно, хотя по-моему провайдеров там за сотню точно, и я боюсь, что если мы начнем это все запихивать в профайлер какой-нибудь, то получится это. +2135.52 2140.96 "Игорь Лабутин" Ты Perf.U видел, да, скрин такой с миллионом галочек, эдитбоксов и прочего. +2140.96 2143.36 "Игорь Лабутин" То есть это будет какой-то очень сложный инженерный тул. +2143.36 2153.20 "Игорь Лабутин" Я не говорю, что они не нужны, и наверное, например, если мы говорим про Perf.U, если вы под виндой, то на Perf.U существует возможность сделать кастом вьюшки так называемые. +2153.20 2163.24 "Игорь Лабутин" То есть вы можете напрограммировать длл, которую Perf.U будет уметь загружать, скармливать ей, собственно, трейс этих ивентов этой вьюшки, а вьюшка может выводить, что хочет. +2163.24 2166.92 "Игорь Лабутин" То есть технически можно сделать такую вьюшку даже прям на базе Perf.U. +2166.92 2191.36 "Игорь Лабутин" Я никогда не пробовал такое делать, но вроде бы видел, что такое делают, вроде там есть какое-то extensibility, и соответственно это можно сделать на Perf.U, но Perf.U довольно ограниченный, в том смысле, что на Windows Only, и видимо поэтому Кристоф решил сделать это в виде такого отдельного онлайн-тула, которое причем на живую, прям на работающем приложении позволяет это делать. +2191.36 2198.60 "Анатолий Кулаков" Ну, ты прав, если там все навалить как в Perf.U, наверное, это будет неюзабельно, в общем случае, по крайней мере. +2198.60 2214.88 "Анатолий Кулаков" Но если сюда подключить какой-нибудь разум, который все-таки будет тебе данные места группировать, и если вдруг они будут выбиваться по статистике из нормального там какого-нибудь распределения, то есть если будет видно, что они занимают существенное время или выполняются дольше, чем обычно, вот тогда их детализировать уметь. +2214.88 2220.12 "Анатолий Кулаков" Ну, без того, чтобы залезть в детали, он бы тебе просто показал как обычные запросы, и все. +2220.12 2234.72 "Игорь Лабутин" Ну, наверное, может быть, когда-нибудь это в трейсинг куда-нибудь влезет, то есть можно, допустим, будет включить опцию, у нас же сейчас уже спаны для всяких внешних вызовов отправляются нормально через OpenTelemetry, поставить галочку, и он тогда тебе будет это бить на микроспаны. +2234.72 2240.12 "Игорь Лабутин" Типа вот тут я сходил в DNS, тут я в Security, тут Connection, а тут, значит, вот он ушел, ушел наконец-таки наружу. +2240.12 2242.12 "Игорь Лабутин" Может быть так. +2242.12 2245.44 "Анатолий Кулаков" Ну, хорошо, хорошо, пойдем к следующей теме. +2245.44 2249.76 "Анатолий Кулаков" Хочется поговорить с вами о том, что не так с Яндекс.Клаудфанкшнами. +2249.76 2252.64 "Анатолий Кулаков" Вот прям нормальная такая статья, прям сразу с наезда. +2252.64 2257.68 "Анатолий Кулаков" Сразу видно, что автор опубликовал статью на Хабре, и это Андрей Порожняков. +2257.68 2272.56 "Анатолий Кулаков" Андрей Порожняков рассказывает нам, как он попробовал Клаудфанкшены, и, в принципе, статья в основном не про Клаудфанкшены, а статья про NativeOut, поэтому если вам интересен NativeOut, а особенно как запустить его в Клаудфанкшенсах, то милости просим. +2272.56 2278.36 "Анатолий Кулаков" Давайте немножко посмотрим на тот опыт, который возник у автора, тем более, что в некоторых местах он довольно-таки уникальный. +2278.36 2286.72 "Анатолий Кулаков" Итак, как я уже сказал, Андрей решил в Клаудфанкшен запустить .NET и посмотреть, а что ж там такого с ними интересного происходит. +2286.72 2289.28 "Анатолий Кулаков" Что такое функции, прежде всего? +2289.28 2298.72 "Анатолий Кулаков" Ну, это функция как услуга, это один из компонентов без серверных вычислений, да, все мы на слуху уже давно имеем у себя Serverless какие-то вычисления, Serverless-функции. +2298.72 2305.12 "Анатолий Кулаков" На самом деле это не тогда, когда у вас нет сервера, это тогда, когда вы просто об этом сервере не заботитесь, а о нем заботится кто-то другой. +2305.12 2314.28 "Анатолий Кулаков" То есть ваша функция лежит на сервере и в этой функции описано на обычном C# коде то, что она должна делать. +2314.28 2316.60 "Анатолий Кулаков" Запускается эта функция по неким событиям. +2316.60 2320.36 "Анатолий Кулаков" Событиями могут быть все, что угодно, то есть очень много разных событий есть. +2320.36 2327.64 "Анатолий Кулаков" Самым частым из них это HTTP-запрос, то есть если на какой-то определенный уровень приходит HTTP-запрос, то запускается ваша функция. +2327.64 2337.24 "Анатолий Кулаков" Безусловно, она может проанализировать какие аргументы перед вашим HTTP-запросом и прочее-прочее, но не сильно отличается от ваших контроллеров, допустим. +2337.24 2341.44 "Анатолий Кулаков" Может быть не такая навороченная, но в целом именно вид именно такой. +2341.44 2350.64 "Анатолий Кулаков" А также событиями могут выступать какой-нибудь планировщик, который по времени запускает эту функцию или появление задачи в очереди задач, в какой-нибудь queue. +2350.64 2356.88 "Анатолий Кулаков" Если задача появилась, то эта задача тоже может обрабатываться с помощью такой же в Cloud Function. +2356.88 2363.64 "Анатолий Кулаков" Плюсы здесь в основном в том, что вам не нужно держать постоянно запущенным какой-то хостинг, какой-то сервер. +2363.64 2375.32 "Анатолий Кулаков" Допустим, вы делаете какое-то маленькое приложение, которому нужно сжимать картинки, и таких картинок у вас там, допустим, раз в неделю вы бы пофотографировали, выложили там 10 картинок в ваш блог и все. +2375.32 2388.84 "Анатолий Кулаков" Для того, чтобы сжать там, допустим, 10 картинок раз в неделю, хостить целый сервер, оставлять его включенным и ждать пока вы к нему пришлете запросы на изменение размеров, это довольно расточительно. +2388.84 2391.12 "Анатолий Кулаков" Тогда вот на помощь приходят такие функции. +2391.12 2397.40 "Анатолий Кулаков" Если к функциям не обращаются, они просто гаснут и вы не платите абсолютно за то время, пока они не используются. +2397.40 2399.48 "Анатолий Кулаков" Ну, по крайней мере, у большинства операторов. +2399.48 2404.56 "Анатолий Кулаков" А вот как только они вам понадобились, вы платите только за те 10 картинок, которые вы сжали. +2404.56 2410.72 "Анатолий Кулаков" Во все остальное время функции, опять же, после сжатия выключаются, лежат и ничего не кушают, времени не требуют, ресурсы не потребляют. +2410.72 2412.04 "Анатолий Кулаков" Что довольно-таки удобно. +2412.04 2421.44 "Анатолий Кулаков" То есть, если у вас есть какие-то небольшие операции, которые случаются редко, то функции это один из хороших выборов, вам его нужно обязательно рассмотреть. +2421.44 2427.56 "Анатолий Кулаков" Такие провайдеры, то есть, такая концепция функций естественно не Яндексом изобретена. +2427.56 2437.48 "Анатолий Кулаков" Есть AWS Lambda, Microsoft Azure Functions, Google Cloud Functions и практически у всего облачного этого провайдера, у любого они есть. +2437.48 2440.00 "Анатолий Кулаков" Но мы сосредоточимся именно на Яндексах. +2440.00 2443.92 "Анатолий Кулаков" У Яндекс фанкшинов поддерживаются различные среды выполнения. +2443.92 2449.64 "Анатолий Кулаков" Нас интересует именно .NET, .NET на данный момент поддерживается восьмой, шестой и триодин. +2449.64 2453.88 "Анатолий Кулаков" В принципе, я думаю, из любых этих вариантов вам обязательно должен подойти. +2453.88 2457.04 "Анатолий Кулаков" Создаются Яндекс.Функции очень просто. +2457.04 2469.16 "Анатолий Кулаков" В удобном интерфейсе вы можете создать файл, и в этом файле вам необходимо будет написать класс, который называется Handler, и у этого класса Handler должна быть функция, которая называется FunctionHandler. +2469.16 2478.72 "Анатолий Кулаков" И в этой уже как FunctionHandler, которая может принимать какие-нибудь аргументы, вы можете творить все, что угодно, например, вернуть строку Hello World. +2478.72 2483.80 "Анатолий Кулаков" Дальше вы на чистом C# можете делать абсолютно любые вещи, которые вам приходят в голову. +2483.80 2488.20 "Анатолий Кулаков" Допустим, посмотрим на то, как же ведет себя вот такой простенький Hello World. +2488.20 2493.92 "Анатолий Кулаков" Если мы его запустим, то предсказуемо он нам ответит той строкой, которую мы в него захардкодили. +2493.92 2495.16 "Анатолий Кулаков" Что здесь можно заметить? +2495.16 2505.84 "Анатолий Кулаков" Если запускать его несколько раз, то время выполнения функции будет меньше при запуске несколько раз подряд одновременно, чем если бы мы запускали его в редких случаях. +2505.84 2509.60 "Анатолий Кулаков" Это как раз демонстрирует тот концепт, который я упомянул выше. +2509.60 2519.40 "Анатолий Кулаков" Если функция не используется, то весь инстанс, все виртуальная машина вашей функции, она гасится и не потребляет никаких ресурсов. +2519.40 2529.12 "Анатолий Кулаков" Как только функцию вы захотели использовать первый раз, снова поднимается эта виртуальная машина, туда загружается ваше приложение, компилируется и начинает работать, то есть начинает выполняться. +2529.12 2544.48 "Анатолий Кулаков" Если вы выполняете ваши запросы очень быстро, то виртуальная машина не гасится, поэтому ваши запросы выполняются быстрее, чем после холодного старта, то есть после вот такого первого запроса на пробуждение. +2544.48 2564.64 "Анатолий Кулаков" Чтобы вы понимали разницу, то уже поднятый, прогретый экземпляр отвечает вам за одну миллисекунду, а вот холодный старт, первый запрос отвечает вам за 150 миллисекунд, то есть естественно в этот ответ входит не только сама работа функции, но и поднятие всей инфраструктуры, всего инвармента для вашей функции. +2564.64 2572.32 "Анатолий Кулаков" Итак, что же входит в этот наш прогретый экземпляр, который может отвечать нам за одну секунду, за одну миллисекунду, извините. +2572.32 2593.08 "Анатолий Кулаков" Естественно за одну миллисекунду ничего там такого быстрого сделать невозможно, то есть невозможно запустить ваше приложение и прогнать JIT и обработать хендлер, поэтому естественно JIT по идее должен был уже отработан, то есть ваше приложение должно уже висеть в памяти, и просто ваш хендлер вызывается несколько раз, при каждом запросе вызывается ваш хендлер. +2593.08 2609.48 "Анатолий Кулаков" Но тут интересно задаться вопросом, а если ваше приложение уже поднято, то это значит, что по сути все данные, которые висят в этом приложении, допустим, которые в статическом контексте у этого приложения хранятся, то все данные они сохраняются. +2609.48 2629.84 "Анатолий Кулаков" То есть любой другой запрос может иметь доступ к данным предыдущего запроса, что немножко противоречит самой концепции функций, потому что функции это по идее такие атомарные единицы работы, которые никаким образом не могут иметь некого непредсказуемого состояния. +2629.84 2641.92 "Анатолий Кулаков" То есть состояние, которое вы явно не сохранили или явно где-нибудь не загрузили, и поэтому они не должны пересекаться, то есть их данные не должны пересекаться с другими параллельными запросами, которые идут к этим же функциям. +2641.92 2643.36 "Анатолий Кулаков" Проведем следующий эксперимент. +2643.36 2652.64 "Анатолий Кулаков" Если мы создадим статическое поле, каунтер, допустим, и начнем в хендлере этот каунтер увеличивать и сделаем несколько запросов подряд. +2652.64 2657.88 "Анатолий Кулаков" Если бы функция была чистая и красивая, то этот каунтер всегда был бы 0. +2657.88 2664.72 "Анатолий Кулаков" Но в нашем случае, когда мы начинаем делать несколько запросов подряд, мы видим, что каунтер увеличивается. +2664.72 2678.40 "Анатолий Кулаков" Каунтер увеличивается, а это значит, что у нас действительно работает одно и то же приложение между разными запросами, и естественно, у этого приложения одни и те же статические свойства, которыми может доступиться абсолютно любой запрос, который придет в этот хендлер. +2678.40 2690.24 "Анатолий Кулаков" Автор сначала подумал, что на самом деле класс хендлер создается каждый раз при входящем запросе, ну как у нас делают контроллеры обычно при входящем запросе, а просто статические свойства, естественно, в приложении никуда не выгружаются. +2690.24 2701.12 "Анатолий Кулаков" Поэтому он убрал статик-модификатор из этого каунтера и вызвал еще несколько запросов, и несколько запросов продолжили увеличить счетчик. +2701.12 2702.36 "Анатолий Кулаков" Что это значит? +2702.36 2710.32 "Анатолий Кулаков" Это значит, что не просто класс хендлер не создается повторно, а класс хендлер используется один и тот же. +2710.32 2717.60 "Анатолий Кулаков" То есть вы можете шарить даже в приватных свойствах класса хендлер, шарить какое-то состояние между запросами. +2717.60 2721.32 "Анатолий Кулаков" То есть класс хендлер будет один и метод будет вызываться много-много раз. +2721.32 2726.64 "Анатолий Кулаков" Это, в принципе, можно рассчитывать как и плюс, и как и минус. +2726.64 2745.88 "Анатолий Кулаков" То есть из плюсов то, что вы в памяти держите какое-то состояние, а минус это в том, что вы на это состояние рассчитывать не можете, потому что как только функция выгрузится из памяти, а сделать она это может абсолютно любую секунду, то вы все это состояние потеряете, и если вы на это вдруг рассчитывали почему-то, то ваши ожидания обломятся. +2745.88 2749.40 "Анатолий Кулаков" Поэтому в идеальной картине мира, естественно, это рассчитывать никогда нельзя. +2749.40 2752.92 "Анатолий Кулаков" Но так как разработчики не идеальны, то просто так запретить нельзя. +2752.92 2756.52 "Анатолий Кулаков" Поэтому хотелось бы, чтобы здесь была какая-то гарантия. +2756.52 2767.36 "Анатолий Кулаков" Иначе на плечи разработчиков ложится такое время, как очищение ресурсов, и оно усугубится, если начнут использоваться ресурсы, например, Unmanaged. +2767.36 2776.96 "Анатолий Кулаков" То есть подключение к базам данных, какие-то сетевые соединения, какое-нибудь сочтение, запись файла, какие-нибудь работы с хендлерами напрямую, в общем, все это очень сложно. +2776.96 2787.88 "Анатолий Кулаков" И намного легче было бы, если бы все-таки вот этого расшаренного стейта не было, если бы весь стейт чистился, как положено в чистых функциях, и весь стейт заново загружался, как положено в чистых функциях. +2787.88 2790.60 "Анатолий Кулаков" Что же мы можем придумать? +2790.60 2802.92 "Анатолий Кулаков" К сожалению, в том конспекте, про который мы говорим сейчас, то есть в environment.net, в environment.cloud.function мы ничего придумать не можем, потому что они именно так работают. +2802.92 2805.40 "Анатолий Кулаков" Они загружают .NET-приложение и просто держат его в памяти. +2805.40 2815.00 "Анатолий Кулаков" Имея такой концепт, у нас руки связаны, мы никак очищать весь стейт не можем, как бы чистить все статические поля, которые существуют в приложении, это просто что-то невероятное. +2815.00 2825.92 "Анатолий Кулаков" Ну и к тому же, там у нас не только статик, там уже у нас есть и какой-нибудь синхронизейшн контекст и какие-то неявные еще переменные, в общем, все не почистишь, так оно не работает. +2825.92 2831.52 "Анатолий Кулаков" Единственный вариант - это гасить приложение полностью и запускать его заново, как только приходит новый год запроса. +2831.52 2834.24 "Анатолий Кулаков" То есть запускать приложение на каждый запрос. +2834.24 2840.32 "Анатолий Кулаков" Звучит якобы безумно, потому что это кажется, что все будет очень долго, но посмотрим, посмотрим. +2840.32 2841.32 "Анатолий Кулаков" Попробуем. +2841.32 2842.56 "Анатолий Кулаков" Запускать приложение на каждый запрос. +2842.56 2846.12 "Анатолий Кулаков" Через .NET Environment яндекс функции мы такое сделать не можем. +2846.12 2850.52 "Анатолий Кулаков" Значит, нам нужен свой Environment чистый и красивый. +2850.52 2857.08 "Анатолий Кулаков" Мы нашли такой Environment с помощью Environment, который называется Bash, то есть запускается который-либо из скриптик. +2857.08 2858.08 "Анатолий Кулаков" Что мы сделали? +2858.08 2861.60 "Анатолий Кулаков" Мы скомпилировали .NET приложение, которое будет у нас вызываться каждый раз. +2861.60 2864.56 "Анатолий Кулаков" Ну и естественно, в будущем мы хотим сделать так, чтобы оно вызывалось быстро. +2864.56 2868.24 "Анатолий Кулаков" Как же нам это сделать быстро? +2868.24 2880.04 "Анатолий Кулаков" Ну, во-первых, нам нужно все это положить в self-content, запустить стриминг и таким образом мы сможем подойти к тому, что сможем использовать native-out публикацию. +2880.04 2890.64 "Анатолий Кулаков" Благодаря native-out публикации у нас весь код компилируется прямо в момент билда вашего приложения, а не в момент запуска, как это происходит обычно при JIT-компиляции. +2890.64 2896.24 "Анатолий Кулаков" Таким образом, в момент именно билда весь ваш код будет преобразован в машинные команды. +2896.24 2906.48 "Анатолий Кулаков" И когда приложение будет запускаться, то на старте не будет тратиться никакое время в JIT. +2906.48 2908.68 "Анатолий Кулаков" Ну, сказано, сделано. +2908.68 2912.36 "Анатолий Кулаков" Взяли баш-среду, написали скриптик, который вызывает наше приложение. +2912.36 2917.92 "Анатолий Кулаков" Наше приложение мы скомпилировали заранее на локальной среде, зная целевую схему. +2917.92 2918.92 "Анатолий Кулаков" Это можно сделать. +2918.92 2925.56 "Анатолий Кулаков" Сохранили в Яндекс.ОбжектСтор и функция наша скачивает из Яндекс.ОбжектСтора приложение и запускает. +2925.56 2929.24 "Анатолий Кулаков" Запускает дотнетное приложение как свое собственное. +2929.24 2945.44 "Анатолий Кулаков" Так как мы использовали базовый образ баш, в нем уже не установлен дотнет-рантайм, именно поэтому нам сюда же подходит и селф-контейнт, потому что селф-контейнт таскает вместе с собой дотнет-окружение вместе с тем экзешником, в который он скомпилирован. +2945.44 2949.32 "Анатолий Кулаков" Ну, и некий вагон, естественно, тоже как наследник от селф-контейнта. +2949.32 2956.68 "Анатолий Кулаков" Поэтому у нас все дотнет-окружение таскается с собой, весь дотнет-код переведен в машинный код, и мы рассчитываем, что это будет работать быстро. +2956.68 2958.64 "Анатолий Кулаков" Давай же посмотрим, как же оно будет работать. +2958.64 2977.36 "Анатолий Кулаков" Вместе с NativeAuto Андрей также притащил обычное селф-контейнт приложение, то есть, у которого есть внутри себя весь полный дотнет-рантайм, у которого отработал тримминг, но не была доделана вот эта фаза компиляции или в нативный код. +2977.36 2978.36 "Анатолий Кулаков" Вот. +2978.36 2979.36 "Анатолий Кулаков" У нас есть три кандидата. +2979.36 2987.84 "Анатолий Кулаков" При холодном старте Яндекс.Функция загружается примерно за 216 миллисекунд и выполняется. +2987.84 3001.28 "Анатолий Кулаков" Селф-контейнт приложение выполняется за 100 миллисекунд, то есть, быстрее, чем Яндекс.Функция, а NativeAuto за 28 миллисекунд, то есть, в 10 раз быстрее холодный старт у приложения на NativeAuto. +3001.28 3010.52 "Анатолий Кулаков" Это как раз-таки показатель того же, что в Яндекс.Дотнет-окружении у нас происходит JIT-компиляция нашего приложения, а в NativeAuto нет. +3010.52 3012.00 "Анатолий Кулаков" Вот как раз выигрыш в 10 раз. +3012.00 3013.00 "Анатолий Кулаков" Неплохо. +3013.00 3017.76 "Анатолий Кулаков" Далее мы пробуем провести тот же самый эксперимент на горячем экземпляре. +3017.76 3022.58 "Анатолий Кулаков" Здесь уже Яндекс.Функция выполняется за 1,2 миллисекунды, то есть, в оптимальное время. +3022.58 3032.60 "Анатолий Кулаков" Селф-контейнт приложения 51 миллисекунда, то есть, здесь уже возможно JIT конкретно вот этого хендлера, который мы выполняем, играет свою роль. +3032.60 3037.04 "Анатолий Кулаков" И NativeAuto 3 миллисекунды, где-то в 2 раза дольше, чем Яндекс.Окружение. +3037.04 3039.08 "Анатолий Кулаков" В принципе, не критично. +3039.08 3042.04 "Анатолий Кулаков" Что отдельно может порадовать, так это используемая память. +3042.04 3045.92 "Анатолий Кулаков" Вот здесь используется 43 мегабайта против яндексовских 87. +3045.92 3050.74 "Анатолий Кулаков" То есть, по памяти NativeAuto ест в 2 раза меньше, что тоже прекрасно. +3050.74 3056.04 "Анатолий Кулаков" Этого автору показалось мало, и он начал унижать Яндекс дальше. +3056.04 3058.60 "Анатолий Кулаков" Каким образом можно унизить Яндекс больше всего? +3058.60 3061.08 "Анатолий Кулаков" Конечно же, заставить его гуглить. +3061.08 3073.64 "Анатолий Кулаков" Поэтому мы взяли наш Hello World приложение, которое в принципе не показывает практически ничего, кроме времени ответа и времени прогрева, и написали более или менее интерпрайс приложения, которое перекладывает JSON. +3073.64 3087.92 "Анатолий Кулаков" Наш Яндекс.Гугл приложение принимает на вход строку, идет в Google Search API, из Search API достает первые 10 результатов и возвращает пользователю заголовки с ссылками. +3087.92 3097.00 "Анатолий Кулаков" То есть, здесь у нас участвует сериализация, децерализация, HTTP подходы, HTTP походы, парсинг входящих параметров, исходящих параметров. +3097.00 3104.28 "Анатолий Кулаков" То есть, идет какая-то нормальная работа, а не сказать, что там какой-нибудь CPU Intensity в большой, но вполне интерпрайс, почему бы и нет. +3104.28 3108.20 "Анатолий Кулаков" И на вот этом интерпрайсе попробуем перемерить наши показатели. +3108.20 3115.96 "Анатолий Кулаков" Естественно, социальный контент нам больше неинтересен, он показывает что-то промежуточное, не то, не сё, а вот Яндекс с NetAuth вполне могут подраться. +3115.96 3120.00 "Анатолий Кулаков" Итак, холодный старт вот этого большого жирного нашего интерпрайса приложения. +3120.00 3130.72 "Анатолий Кулаков" У Яндекса занял больше секунды, NetAuth показал 583 миллисекунды, ну то есть в два раза быстрее, уже не в 10, а в 2, ну допустим. +3130.72 3151.68 "Анатолий Кулаков" И прогретый экземпляр у Яндекса, вызов метода из прогретого экземпляра у Яндекса занял 354 миллисекунды и у NetAuth 486 миллисекунд, ну то есть совсем не сильно он отстал, так буквально процентиков на 30 отстал NetAuth, при этом со стартом в два раза больше. +3151.68 3174.04 "Анатолий Кулаков" Итак, что же мы получаем, если вот кратко смотреть на эти результаты, то Яндекс, среда выполнения Яндекс функций дает лучшее время выполнения для уже разогретых для подготовленных экземпляров, но почему-то все еще больше, чем у NetAuth, но при этом достаточно долго отрабатывает холодные старты. +3174.04 3184.32 "Анатолий Кулаков" У NetAuth лучшее время при холодном старте, прямо значительно лучшее, но почему-то несколько проигрывает в горячем экземпляре, то есть в прогретом, в подготовленном экземпляре. +3184.32 3188.36 "Анатолий Кулаков" И вот здесь, наверное, довольно интересный вопрос, почему проигрывает-то? +3188.36 3202.92 "Анатолий Кулаков" На самом деле, понятно, что JIT на старте не выполняется и понятно, почему оно выигрывает, но если у вас два приложения поднятых, то есть .NET на одно приложение поднято и NetAuth на приложение поднято, то дальше дело техники просто вызвать функцию и все. +3202.92 3212.04 "Анатолий Кулаков" И для того, чтобы устранить некие вопросы, которые у нас возникли во время прочтения данной статьи, мы в эфир позвали ее автора, прямо вот непосредственно Андрея Порожнякова. +3212.04 3213.04 "Анатолий Кулаков" Привет, Андрей! +3213.04 3217.48 "Анатолий Кулаков" Да, всем привет, спасибо, что позвали, я готов дать разъяснения. +3217.48 3228.28 "Анатолий Кулаков" Смотри, хорошая статья, но вот первое, что сразу бросается в глаза, это почему NetAuth все-таки медленнее стандартного .NET окружения на прогретом экземпляре? +3228.28 3236.16 "Анатолий Кулаков" Казалось бы, они должны быть или одинаковыми, ну или NetAuth, раз он настолько оптимизированный, красивый и такое, должен быть даже быстрее. +3236.16 3238.12 "Анатолий Кулаков" Откуда вот эта медленность? +3238.12 3242.84 "Анатолий Кулаков" Да, хороший вопрос, на самом деле, начну немножко издалека. +3242.84 3257.28 "Анатолий Кулаков" Смотри, в случае, когда мы используем в Яндекс.Функциях холодный старт, то приложение у нас каждый раз запускается заново, если мы работаем с JIT, вот, и происходит JIT-компиляция. +3257.28 3261.20 "Анатолий Кулаков" Вот за счет этого холодный старт, он достаточно долго отрабатывает. +3261.84 3278.84 "Анатолий Кулаков" Для подготовленного экземпляра, как я уже описал в статье, мы видим, что существует уже поднятый хост с приложением, которое скомпилировано, вот, и, собственно, это доказывается тем, что как раз там вылезает вот этот сайд-эффект, данные от одного запроса могут быть доступны другому запросу. +3278.84 3289.04 "Анатолий Кулаков" Вот, это нам говорит о том, что хост с .NET-приложением, он поднят, вот, и мы, собственно, функции каждый раз вызывая, уже стреляем в этот поднятый хост. +3289.04 3306.60 "Анатолий Кулаков" Вот, и вот для JIT-а из-за этого холодный старт сильно отличается по времени работы от подготовленного экземпляра, потому что, в первом случае, у нас поднят хост, запущено приложение, там, весь EL-код уже переведен в машинные команды, все, бери да отрабатывай. +3306.60 3310.60 "Анатолий Кулаков" А в случае с холодным стартом все это нужно делать каждый раз. +3310.60 3319.60 "Анатолий Кулаков" Вот, ну, и, собственно, когда мы говорим про AVT, у нас уже холодный старт от подготовленного экземпляра отличается фактически не сильно. +3319.60 3326.12 "Анатолий Кулаков" Мы в первом и в втором случае полностью запускаем собранные AVT-приложения, там, из бар-скрипта. +3326.12 3338.56 "Анатолий Кулаков" В случае с подготовленным экземпляром у нас разве что само окружение уже поднято, то есть, да, там, Linux какое-то, какой-то Linux-окружение, на котором приложение выполняется, оно поднято. +3338.56 3341.56 "Анатолий Кулаков" Но, кстати, Яндекс.Функция его довольно быстро и так поднимает. +3341.56 3343.56 "Анатолий Кулаков" Вот, поэтому разница небольшая. +3343.56 3351.64 "Анатолий Кулаков" И вот почему у нас получается, отвечая, да, на вопрос, почему AVT медленнее в подготовленном экземпляре, чем JIT. +3351.64 3359.80 "Анатолий Кулаков" У меня есть три, ну, как, не только предположения, три фактора, которые совершенно точно на это влияют. +3359.80 3372.32 "Анатолий Кулаков" Во-первых, когда мы работаем с JIT-компиляцией, с встроенной .NET-средой, когда мы стреляем в подготовленный экземпляр, он, приложение на нем уже запущено. +3372.32 3377.44 "Анатолий Кулаков" В случае с AVT, приложение нужно запустить, это все равно какой-то ресурс занимает. +3377.44 3384.88 "Анатолий Кулаков" Нужно выделить память, ну, из вашего скрипта запускается приложение каждый раз заново, на это какие-то ресурсы тратятся. +3384.88 3385.88 "Анатолий Кулаков" Вот. +3385.88 3409.16 "Анатолий Кулаков" И вот это, я думаю, влияет, причем достаточно сильно, потому что, да, AVT у нас обгоняет JIT при старте, за счет того, что отсутствует необходимость компиляции, но в случае с подготовленным экземпляром у нас мало того, что там JIT уже скомпилирован, так он еще и запущен, а здесь нам нужно приложение запускать, поэтому вот какой-то ресурс на это тратится, я думаю, существенно. +3409.16 3428.16 "Анатолий Кулаков" Во-вторых, что еще влияет, почему встроенный JIT, .NET-шески, в Яндекс.Функциях быстрее, это то, что в принципе вообще у нас AVT так работает, что он генерирует универсальный набор инструкций для какой-то указанной среды, которую мы вот указали, в Runtime Identifier. +3428.16 3432.64 "Анатолий Кулаков" Мы там можем указать Linux x64, там Windows x64 и так далее. +3432.64 3433.64 "Анатолий Кулаков" Вот. +3433.64 3444.68 "Анатолий Кулаков" Такой подход, он не учитывает много особенностей какого-то конкретного окружения, то есть генерируется максимально универсальный набор инструкций для Linux x64, например. +3444.68 3461.92 "Анатолий Кулаков" А .NET, современный JIT, встроенный в .NET, он более умный, он смотрит, где он запущен, да, он там понимает гораздо больше особенностей среды, это не просто там Linux x64, а еще какие-то особенности архитектуры и так далее. +3461.92 3466.00 "Анатолий Кулаков" И он более оптимальный набор инструкций будет генерировать под эту среду. +3466.00 3467.00 "Анатолий Кулаков" Вот. +3467.00 3485.68 "Анатолий Кулаков" Но здесь стоит отметить, что .NET можно настраивать в ряде случаев, я вот этим не занимался, то есть можно там указать в csproj файле там набор атрибутов, если мы точно знаем, ну, некоторые особенности той среды, на которой он будет выполняться, то может быть вот здесь можно чуть-чуть соптимизировать. +3485.68 3495.32 "Анатолий Кулаков" Я этим не занимался, но может быть небольшое ускорение здесь можно получить за счет того, что мы сразу укажем там какие-то наборы инструкций. +3495.32 3500.40 "Анатолий Кулаков" Ты имеешь в виду инструкции именно процессора, который используется? +3500.40 3501.40 "Анатолий Кулаков" Да-да-да. +3501.40 3508.60 "Анатолий Кулаков" То есть мы должны понимать, ну, для этого нужно, конечно, знать архитектуру того, где Яндекс.функции запускает твое приложение. +3508.60 3510.00 "Анатолий Кулаков" Я вот так глубоко не копал. +3510.00 3519.92 "Анатолий Кулаков" Ну, так как у них там все равно виртуальные машины запускаются, то есть эта архитектура, скорее всего, у них не сильно меняется между запуском функций, то есть там какая-то виртуальная машина, которая подразумевает конкретный процессор, который она эмулирует. +3519.92 3523.24 "Анатолий Кулаков" Ну и, наверное, эта информация более-менее стабильная, то есть на нее можно рассчитывать. +3523.24 3531.52 "Анатолий Кулаков" Ну, я надеюсь, что да, скорее всего, да, то есть в эту сторону можно покопать и можно, может быть, чуть-чуть ускорить за счет этого. +3531.52 3543.00 "Анатолий Кулаков" Но, тем не менее, я этим не занимался, я там указал условно максимально универсальное средоуполнение, Linux x64, и довольствовался тем, что мне AUT легенерирует. +3543.00 3567.80 "Анатолий Кулаков" Ну и третий, третий фактор, который влияет, это, опять же таки, G в современном .NET-е, он имеет ряд оптимизаций в рантайме непосредственно, то есть когда приложение запущено, оно работает и, ну, условно говоря, в рантайме может перекомпилироваться, могут перекомпилироваться определенные участки кода по-другому, более оптимально в процессе работы. +3567.80 3579.20 "Анатолий Кулаков" AUT, конечно, ничего такого не умеет, то есть вот как он сгенерировал машинные команды на этапе компиляции, так они будут выполняться, ничего там перекомпилироваться уже не будет, там никакой перекомпиляции нет. +3579.20 3592.84 "Анатолий Кулаков" Вот, поэтому я думаю, что за счет этого еще тоже может определенный прирост производительности, ну, получаться, если GIT компилирует код, и приложение работает достаточно долго, то есть подготовленный экземпляр висит какое-то время. +3592.84 3619.96 "Анатолий Кулаков" Угу, и смотри, мне кажется, что самым существенным — это первый пункт должен быть, да, то есть накладные расходы как раз на вызов, на загрузку самого приложения, на загрузку его с памяти, на выделение памяти, на загрузку с диска, на выделение памяти и так далее, а ты не знаешь, не смотрел ли, может быть, у других провайдеров, клауд-провайдеров есть какие-то, не знаю, хосты для нативных приложений, которые вот его уже загрузили, осталось там по какому-нибудь C-коду дернуть, правильный метод и все. +3619.96 3623.48 "Анатолий Кулаков" Вот что-нибудь такое не видел, не встречал, есть ли решение этой проблемы принципиальной? +3623.48 3636.68 "Анатолий Кулаков" Во-первых, я не считаю это проблемой, то есть если мы посмотрим на метрики в статье, то да, NativeUIT проигрывает по времени подготовленному экземпляру со встроенным дотнетом, но на мой взгляд проигрывает не сильно. +3636.68 3637.68 "Анатолий Кулаков" Вот. +3637.68 3644.36 "Анатолий Кулаков" И скорее всего, если поднять, ну то есть мы говорим о том, что приложение будет запущено и оно будет висеть какое-то время. +3644.36 3651.76 "Анатолий Кулаков" Здесь у нас есть опасность попасть, ну получить тот же тайт-эффект, от которого я в статье и пытался избавляться. +3651.76 3655.20 "Анатолий Кулаков" Если приложение уже запущено, оно может сохранять какие-то данные. +3655.20 3662.76 "Анатолий Кулаков" И если данные можно сохранить внутри приложения в каких-то переменных, значит их можно шарить между запросами. +3662.76 3671.80 "Анатолий Кулаков" А это уже нарушает один из основных принципов FaaS архитектуры, то, что вызовы должны быть изолированы вокруг. +3671.80 3672.80 "Анатолий Кулаков" Вот. +3672.80 3673.80 "Анатолий Кулаков" Ну да, да. +3673.80 3688.88 "Анатолий Кулаков" Ну, да, я отвечаю на твой вопрос, я не смотрел, где можно прямо вот, чтобы у какого-то облачного провайдера было кто-то именно заточенное под native-UT приложение .NET, я вообще не думаю, что такое можно найти. +3688.88 3689.88 "Анатолий Кулаков" Вот. +3689.88 3698.32 "Анатолий Кулаков" Тут в Яндекс.Функциях, я не нашел в интернете абсолютно никаких следов, что кто-то когда-то в Яндекс.Функциях пытался хотя бы запускать native-UT приложение. +3698.32 3704.92 "Анатолий Кулаков" Возможно, я сделал первый, может быть, даже до сих пор единственный, ну, видимо, людям это пока не очень нужно. +3704.92 3706.60 "Анатолий Кулаков" Может быть, кому-то это решение поможет. +3706.60 3711.52 "Анатолий Кулаков" Да, в любом случае, опыт прекрасный, поэтому хорошо, что ты его зафиксировал в виде отдельной статьи. +3711.52 3718.60 "Анатолий Кулаков" Ну, я с тобой согласен, что если все-таки копать в переиспользование одного хаста, который будет запускать, это полностью уходит от цели статьи. +3718.60 3719.60 "Анатолий Кулаков" Отлично. +3719.60 3737.04 "Анатолий Кулаков" Так, давай напоследок, смотри, мы еще сошлемся на твой доклад, но ты в статье описал, что, в принципе, если вам этот подход понравился, то перед вами стоит ограничение, да, ограничение самого IoT, то есть вы не все, не весь ваш код сможете превратить, запаковать вот таким вот образом. +3737.04 3753.44 "Анатолий Кулаков" Можешь назвать кратко вот три, не знаю, самых существенных ограничения, которые чаще всего встречаются в приложении, которые, с помощью которых, из-за которых невозможно будет таким образом упаковать ваше приложение и опубликовать в виде Яндекс-функции? +3753.44 3771.36 "Анатолий Кулаков" Да, смогу назвать, на самом деле, у Native IoT собственных ограничений как таковых нет, но есть ограничения связанные с стримингом, то есть стриминг используется, есть ограничения связанные с публикацией, ну, с сингл-файл публикейшн. +3771.36 3772.36 "Анатолий Кулаков" Вот. +3772.36 3779.80 "Анатолий Кулаков" И все они перетекли к нам в наследование, если мы хотим собирать Native IoT приложение, то придется эти ограничения учитывать. +3779.80 3806.00 "Анатолий Кулаков" Вот, могу дать такой универсальный совет, скорее всего, если кто-то будет писать приложение сразу под Native IoT, то придется учитывать, что JSON-сериализация, вот, часть всего, я вижу на проекте, который я пытался переводить уже готовый на Native IoT, или если пишут с нуля, то первое, что стоит учитывать, что нужно использовать source-генераторы для JSON-сериалайзеров. +3806.00 3807.00 "Анатолий Кулаков" Вот. +3807.00 3816.76 "Анатолий Кулаков" Это вот такое, ну, не то чтобы ограничение, а особенность разработки, да, то есть если это не учесть, если оставить JSON-сериализацию в рантайме, то оно в Native IoT не заработает. +3816.76 3817.76 "Анатолий Кулаков" Вот. +3817.76 3822.72 "Анатолий Кулаков" И если нужно там определенный атрибут добавлять, у меня в докладе это есть, как этим пользоваться. +3822.72 3823.72 "Анатолий Кулаков" Вот. +3823.72 3830.44 "Анатолий Кулаков" Поэтому это вот, ну, не только прям ограничение, но это, наверное, да, в каком-то смысле это какие-то дополнительные source-генераторы. +3830.44 3835.50 "Анатолий Кулаков" То есть всю JSON-сериализацию нужно учесть и описать в виде source-генерации. +3835.50 3846.72 "Анатолий Кулаков" А так, ну, не все поддерживается, да, то есть не получится развернуть какое-нибудь полноценное там Blazor или Razor Pages приложение, пока что не получится. +3846.72 3850.92 "Анатолий Кулаков" То есть есть, опять же, такие… Ну, если мы говорим о функциях, наверное, это не так страшно. +3850.92 3872.56 "Анатолий Кулаков" Да, в функциях, я вот даже так не могу навскидку сказать, чего может не хватить, если используем какие-то дополнительные решения, ну, то есть какие-то даже известные, там, видите, ну, GetPackets, условно, какой-нибудь медиатор, я не знаю, хочет ли кто-то в функциях использовать медиатор, мне кажется, функция это что-то такое быстрое, что отработало, один раз умерло, там, до следующего вызова. +3872.56 3873.56 "Анатолий Кулаков" Вот. +3873.56 3876.32 "Анатолий Кулаков" Ну, вот медиатор прям, он условно поддерживается в Native IoT. +3876.32 3877.32 "Анатолий Кулаков" Там коктейлить придется. +3877.32 3878.32 "Анатолий Кулаков" Ну, и да. +3878.32 3881.92 "Анатолий Кулаков" Ну, хорошо, смотри, сервизатор, который ты назвал, это уже прекрасно. +3881.92 3884.00 "Анатолий Кулаков" Ну, об остальном, я думаю, мы посмотрим в докладе. +3884.00 3885.00 "Анатолий Кулаков" Хорошо. +3885.00 3888.16 "Анатолий Кулаков" Спасибо, что помог разобраться. +3888.16 3892.92 "Анатолий Кулаков" Так, я напомню, что с нами был Андрей Порожняков, автор статьи, которую мы обсуждаем. +3892.92 3893.92 "Анатолий Кулаков" Спасибо большое. +3893.92 3894.92 "Анатолий Кулаков" До новых встреч, Андрей. +3894.92 3896.44 "Анатолий Кулаков" Да, спасибо, что позвали. +3896.44 3897.44 "Анатолий Кулаков" Всем пока. +3897.44 3898.44 "Анатолий Кулаков" Пока. +3898.44 3902.08 "Анатолий Кулаков" Так, отлично, отлично, что Андрей нам все прояснил. +3902.08 3903.24 "Анатолий Кулаков" Давайте подведем итоги. +3903.24 3904.76 "Анатолий Кулаков" Итак, что же получается? +3904.76 3924.00 "Анатолий Кулаков" Что если вы готовы принять на себе риски, когда ваше состояние в ваших функциях может смешиваться, вы понимаете, что вы или все контролируете, или для вас это не страшно, а также если для вас время холодного старта не особо критично, то, наверное, можно выбрать чистые Яндекс-функции с дотнет-окружением. +3924.00 3936.26 "Анатолий Кулаков" Если же вы хотите все-таки, чтобы никакого состояния не смешивалось и ваши функции были наичистейшие, то вы можете использовать NativeOut в виде запускаемого файла. +3936.26 3945.64 "Анатолий Кулаков" Здесь еще нужно иметь в виду, что действительно у NativeOut есть ограничения, то есть не любое приложение вы прям можете взять и прекомпилировать в NativeOut. +3945.64 3949.72 "Анатолий Кулаков" Его необходимо или немножко подготовить, или может быть даже это совсем невозможно. +3949.72 3963.00 "Анатолий Кулаков" Какие именно ограничения связаны с NativeOut, как его готовить и какие тонкости на этом пути вас могут встретить, вы можете посмотреть в прекрасном докладе Андрея Порожнякова «NativeOut. Возможности и ограничения», который мы упоминали выше. +3963.00 3976.04 "Анатолий Кулаков" Если же вам интересно, как работают Яндекс-клаундфункшены под капотом, то есть шикарный доклад, который Максим Шошин делал на spb.net, который называется «Серверлесс под капотом клаундфункшенов». +3976.04 3996.44 "Анатолий Кулаков" Макс работает в Яндексе и непосредственно участвовал в разработке клаундфункшенов, поэтому он красиво на картинках показывает, как же это все там работает, вся эта магия с виртуальными машинами, с засыпанием, с прогревом, с амортизацией, в общем, очень интересно, поэтому вот эти два доклада обязательно гляньте, если тема клаундфункшенов и аота вам интересна. +3996.44 4008.40 "Игорь Лабутин" Ну прям монументально, статья оказалась всего-то что не так, краткий ответ сначала думал, что все не так, но оказалось все гораздо сложнее и интереснее, действительно. +4008.40 4021.48 "Игорь Лабутин" Ну непонятно, насколько как бы хочется прям вкладываться в NativeOut для того, чтобы получить выигрыш, особенно если прогретые функции работают быстрее, ну да, надо смотреть. +4021.48 4025.76 "Игорь Лабутин" Потому что NativeOut все-таки требует некоторого приседания для того, чтобы все под ним заработало. +4025.76 4033.12 "Анатолий Кулаков" С другой стороны, видишь, не талия, это прекрасная техническая задачка, на которую можно потратить выходные, а потом хвастаться перед пацанами. +4033.12 4041.68 "Анатолий Кулаков" Ну или на первую неделю в NativeOut, ну или месяц, а потом еще баги отлавливать пару месяцев, да, это все тонкости. +4041.68 4096.12 "Игорь Лабутин" Да, ладно, давай пойдем дальше, дальше у нас, наверное, будет не очень профильная для нас статья, ну даже не статья, а это вышедший Technology Radar, он на самом деле вышел довольно давно, мне кажется, выходит он 2 раза в год, если я ничего не путаю, и я его проглядел, казалось бы, ну что там интересного может быть, все же будут говорить про LLM, и я в общем не ошибся, если мы посмотрим в раздел техники, напоминаю, что Technology Radar это такая штука, которая выпускается компанией ThoughtWorks, и там рассказано, грубо говоря, там все технологии, нетехнологии, в общем там 4 раздела под названием Technics, Platforms, Tools и Languages and Frameworks, и в каждом из разделов различные технологии, софт, подходы, языки и прочее разделены на 4 части. +4096.12 4109.56 "Игорь Лабутин" Adopt, это значит можно использовать, все нормально, Tryout — пробуйте, но присматривайтесь, и Hold — лучше пока прекратить использовать, если вы используете. +4109.56 4143.08 "Игорь Лабутин" И в разделе Technics, то есть всякие разные техники, не знаю, подходы, сложно на русском перевести каким-то одним словом сейчас сходу, там действительно прям засилье LLM-ок во всех разделах, то есть в трайле 6 из 8 пунктов про LLM, в ASS 5 из 7 пунктов про LLM, и даже в Hold пробрался LLM, где сказано, не надо заменять парное программирование парным программированием с AI, это пока не то. +4143.08 4153.12 "Игорь Лабутин" Это был неожиданный вывод, то есть пока ты читаешь, ты такой, и тут LLM, и тут LLM, и тут Tools для LLM, и тут надо LLM, и тут LLM, и тут в Hold, а вот для парного программирования не надо. +4153.12 4160.00 "Анатолий Кулаков" То есть как раз та ситуация, когда ты технологию еще даже не начал использовать, а другие уже закончили +4160.00 4161.00 "Игорь Лабутин" использовать. +4161.00 4164.08 "Игорь Лабутин" Типа того, то есть как бы живой человек пока лучше. +4164.08 4183.88 "Игорь Лабутин" В Platforms я ничего интересного не нашел, там какие-то такие очень супер специфичные интерфразные какие-то платформы либо опять же все, что относящиеся к AI, а вот секция Tools она в принципе интересна, я планирую в нее заглянуть, посмотреть, ну в смысле я в нее уже заглянул, и даже какие-то кусочки из нее использую или пробовал. +4183.88 4201.00 "Игорь Лабутин" Значит в секции Adopt, то есть в секции давайте уже пора применять можно, мы разрешаем, или мы советуем, находится такой тул под названием Bruna, мы его уже упоминали по-моему в кратко разном в каком-то из выпусков с полгодика назад, когда он вышел, это замена Postman. +4201.00 4215.48 "Игорь Лабутин" Если вы пользуетесь Postman, Postman сейчас стал супертяжелый Postman, по-моему больше не разрешает никакого Local Only разработки, там нужно обязательно логиниться в их клауд, или что-то в таком духе, когда я давно уже не пользуюсь, но что-то такое слышалось. +4215.48 4226.32 "Игорь Лабутин" Это если вдруг у вас по какой-то причине нет интернета, то он там будет страдать и не запускаться, по крайней мере была такая версия у меня, которая без интернета не запускалась. +4226.32 4262.52 "Игорь Лабутин" В общем, кому-то это тоже надоело, и товарищ написал опенсурсный клиентик Bruna, там у него есть какие-то кусочки платных функций, которые не опенсурсные, но даже в бесплатном варианте он вполне себе функционален, активно очень дорабатывается, поэтому если вы пользовались Postman, можно посмотреть на альтернативы, я сейчас в основном пользуюсь клиентом Insomnia, который, если я правильно помню, по-моему тоже Electron, плюс кусочек .NET, мне казалось там был раньше, по крайней мере, вот, но на Bruna тоже поглядываю, он у меня стоит вторым, и в принципе более-менее работает. +4262.52 4268.96 "Игорь Лабутин" Значит, в разделе Trial тоже есть штука, которую я либо пробовал, либо планирую попробовать. +4268.96 4290.88 "Игорь Лабутин" Во-первых, это тулл, не знаю, на комплект туллов под названием Devbox, они называют это Isolated Environments Without Docker, то есть если вы хотите каким-то образом изолировать всякие разные ваши инвайорменты друг от друга, ну там, не знаю, .NET 5, .NET 8 или 9, без использования докера и чего-либо. +4290.88 4315.00 "Игорь Лабутин" В общем-то, идея не нова, таких штук существует довольно много и разных, .NET сам по себе довольно неплохо умеет изолироваться, у нас, как известно, SDK ставится каждый в свою папочку, такие же туллы существуют для Java, для Python, в Python, мне кажется, это наиболее развито со всякими их VN и прочими штуками, а здесь тулл, который вроде как для всего. +4315.00 4321.56 "Игорь Лабутин" Там у них на сайте указано, по-моему, типа 15 разных языков и он, мол, для всех умеет работать. +4321.56 4324.40 "Игорь Лабутин" Планирую посмотреть, попробовать, может быть, действительно что-то удобное. +4324.40 4327.32 "Анатолий Кулаков" То есть ты не знаешь, как он внутри работает, да, как он изоляции добивается? +4327.32 4328.32 "Анатолий Кулаков" Не смотрел. +4328.32 4329.32 "Игорь Лабутин" Гарантирует? +4329.32 4330.32 "Игорь Лабутин" Да, не смотрел. +4330.32 4369.44 "Игорь Лабутин" Ну, гарантировать там вряд ли, я думаю, что, скорее всего, там ничего более креативного, чем сим линками правильно разделять туллы и так далее, не придумали особо, понятное дело, просто вопрос, что оно делает это все единообразно для всех, потому что вот у меня там стоит, допустим, несколько версий Python, мне нужно помнить все команды, чтобы управлять ими, отдельно у меня стоит, ох, как его зовут, sdkman для управления версиями джавы, для .NET, понятно, у меня есть .NET tool, и в каждом из них нужно помнить свой синтаксис, как выбрать текущий, как поставить нужный, как посмотреть, какие доступны. +4369.44 4372.64 "Игорь Лабутин" Если это все будет сделано одним туллом, в принципе, будет удобно. +4372.64 4383.28 "Игорь Лабутин" Я планирую посмотреть, попробовать, мне приходится переключаться между разными технологиями, и если он будет выполнять свою задачу, будет хорошо, хотя бы даже в рамках одного моего ноутбука. +4383.28 4397.60 "Игорь Лабутин" Я не говорю про то, чтобы делать там стандартом на всю команду и вот это все, это как бы ладно, пусть остаются PyEnv, ну, допустим, если это про Python мы говорим, но даже хотя бы локально будет, может быть, полезно. +4397.60 4431.44 "Игорь Лабутин" Вторая штука – это продукт под названием divtastic, это open-source продукт, MIT лицензия, div differ, который умеет вроде как структурный div с учетом синтаксиса исходников, я бы сказал, то есть он умеет понимать синтаксис исходников и, соответственно, как-то показывает диффы более оптимально, нежели чем обычные дифферы, которые просто трочки сравнивают, не зная, что такое синтаксис. +4431.44 4483.96 "Игорь Лабутин" Пока выглядит, что вроде как командлайновский, и я так понимаю, что его главное предназначение это как раз таки, ну, либо для тех, кто фанат командлайн, да, и живет в командлайне, либо его иногда удобно использовать, настроить в качестве git div tool, я иногда действительно пользуюсь git div в командлайне, чтобы быстренько посмотреть, что я там собираюсь коммитить, и приятно будет, если это будет не, ну, как-то действительно красиво расцвечено, он цветами всё это рисует в консольке, если терминал поддерживает вот это всё, вот именно поэтому я его хочу попробовать прикрутить именно как div tool, чисто иногда смотреть в консольке, так, я обычно использую что-то стороннее и более развесистое, гуёвое, когда мне нужно особенно какие-то three-way merges делать, вот это всё, тут понятно, что одним простым диффом не обойдёшься. +4483.96 4493.08 "Анатолий Кулаков" Да, я смотрю сейчас по документации, что это действительно больше он div, как раз действительно git tool, командлайновый без merge. +4493.08 4495.52 "Анатолий Кулаков" Ну, без merge, это уже другой инструмент. +4495.52 4517.88 "Игорь Лабутин" Ну, это другой инструмент, но быстренько проглядеть, что же вы там собираетесь закоммитить, если вы, например, пользуетесь командлайновым git, а я знаю людей, которые именно коммитят git, то есть всякие там rebases, ну, сложные короче workflow делают всё-таки в UI, а базовую работу, да, там, checkout, бранчи посвечить, коммиты сделать, пуши сделать, вот из командлайн, я тоже, наверное, как-то так делаю, +4517.88 4518.88 "Анатолий Кулаков" будет полезно. +4518.88 4522.44 "Анатолий Кулаков" Я как раз наоборот, в rebase, в UI боюсь, я в rebase только командлайн не делаю. +4522.44 4524.36 "Анатолий Кулаков" Ну и всё остальное тоже командлайн. +4524.36 4527.48 "Анатолий Кулаков" Кстати, программинг-лэнгвич, который поддерживается, C# есть. +4527.48 4528.48 "Анатолий Кулаков" Да, да, да. +4528.48 4529.48 "Анатолий Кулаков" Наверное, будет удобно. +4529.48 4540.64 "Анатолий Кулаков" Меня больше удивляет, почему это привлекло внимание почему-то техрадара, ну то есть утилиток миллиард, ну то есть любой студент пишет div, tool, zoo, и она консольная, и она примитивная, ну то есть при чём здесь техрадар-то, как она туда попала? +4540.64 4541.64 "Игорь Лабутин" Интересный вопрос, несомненно. +4541.64 4553.08 "Игорь Лабутин" Ну нет, у них 21 тысяча звёздочек, то есть видимо это хороший какой-то на репозитории, в гитхабе, то есть в общем так-то… +4553.08 4560.08 "Анатолий Кулаков" Просто функциональность элементарная, ну что такое, посмотреть div в командной строке, ну это нужно, я не знаю, раз в день это максимально просто. +4560.08 4562.60 "Анатолий Кулаков" Ну, может быть, потому что это написано на расте? +4562.60 4570.08 "Анатолий Кулаков" Это можно сравнить с кубернетосом, который, допустим, тоже в техрадаре существует, то есть они где-то одного уровня tool, zoo, да, кубернетос, и диффер консольный. +4570.08 4575.08 "Игорь Лабутин" Один на год, другой на расте, ну что там, разницы-то никакой. +4575.08 4580.64 "Игорь Лабутин" Дальше, следующий из разряда – это терминал. +4580.64 4582.92 "Игорь Лабутин" Каким терминалом ты пользуешься, Анатолий? +4582.92 4587.92 "Игорь Лабутин" У меня коньему и фар, не, ну для терминала коньему. +4587.92 4598.16 "Игорь Лабутин" Ну, ты, соответственно, под виндой, я сейчас живу на маке, на маке у меня iTerm, iTerm2, который не стандартный терминал, а чуть-чуть более развесистый терминал. +4598.16 4600.40 "Игорь Лабутин" А техрадар рекомендует использовать варп. +4600.40 4616.88 "Игорь Лабутин" Это, ну правда, тебе не подойдет, у них виндовой версии еще нет пока, но уже в техрадаре, прикинь, то есть они тоже как-то очень активно развиваются, это тоже написано на расте, может, в этом причина, может, они из-за раст все, вот. +4616.88 4623.40 "Анатолий Кулаков" Может, может, там этот фаулер перевел на раст всю свою компанию, теперь радуются любые фанюрки. +4623.40 4624.40 "Игорь Лабутин" Возможно, возможно. +4624.40 4638.24 "Игорь Лабутин" Я не знаю, что там происходит, потому что действительно там варп, ну действительно, выглядит прикольно, там, по-моему, не было квейк-режима, и это для меня сразу минус. +4638.24 4643.28 "Анатолий Кулаков" Так, а как им, возможно, пользоваться-то они, по-американски? +4643.28 4651.68 "Игорь Лабутин" Не, ну кто-то, например, я видел, и в принципе иногда я так делаю, бывает такой, что моя терминалка просто на отдельном десктопе лежит, то есть я туда переключаюсь. +4651.68 4668.40 "Игорь Лабутин" Ну что на винде, что на макетах делал, просто кладешь его на отдельный десктоп, и туда-сюда переключаешься, просто свайпом вправо-вправо, ну не свайпом, как-то с клавиатурой там, я не помню, виндус, не виндус, вправо, там, короче, какая-то магическая комбинация клавиш, я уже забыл, переключение +4668.40 4669.40 "Анатолий Кулаков" между десктопами. +4669.40 4674.56 "Анатолий Кулаков" Ну да, да, я точно так же на макетках, типа переключаюсь на виртуальный второй экран, в принципе удобно, конечно, +4674.56 4675.56 "Игорь Лабутин" но. +4675.56 4713.16 "Игорь Лабутин" Ну в общем вот, и туда же текстовый редактор z, опять же, текстовых редакторов миллион, sublime, z, какие еще есть, наверняка еще какие-то есть, вот, я имею в виду таких, которые кроссплатформенные везде, понятно, что если мы берем каждую платформу, там много кого будет, еще notepad++, да, для винды и прочее, но z тоже написан на расте, и когда я третий продукт увидел, который написан на расте, у меня закрывалось подозрение, что видимо раст как-то их немножко проплатил, ну не проплатил наверное, но как-то что-то вот оно есть такое. +4713.16 4714.88 "Анатолий Кулаков" Мельчает как-то, радар мельчает. +4714.88 4717.72 "Игорь Лабутин" Да, да, да, это меня тоже удивило. +4717.72 4722.64 "Игорь Лабутин" Дальше, ну не то, что интереснее, languages and frameworks, чтобы понимали масштаб. +4722.64 4749.92 "Игорь Лабутин" Там много всего очень узкоспецифичного, типа там граф QL опять появился в разделе trial, по-моему, если я правильно помню, как ни странно, но в adopt есть testcontainers, и тут, наверное, я соглашусь, testcontainers, технология хорошая, но опять же, сравниваем, да, масштаб testcontainers и command-line-differ, ну как бы да, берете, пользуйтесь testcontainers. +4749.92 4762.96 "Игорь Лабутин" А вот в trial, наверное, это редкий случай, но в trial затесалась дотнетная библиотека, причем это даже не tool, и не какой-то продукт, а это гитхабовская просто библиотечка. +4762.96 4767.20 "Игорь Лабутин" Библиотечка называется CAP, ну C-A-P, как CAP-теорема. +4767.20 4768.64 "Игорь Лабутин" Может, кстати, поэтому она так называется? +4768.64 4773.84 "Игорь Лабутин" Мы тут с тобой перед выпуском обсуждали, почему так называется, потому что распределенный система. +4773.84 4787.96 "Анатолий Кулаков" Безусловно, да, безусловно, навеяно именно этим, но просто, знаешь, как CAP-теорема, это такая богатая абстракция, за которой кроется тонны научных статей, и вот одна из статей может вылиться в отбокс, но как бы слишком абстрактно названо. +4787.96 4820.24 "Игорь Лабутин" Ну, библиотечка, да, значит, это дотнетный нугет-пакет, который имеет там 6500 звездочек, 1500 форков, почти, ну, не то чтобы прям миллионы, но довольно много, и написано, что это distributed transaction solution in microservice based on eventual consistency, also an event bus with outbox pattern, короче, это и event bus тебе, и outbox, и eventual consistency там, и короче, чертовступе. +4820.24 4844.64 "Игорь Лабутин" Смысл в том, что, ну, основная идея, это, конечно, то, что эта библиотека будет работать в качестве outbox, тут прям написано, что вот CAP implements the outbox pattern described in the eShop eBook, но это классическая книжка Microsoft, внутренняя по архитектуре, модельный пример, eShop, он контейнер, и вот это все. +4844.64 4857.12 "Игорь Лабутин" И для того, чтобы это все поиспользовать, вы просто его ставите, dotnetcore.cap пакет называется, он тут поддерживает огромное количество очередей, надо напомнить, что такое outbox. +4857.12 4866.68 "Игорь Лабутин" Outbox - это когда вы вместе с основной транзакцией записи в вашу базу пишете в вашу же базу сообщение, которое надо отослать, а потом какой-то worker это сообщение таки отсылает куда-нибудь там, в какую-нибудь кавку, рэббит и еще кого-нибудь. +4866.68 4877.92 "Игорь Лабутин" Тут поддерживается и кавка, и рэббит, и эйджер, и амазон, и нац, и редис, и пульсар, а в качестве баса - сиквел, и майсиквел, и позгрей, и монго, ну и тут много чего еще. +4877.92 4884.36 "Игорь Лабутин" Короче, тут довольно простой интерфейс, если вам нужен outbox и вам лениво его писать самому, то пожалуйста. +4884.36 4890.60 "Игорь Лабутин" Причем он судя по всему, судя по тому, что тут есть всякие атрибутики капсабскрайб и вот это все, он еще и подписываться на что-то умеет. +4890.60 4898.84 "Игорь Лабутин" То есть он может и по архитектурной схеме, он, короче, может стоять на двух сторонах вашего outbox'а, в смысле и на отправляющей, и на принимающей стороне. +4898.84 4901.04 "Игорь Лабутин" В общем, интересно. +4901.04 4908.12 "Анатолий Кулаков" Интересно, что по языкам здесь есть Vue и JavaScript, то есть у него еще какая-то и красивая мордочка, видимо, +4908.12 4909.12 "Игорь Лабутин" есть. +4909.12 4941.04 "Игорь Лабутин" Да, там есть дэшборд в отдельном пакете, не бойтесь, вы не затащите никакой vue.js в ваш бэкэнд, то есть это отдельный пакет, кап.дэшборд, если я правильно помню, называется, который позволяет, видимо, посмотреть, как это все живет, работает, может, какую-то статистику я не смотрел, но библиотечка интересная, я про нее не слышал раньше, мы как-то outbox всегда руками писали, но надо посмотреть, может, действительно полезно, если оно отлажено, работает, звездочек много, issues'ов не так много открытых, это значит, что либо никто не пользуется, но по звездочкам вроде пользуются, либо значит, автор хорошо, молодец, быстро закрывает, фиксит все. +4941.04 4954.68 "Игорь Лабутин" Так что вот такое вот внезапное отвлечение, наверное, на техрадар, который в этот раз мы довольно редко, мне кажется, последний раз перед этим мы смотрели на 28-ой что ли, то есть это получается года полтора-два назад, что это был 31-ый. +4954.68 4965.00 "Анатолий Кулаков" Да, там что-то попадалось такое про dotnet, хотя непонятно, как они, если все везде любят раст, как они эту библиотечку с outbox'ом запихнут в свое приложение. +4965.00 4992.64 "Игорь Лабутин" Ну, непонятно, непонятно, у меня такое ощущение, что, ну, собственно, это не ощущение, мне кажется, то, как техрадары строятся, то есть они же компания, да, они же консультанты, то есть вот они поработали полгода, ну вот за полгода у них было много раста, вероятно, и, наверное, им попался какой-нибудь dotnet-ный проект, в котором они либо увидели эту библиотеку, либо ее заюзали, потому что им нужен был outbox, посмотрели, что это хорошо и решили, что это надо рекомендовать. +4992.64 4999.48 "Игорь Лабутин" Ну, тоже метод, даже просто их, по сути, список, чего они рекомендуют, это не то, что там вся индустрия обязана пользоваться. +4999.48 5001.60 "Игорь Лабутин" Просто хорошая практика. +5001.60 5020.40 "Анатолий Кулаков" Ну, безусловно, нужно слушателям понимать, что это какой-то опыт определенный одной компании, это никаким образом не влияет ни на индустрию, ни на другие компании, ни на популярность библиотек, ни на что, просто компания довольно авторитетная и интересная, которая впервые выдумала этот самый техрадар, и за ней таким образом по интуиции все до сих пор следят. +5020.40 5052.00 "Игорь Лабутин" Ну и надо сказать, что вообще сама по себе идея хорошая, то есть если вы достаточно крупная компания, в которой есть там развесистый стек, то такую штуку полезно регулярно делать внутри компании самим, чтобы смотреть, следить за актуальным стеком, обновлять, иметь некоторые рекомендации, что мы используем, что не используем, чтобы знать, на каких версиях каких продуктов вы живете, ну или фреймворков, библиотек, какие подходы вы используете, и все такое прочее, чтобы идти в ногу со временем или наоборот не слишком его опережать. +5052.00 5055.04 "Анатолий Кулаков" Да, так и есть. +5055.04 5069.08 "Анатолий Кулаков" Так, чтобы нам идти в ногу со временем, не поверишь, у нас вторая статья с Хаббера, то как бы не дожидались мы целый год, а тут прям две сразу, ну, наверно авторы просыпаются после лета, загорелые, вдохновленные. +5069.08 5094.04 "Анатолий Кулаков" И вторую статью с Хаббера мы нашли, которую написал Александр Кузнецов, называется она "Тюнинг запросы в EF-корс с помощью интерсепторов", а статья не то чтобы глубокая или мега страшная, просто она очень полезная, потому что как раз-таки не все разработчики знают о том, на что способен их Entity Framework, и поэтому могут упускать много возможностей, которые уже встроены в их фреймворк. +5094.04 5122.64 "Анатолий Кулаков" На самом деле, Entity Framework очень мощный механизм, и с каждым новым релизом в нем добавляется еще множество-множество всего, поэтому если вдруг вы захотите каким-то образом в вашем приложении очень глубоко использовать этот фреймворк, то стоит, наверное, сесть и разобраться в нем, то есть по Entity Framework прям отдельно очень много книг даже выходит, и в книгах там тоже раскрываются такие аспекты, о которых рядовой разработчик наверняка никогда бы не узнал в своей жизни, если бы не пошел специально это копать. +5122.64 5155.80 "Игорь Лабутин" А еще, я тебя перебью, извини, что хорошо и полезно знать внутренности, чтобы не было некоторых неправильного понимания, наверное, вот так скажу, потому что когда я видел заголовок этой статьи, я сначала продумал про интерсепторы, которые фичи языка, и долго думал, каким образом фичи языка, которые, помните, интерсепторы, когда вы можете заинтерсептировать вызов произвольной функции с помощью source-генератора, сгенерив специальный атрибут со ссылкой на номер строки, и думаю, как так интересно, запросы-то приятные, чего-нибудь будут. +5155.80 5160.08 "Игорь Лабутин" Сейчас мы будем там что-нибудь переписывать в source-генераторах запросы. +5160.08 5179.64 "Игорь Лабутин" Ну вот, чтобы вы знали, чтобы вы так не путали, нужно знать, что внутри F-Core свои интерсепторы, и терминология очень полезна, когда вы работаете, ну, короче, да, когда вы работаете с каким-то фреймворком, знать вообще, что в нем бывает, чтобы вот так вот не путаться. +5179.64 5184.00 "Анатолий Кулаков" Да, чтобы понимать вообще, куда это вообще относится, куда коней запрягать. +5184.00 5190.92 "Анатолий Кулаков" В принципе, интерсепторы в Entity Framework'е появились еще до файл-генераторских интерсепторов. +5190.92 5196.08 "Анатолий Кулаков" Грубо говоря, в ASP.NET'е вот эти, те же самые middleware, их тоже можно назвать интерсепторами в своем-то виде. +5196.08 5197.08 "Игорь Лабутин" Почему бы и нет? +5197.08 5202.24 "Игорь Лабутин" Ну, по логике, да, просто что по названию я их как-то никогда не пользовал в F-Core, и поэтому я напрочь забыл. +5202.24 5206.80 "Игорь Лабутин" Только уже когда начинаешь читать статьи, думаешь, а, точно, ну, что-то было такое, но мне как-то никогда не надо было. +5206.80 5208.84 "Игорь Лабутин" Давай послушаем, зачем это, может быть, надо. +5208.84 5212.40 "Анатолий Кулаков" Ну, и как раз объявимся, что же это такое, чтобы в следующий раз вы их не путали. +5212.40 5214.44 "Анатолий Кулаков" Итак, начнем сначала. +5214.44 5230.40 "Анатолий Кулаков" Entity Framework — это довольно-таки богатый фреймворк, и он обладает богатыми возможностями по преобразованию вашей объектно-ориентированной модели, ваших DTO-шек, ваших объектных доменных сущностей в язык запросов, так, когда вы запрашиваете каких-нибудь юзеров и так далее. +5230.40 5241.48 "Анатолий Кулаков" И иногда бывает таким образом, что вам не хватает этих запросов, потому что, как ни крути, Entity Framework — это некое среднее, это пересечение между всеми базами данных. +5241.48 5248.44 "Анатолий Кулаков" Если мы берем любую базу данных, то в общем случае она будет мощнее, чем Entity Framework, у нее будет больше возможностей, она больше всего будет уметь. +5248.44 5256.72 "Анатолий Кулаков" Но так как Entity Framework пытается объединить под своим крылом множество датабайс-провайдеров, он выбирает всю середину, которая есть. +5256.72 5267.84 "Анатолий Кулаков" Поэтому иногда вы хотите чего-то, что Entity Framework не поддерживает, а конкретная база данных, которая используется в вашем приложении, это поддерживает, и как-то кажется странным терять эту возможность. +5267.84 5272.36 "Анатолий Кулаков" И чтобы решить эту проблему, есть несколько вариантов. +5272.36 5277.04 "Анатолий Кулаков" Наверное, самый популярный — это писать SQL-запросы напрямую. +5277.04 5279.00 "Анатолий Кулаков" Entity Framework это позволяет. +5279.00 5282.88 "Анатолий Кулаков" Второй вариант — это использовать хранимые процедуры. +5282.88 5290.68 "Анатолий Кулаков" Еще не ясно, что из этого хуже, но опять же, если вы спускаетесь на такой низкий уровень, то с этим имеется куча проблем. +5290.68 5310.28 "Анатолий Кулаков" Это, наверное, тема для другой отдельной статьи, почему сырые SQL-запросы — это плохо, но как показала практика, большинство компаний используют именно ORM в нашей инфраструктуре, как раз потому, что они поняли все плюсы ORM и не хотят лезть во все минусы ручного написания запросов и тем более хранимых процедур. +5310.28 5318.80 "Анатолий Кулаков" Поэтому у нас есть третий выход, который избавляет нас от того, чтобы писать вручную SQL-код и каким-то образом сопровождать хранимые процедуры. +5318.80 5321.08 "Анатолий Кулаков" Третий выход — это как раз-таки интерсепторы. +5321.08 5336.84 "Анатолий Кулаков" Интерсепторы — это некие перехватчики, которые помогают вам немножко расширить функциональность, ту, которая идет из коробки к Entity Framework, немножко расширить функциональность благодаря тому, что вы в вашем приложении обладаете знаниями конкретной базы данных, которые вы используете. +5336.84 5343.12 "Анатолий Кулаков" То есть Entity Framework сама это сделать не может, а вы можете, потому что вы знаете, что у вас за база данных под капотом. +5343.12 5346.96 "Анатолий Кулаков" Давайте же разберемся на примере, каким же образом это сделать. +5346.96 5352.16 "Анатолий Кулаков" Автору понадобилась необходимость добавить специальный оператор forUpdate. +5352.16 5357.72 "Анатолий Кулаков" В PostgreSQL такой оператор поддерживается, а в Entity Framework не поддерживается. +5357.72 5359.00 "Анатолий Кулаков" Что такое forUpdate? +5359.00 5361.24 "Анатолий Кулаков" Это достаточно такая простая штука. +5361.24 5386.48 "Анатолий Кулаков" Например, если мы хотим выбрать некое подмножество каких-то записей для того, чтобы их в будущем изменить, добавляя специальное окончание forUpdate, мы сообщаем базе данных, что эти записи заблокированы для другого запроса forUpdate, который попытается их изменить. +5386.48 5391.60 "Анатолий Кулаков" Это немножко похоже на пессимистичную блокировку, которую мы обсуждали с вами несколько статей ранее. +5391.60 5396.42 "Анатолий Кулаков" То есть это такая своеобразная блокировка берется на все эти записи. +5396.42 5410.80 "Анатолий Кулаков" И пока мы эти записи этим forUpdate не отпустили, то есть по сути, пока мы не закрыли транзакцию, в которой вызван этот forUpdate, другой select forUpdate эти записи взять не сможет. +5410.80 5414.40 "Анатолий Кулаков" Таким образом, мы получаем вот такой пессимистичный лог. +5414.40 5423.80 "Анатолий Кулаков" Записи мы с forUpdate забираем, изменяем, сохраняем, закрываем транзакцию, и следующий клиент, уже следующий поток, следующий concurrency какой-то агент уже может дальше работать с этими записями. +5423.80 5430.32 "Анатолий Кулаков" Итак, вроде все понятно, концепция простая, и на уровне кода она реализуется точно так же, все довольно просто. +5430.32 5435.24 "Анатолий Кулаков" Естественно, необходимо добавить специальные ключевые слова forUpdate в конец запроса, в конец запроса селекта. +5435.24 5441.68 "Анатолий Кулаков" Да, то есть вы получаете select, rollie, valise, from users, forUpdate, и все, в этом принципе и все, что нам нужно сделать. +5441.68 5448.52 "Анатолий Кулаков" Итак, попробуем же научить Entity Framework добавлять вот такой префикс в конечный запрос, который он генерирует в базу данных. +5448.52 5453.48 "Анатолий Кулаков" На самом деле кажется, что это довольно сложно, потому что Entity Framework большой, мощный, много всего умеет. +5453.48 5463.56 "Анатолий Кулаков" Но на самом деле он большой и мощный не только потому, что много всего умеет, но и потому, что в нем очень хорошо продуманы различные точки расширения, которые вы можете делать из своего приложения. +5463.56 5467.00 "Анатолий Кулаков" Поэтому данное расширение тоже работает довольно просто. +5467.00 5476.20 "Анатолий Кулаков" И точек расширения таких очень много, да, интерсепторы это всего лишь одна из таких точек, но нам она лучше всего подходит. +5476.20 5477.20 "Анатолий Кулаков" Что же такое интерсепторы? +5477.20 5484.32 "Анатолий Кулаков" Это специальный промежуточный код, который позволяет вам модифицировать запрос до того, как этот запрос уйдет в базу данных. +5484.32 5489.44 "Анатолий Кулаков" Для того, чтобы нам создать такой интерсептор и подключить его и использовать, нам необходимо сделать три шага. +5489.44 5492.20 "Анатолий Кулаков" Ну, во-первых, это объявить сам класс интерсептора и наполнить его какой-то логикой. +5492.20 5497.00 "Анатолий Кулаков" Во-вторых, зарегистрировать интерсептор в нашем датабейс-контексте. +5497.00 5503.88 "Анатолий Кулаков" И в-третьих, это понять тот момент, а когда нужно этот интерсептор применить, то есть в какой момент он должен сработать. +5503.88 5509.76 "Анатолий Кулаков" Если же вы хотите, чтобы он применялся на каждый ваш запрос, то в принципе последний пункт вам не нужен. +5509.76 5514.68 "Анатолий Кулаков" Но обычно вы хотите, чтобы он применялся не на каждый запрос. +5514.68 5519.00 "Анатолий Кулаков" В нашем случае, в For Update, мы не хотим его добавлять, например, к делитам. +5519.00 5521.68 "Анатолий Кулаков" Более того, мы не хотим его добавлять ко всем селектам. +5521.68 5529.12 "Анатолий Кулаков" Мы хотим его добавлять только к селектам, которые мы пометили каким-то специальным атрибутом для того, для For Update. +5529.12 5536.44 "Анатолий Кулаков" То есть у нас уже какое-то маленькое подмножество запросов должно попадаться, попадать под наш интерсептор. +5536.44 5545.52 "Анатолий Кулаков" Начнем с самого сложного пункта, это как раз таки с понимания того, какие запросы мы должны модифицировать с помощью нашего интерсептора. +5545.52 5554.00 "Анатолий Кулаков" В самых простейших случаях, например, как в нашем, мы можем воспользоваться таким прикольным методом, как tag_div. +5554.00 5561.92 "Анатолий Кулаков" У любого iQueryable интерфейса есть метод tag_div, который принимает в качестве параметра обычную строчку. +5561.92 5566.72 "Анатолий Кулаков" И все, что он делает, это раскладывает эту строчку в SQL-комментарий. +5566.72 5568.64 "Анатолий Кулаков" Это, например, полезно для диагностики. +5568.64 5577.68 "Анатолий Кулаков" Когда вы посылаете какой-то запрос в базу данных, то Quantity Framework вам пишет в логах, какой запрос он сделал. +5577.68 5586.36 "Анатолий Кулаков" И, например, в логах вы можете с помощью метода tag_div добавить какой-то понятный для вас комментарий. +5586.36 5591.44 "Анатолий Кулаков" Например, указать какой-нибудь Trace ID, из-за которого породился этот SQL-запрос. +5591.44 5595.44 "Анатолий Кулаков" Или добавить текущего пользователя, который инициировал этот SQL-запрос. +5595.44 5598.44 "Анатолий Кулаков" В общем, какую-то добавочную интересную информацию. +5598.44 5601.08 "Анатолий Кулаков" То есть обычный комментарий к SQL. +5601.08 5611.24 "Анатолий Кулаков" В нашем же случае, в принципе, мы можем проанализировать этот tag_div, то есть, что этот комментарий мы туда добавили, и каким-то образом в интерсепторе, допустим, на это среагировать. +5611.24 5615.28 "Анатолий Кулаков" Таким образом, мы можем написать метод расширения, который называется for_update. +5615.28 5617.40 "Анатолий Кулаков" Этот метод расширения будет iQueryable. +5617.40 5626.56 "Анатолий Кулаков" И в этом методе расширения, в его реализации мы просто добавим tag, который в качестве параметра принимает строчку for_update. +5626.56 5630.00 "Анатолий Кулаков" То есть это какой-то специальный ключ для нашего будущего интерсептора. +5630.00 5632.80 "Анатолий Кулаков" Мы его просто передаем iQueryable, и все. +5632.80 5637.56 "Анатолий Кулаков" И больше, в принципе, никаких задач нам делать не нужно. +5637.56 5638.56 "Анатолий Кулаков" Дальше. +5638.56 5639.92 "Анатолий Кулаков" Как же этот метод расширения использовать? +5639.92 5640.92 "Анатолий Кулаков" Очень просто. +5640.92 5645.44 "Анатолий Кулаков" Вызываете у вашего DB-контекста метод users, допустим, если вы хотите выбрать всех пользователей. +5645.44 5650.00 "Анатолий Кулаков" Определяете какие-нибудь там условия, where user_id = id. +5650.00 5651.00 "Анатолий Кулаков" Пишите .for_update. +5651.00 5657.80 "Анатолий Кулаков" В этот момент вызывается наш метод расширения, и под капотом добавляет специальный SQL-комментарий. +5657.80 5660.36 "Анатолий Кулаков" Теперь перейдем к написанию самого интерсептора. +5660.36 5670.92 "Анатолий Кулаков" Для того, чтобы написать свой интерсептор, нам нужно пронаследоваться от стандартного интерфейса или базового класса DBCommandInterceptor и перекрыть всего лишь на всего один метод. +5670.92 5673.16 "Анатолий Кулаков" В нашем случае это reader_executing. +5673.16 5682.60 "Анатолий Кулаков" Как раз этот интерсептор, этот метод вызывается как раз в тот момент, когда мы подготавливаем запрос для чтения из базы данных. +5682.60 5684.64 "Анатолий Кулаков" Что же мы можем здесь сделать? +5684.64 5695.12 "Анатолий Кулаков" На данном этапе у нас существует некий объект DBCommand, у которого есть common_text, и этот common_text содержит полный SQL-запрос, тот, который сейчас пойдет в базу данных. +5695.12 5705.56 "Анатолий Кулаков" Автор предлагает нам просто-напросто взять этот common_text с помощью метода contains, понять, есть ли в нем тот SQL-оператор, который мы поставили, то есть в нашем случае contains for_update. +5705.56 5711.36 "Анатолий Кулаков" И если вдруг он есть, мы просто в конец текста добавляем ключевые слова for_update. +5711.36 5714.52 "Анатолий Кулаков" Вот, в принципе, вся реализация, буквально в три строчки. +5714.52 5734.60 "Анатолий Кулаков" Ну, тут предположение довольно смелое, то есть, действительно, метод contains я бы, наверное, заменил все-таки на ends_with, потому что если мы будем обновлять в базе данных фамилию юзера, и эта фамилия будет называться --for_update, то данный интерсептор тоже нам что-нибудь нехорошее сделает. +5734.60 5754.16 "Анатолий Кулаков" Ну и также, то есть нужно проверить прежде всего, что этот for_update, компилятор где-нибудь должен, for_update комментарий должен быть где-нибудь там внизу или в самом верху, в общем, как-то более подстраховаться, наверное, или, может быть, стоит уже как-то синтаксически проанализировать, именно семантически, то есть проанализировать данный запрос, а не просто contains-ом полагаться. +5754.16 5759.48 "Анатолий Кулаков" Но в общем случае, в принципе, подход рабочий, почему бы и нет. +5759.48 5766.28 "Анатолий Кулаков" Если все остальные условия вас не пугают, то пожалуйста, то есть мы просто добавляем ключевой текст в конец нашего запроса. +5766.28 5771.16 "Анатолий Кулаков" И самое последнее, что нам осталось сделать, это просто-напросто зарегистрировать наш интерсептор. +5771.16 5772.16 "Анатолий Кулаков" То есть это тоже элементарно. +5772.16 5787.96 "Анатолий Кулаков" В наследнике db_context, вашем application db_context, при регистрации провайдера, при указании там, где вы ему указываете connection string, вы просто вызываете ключевое слово add_interceptor и туда передаете ваш новый созданный красивый испеченный интерсептор. +5787.96 5796.64 "Анатолий Кулаков" Теперь во время каждого запроса ваш интерсептор будет вызываться, и он сам будет определять, хочет он этот запрос модифицировать, если хочет, то как он его будет модифицировать. +5796.64 5801.44 "Анатолий Кулаков" Итак, интерсепторы довольно такая полезная, мощная, интересная штука. +5801.44 5808.76 "Анатолий Кулаков" И если бы их не было, то вам бы пришлось больше писать чистого скейтс-кода или чистых хранимых процедур. +5808.76 5817.40 "Анатолий Кулаков" Ну, в общем, в любом случае, вы бы спустились в этот низкоуровневый мир, и вам бы навалилась большая тонна проблем после этого. +5817.40 5829.08 "Анатолий Кулаков" Интерсепторы же помогают остаться вам все-таки в менеджмент мире, все-таки остаться на каких-то ORM-ках, управлять вашими сущностями, как вы к этому привыкли, и при этом расширять функциональность до прямо низкоуровневых протоколов. +5829.08 5832.92 "Анатолий Кулаков" Также стоит отметить, что существует множество разных интерсепторов. +5832.92 5857.92 "Анатолий Кулаков" Кроме command-интерсептора, который мы рассмотрели, есть connection-интерсепторы, которые позволяют управлять коннекциями, то есть соединениями с базой данных, есть transaction-интерсепторы, которые позволяют там джонглировать транзакциями в различных их семантических значениях, в общем, много красивых интересных интерсепторов, которые позволяют не только там расширять, допустим, все электронные апдейты и делиты, и менять типы, и в общем, много-много всего интересного можно с ними поделать. +5857.92 5873.56 "Анатолий Кулаков" Поэтому если вдруг вам нужно немножко подрегулировать entity-framework для того, чтобы он генерил какие-то новые скейт-запросы, или каким-то образом транзакции обрабатывал по-особому, или логировал все коннекции, в общем, то посмотрите в сторону интерсепторов, довольно богатый и мощный механизм. +5873.56 5907.12 "Игорь Лабутин" Единственный момент, который я хочу отметить, что если вы будете использовать интерсепторы вот с тем подходом, как показано в статье, то есть через теги, то вы можете, надо внимательно посмотреть, чтобы не потерялась еще одна полезная возможность, потому что вот эти самые теги интересно и полезно использовать, чтобы каким-то образом отличать запросы друг от друга, то есть у нас, например, одно время использовались вот эти конструкции with text, они явно были написаны, туда дописывался комментарий по сути о том, что это за запрос, кратко. +5907.12 5918.92 "Игорь Лабутин" Тогда у вас в логах или в SQL-серверных логах или еще где-то просто видны эти названия запросов, даже если у вас запрос отрезан в конце, вам все равно по первому комментарию видно, что это был за запрос. +5918.92 5931.72 "Игорь Лабутин" И вот если вы теги начинаете использовать для таких интерсепторов, то нужно будет внимательно посмотреть, чтобы вы правильно их находили и нужные теги заменяли на дописывание запроса в нужном месте. +5931.72 5932.72 "Игорь Лабутин" Вот. +5932.72 5933.72 "Анатолий Кулаков" Это просто. +5933.72 5946.12 "Анатолий Кулаков" Ну, текущая реализация, кажется, твоему примеру не противоречит, она, ну, мы можем много использовать тегов, и она их, ну, и она ключевое слово, этот ключевой строков update просто в конец записывает, поэтому все остальные теги останутся на месте. +5946.12 5951.80 "Игорь Лабутин" Ну да, да, главное, чтобы не было конфликта с чем-нибудь еще. +5951.80 5952.80 "Игорь Лабутин" Вот. +5952.80 5958.32 "Игорь Лабутин" Хорошо, давай пойдем напоследок расскажем у нас кратко о разном. +5958.32 5966.88 "Игорь Лабутин" Тут накопилось немножечко статей, не статей, и начнем мы с tools, опять же. +5966.88 5989.48 "Игорь Лабутин" Мы, наверное, давно уже не касались всяких разных дампов для дотнета, того, как это все собирать, как это все анализировать, но если вы этим занимались, вы наверняка знаете такой tool procdump из комплекта sysinternals, отличных тулов от Марка Русиновича, которые позволяют на винде творить много чего полезного. +5989.48 6023.88 "Игорь Лабутин" У нас были доклады на dotnext давно уже про то, что некоторые из этих тулов, прокмон, например, перенеслись на линукс, и у них существует линукс-версия, так вот теперь появилась версия procdump для macOS, то есть если вы вдруг запускаете ваше дотнет-приложение на macOS, и вам хочется собрать дампы, напомню, что procdump он умеет собирать очень умно, его можно настроить до первого исключения или до конкретного, или еще как-то, или по памяти собрать вам дамп, или по времени, в общем, полезная штука, теперь она есть на macOS, можно пользоваться. +6023.88 6024.88 "Игорь Лабутин" Дальше. +6024.88 6081.36 "Игорь Лабутин" Есть библиотечка, у нас, кстати, это, наверное, один из немногих выпусков, где вы еще ни разу не сказали слово dotnetspire, исправляемся, появилась библиотека, называется dotnetspire-community-toolkit, видимо, это те интегрейшены, то есть те самые расширения для dotnetspire, которые не нашли или по какой-то причине не были включены в основной комплект dotnetspire, я напомню, что основные интегрейшены живут в самом репозиторе dotnetspire, но здесь живут другие, и там, в частности, там живет всякие джаваскриптовые штуки типа bana, dno, gotem живет, java со спрингом, node.js, ollama, rust, в общем, всякие, если вы хотите вот такие штуки подключить к вашему ispire-проекту, вам в этот самый dotnetspire-community-toolkit возможно в этом что-то найдете. +6081.36 6082.36 "Игорь Лабутин" Далее. +6082.36 6113.00 "Игорь Лабутин" У нас есть в дотнете командлайновый способ создать новый проект из шаблончика, называется dotnetnew, дальше можно выбрать какой шаблон вам нужен, и что-то там сделать, но был запрос, я не знаю откуда, что нам нужен новый interactive CLI tool, то есть в dotnetnew, как правило, вы практически все передаете командлайн, там он вам спрашивает пару вопросов, но в целом обычно большую часть всего передаете командлайн. +6113.00 6136.28 "Игорь Лабутин" Здесь же это теперь interactive новый tool появился, называется dotnetscaffold, пока это превьюшка, устанавливается как обычно global tool, сейчас поддерживает пока ispire.net core, webapp, webapi и dotnetspire с blazor, то есть если вы хотите какой-то более такой wizard-стайл создания новых приложений из шаблонов, посмотрите в сторону dotnetscaffold, возможно вам понравится. +6136.28 6141.08 "Анатолий Кулаков" При том из командной строки, не просто там wizard какой-нибудь с кнопочками, а командно-строковый wizard. +6141.08 6147.24 "Игорь Лабутин" Interactive CLI tool, прям подчеркнуто, то есть это как бы ньюайны, да, все в командной строчке. +6147.24 6174.28 "Анатолий Кулаков" Опять же, немножко страшно, странно, да и страшно тоже, потому что обычно в языках scaffold это немножко другое, это штука, которая помогает тебе, например, у существующего приложения добавить, допустим, контроллер, который протянется в модельку и который зарегистрируется в базу данных и который сгенерит миграцию, вот это scaffold, а то, что мы создаем что-то с нуля, это уже больше какой-то действительно new, и лучше бы они там dotnet.new как-нибудь расширили, добавили бы и флажок interactive или что-нибудь в этом духе. +6174.28 6179.72 "Игорь Лабутин" Ну может потом переименуют и сделают его view, а scaffold за view, не знаю, посмотрим. +6179.72 6221.20 "Игорь Лабутин" Дальше, мы уже сегодня обсуждали статью Кристофа Назара про то, как сделать собственный профайлер узкоспециализированный, есть такой товарищ Александр Мютл, он периодически делает какие-то доклады, ну и вообще низкоуровневый товарищ про dotnet, он тоже сделал свой собственный профайлер, он доступен только на Windows, потому что он работает на Event Tracing for Windows, ему был нужен, я так понимаю, некоторый аналог perfview в каком-то смысле в более красивом виде, плюс который умеет работать одновременно и с ядерными функциями, и с нативным кодом, и с managed, короче, все вместе. +6221.20 6295.44 "Игорь Лабутин" В итоге он написал профайлер, который в качестве UI, ну чтобы не париться, использует профайлер из Firefox, то есть на самом деле он просто генерит некоторые трейсы в формате, который умеет понимать профайлер.firefox.com, это всякие там, как раз там будут, как они называются, flame graph и вот это все, короче, все умеется, там довольно неплохой UI, вот, он умеет профайлер в смысле категоризировать функции, что это dotnet, dotnet.jit, dotnet.garbage.collector, native, kernel, как-то умеет трекать память, умеет понимать где когда срабатывал JIT с точки зрения compile time и какую функцию он в этот момент компилировал, знает ивенты от garbage.collector, всякие allocation ticks и прочее, при этом довольно легковесный, как написано, ну он генерит всего несколько мегабайт за 10 секунд работы, вот, но единственное, что требует восьмого дотнета или позднее, ставится через dotnet global tool install, если вам нужен какой-то очень развесистый профайлер, точнее не столько развесистый, сколько профайлер, который хорошо умеет с нативным кодом и внутрянкой дотнета работать, вот возможно, а перфю вы боитесь по какой-то причине или непонятно, как с ним работать, вот посмотрите на эту штуку, может вам понравится. +6295.44 6317.52 "Игорь Лабутин" И последнее от меня, это забавный сайтик, я на него возлагал, ну как не сайтик, это очередной гитхаб репозиторий, такие встречаются практически для разных технологий, это build with maui, мы с тобой много раз про мауи говорили, про то, что ну что-то как-то развивается непонятно как, непонятно как, а есть ли какие-то продукты, которые на нем написаны. +6317.52 6318.52 "Игорь Лабутин" Ну в общем, короче, я нашел. +6318.52 6320.52 "Анатолий Кулаков" Да, это хороший список, ну-ка, сколько там продуктов +6320.52 6321.52 "Игорь Лабутин" нахуй? +6321.52 6324.44 "Игорь Лабутин" Там 27 приложений, я не знаю ни одного. +6324.44 6328.84 "Игорь Лабутин" Это хороший показатель того, что нахуй никому этот мауи не нужен. +6328.84 6339.08 "Игорь Лабутин" Ну то есть, там они довольно узкоспециализированы, то есть там типа, какое-то приложение для что-то типа трекинга сна или что-то в таком духе, какое-то приложение для скалолазания. +6339.08 6362.20 "Игорь Лабутин" Ну то есть, конечно, очень узкоспециализированные приложения для ios и андроида в основном, там с указанием количества скачиваний, некоторые даже довольно неплохо скачиваются, там на десятки тысяч идет речь, но десятки тысяч в разрезе как бы плеймаркета и апстора ios, это мне кажется очень немного, надо сказать, там действительно какое-то узкоспециализированное. +6362.20 6373.16 "Игорь Лабутин" То есть, в общем, они есть, но их как-то очень пока мало и ничего суперизвестного я там не нашел, даже, ладно, супер, уберем приставку, ничего хоть как-то известного мне я не нашел. +6373.16 6374.16 "Игорь Лабутин" Такие дела. +6374.16 6375.16 "Игорь Лабутин" Да, жалко мауи, жалко. +6375.16 6376.16 "Анатолий Кулаков" Ну что, пойдем дальше? +6376.16 6396.36 "Анатолий Кулаков" Я хотел еще в коротко-разном немножко упомянуть парочку докладов, потому что у нас как бы есть рубрика «Прослушано», в которой мы обсуждаем о том, о чем поговорили другие подкасты, другие люди, а свои, собственно, лекции те, которые мы курируем и делаем, мы почему-то никогда не освещаем. +6396.36 6403.28 "Анатолий Кулаков" Мне кажется, это несправедливо, поэтому вот с сотой, сотого митапа уже, мне кажется, мы начнем это делать. +6403.28 6404.28 "Анатолий Кулаков" О чем я говорю? +6404.28 6427.92 "Анатолий Кулаков" Мы в том числе участвуем в группе, которая тренирует докладчиков на .NET.RU всякие митапы, в частности на SPB.NET митап, и в этом году у SPB.NET митапа случился сотый выпуск, то есть мы уже сто раз собирались, и на каждом из этих митапов читаются уникальные, классные, интересные доклады, которые авторы сами изобретают, сами исследуют, сами рассказывают, сами готовят. +6427.92 6431.40 "Анатолий Кулаков" Именно поэтому они такие аутентичные и довольно занимательные. +6431.40 6438.88 "Анатолий Кулаков" В частности, чтобы вы понимали, о чем я говорю, и могли бы, может быть, тоже расширить свой кругозор, если вдруг тема вам интересна. +6438.88 6448.84 "Анатолий Кулаков" На сотом выпуске на юбилейном у нас выступил Дмитрий Нестрюк, который рассказал про разработку с использованием искусственного интеллекта, как раз то, на чемся хайпит последние годы весь мир. +6448.84 6469.20 "Анатолий Кулаков" Вот Дмитрий проанализировал, насколько это разработчикам полезно или не полезно, как это можно использовать в своей работе, куда это движется, и, в общем, такой практически философский доклад получился на весь митап, то есть на три часа почти, с рассуждениями о том, как это можно применять и куда нужно смотреть. +6469.20 6478.60 "Анатолий Кулаков" Дальше есть доклад, вышел за запись Евгения Пешкова, это о синхронности не только о синковой, в котором Женя как раз таки рассказала, что еще можно знать про синхронность. +6478.60 6485.68 "Анатолий Кулаков" И если вам так же точно интересно, о чем Женя Пешков внутри про синхронность мог рассказать, то обязательно посмотрите. +6485.68 6489.64 "Анатолий Кулаков" У него доклады всегда свежие, интересные и полны каких-нибудь новых мыслей. +6489.64 6500.20 "Анатолий Кулаков" Станислав Сидристый у нас был с рассказом о том, как писать плагины к сервисам и как сделать безопасное расширение функциональности в нашем 21-м веке. +6500.20 6520.68 "Анатолий Кулаков" Когда-то в свое время, мне кажется, любое приложение обязательно выпускалось с помощью плагинов, более того, если мы делали какой-нибудь DI-контейнер, который подключал компоненты, то если у такой DI-контейнера не была возможность динамически в рантайме сканить диск и находить там какие-то сборки, подключать эти сборки в виде плагинов, то это считался плохой DI-контейнер. +6520.68 6543.68 "Анатолий Кулаков" К счастью, те времена уже довольно-таки давно прошли, плагины уже не так популярны, как раньше, то есть каждый разработчик не мечтает сделать свою плагинную систему, но все-таки плагины никуда не делись и некоторым системам их все еще делать нужно, все еще поддерживать нужно, а после того, как Microsoft обрубил поддержку апдоменов .NET Core, может быть, для некоторых неочевидно, а как же, собственно, их делать. +6543.68 6552.08 "Анатолий Кулаков" Оказывается, есть современные техники, как делать классные, хорошие, изолированные плагины, которые хорошо в рантайме подгружаются, более того, даже выгружаются. +6552.08 6555.96 "Анатолий Кулаков" В общем, обязательно посмотрите доклад Станислава Сидористова, если вам это интересно. +6555.96 6572.84 "Анатолий Кулаков" Андрей Порожняков рассказывал у нас про nativeout, тот доклад, который сегодня как раз-таки уже был отрекламирован, если вам вдруг интересен nativeout, интересно, откуда он берет такую шикарную производительность относительно основного большого .NET, а также какие подводные камни с ним связаны, в общем, в докладе Андрея вы все это увидите. +6572.84 6577.20 "Анатолий Кулаков" Дмитрий Георгов рассказывал нам про использование AWP в .NET. +6577.20 6588.76 "Анатолий Кулаков" В общем, здесь тоже тема довольно узкая, но достаточно интересно, если аспект на ориентированное программирование тоже каким-то образом вас касается, то доклад Дмитрия расскажет вам про много вещей, о которых вы даже не знали. +6588.76 6604.68 "Анатолий Кулаков" Александр Гальдебаев рассказывал про Aspire in Action, поэтому Aspire Aspire, если вдруг вы до сих пор не знаете, что это, как это, с чем это едят, то, наверное, самый большой и самый глубокий обзор из лекций на русскоязычном языке, который есть, представлен в этом докладе. +6604.68 6651.56 "Анатолий Кулаков" Виктор Греков читал доклад про анализ дампов, с чего начать, поэтому если вы вдруг боитесь дампов или профайлеров, про которые мы сегодня уже не раз упоминали, не знаете, что это такое, зачем они используются и в какое место их засовывать, то вот как раз доклад Виктора продемонстрирует вам о том, что это достаточно хороший инструмент, и он удобен для, может быть, каждодневного даже использования, он удобен для того, чтобы просто посмотреть, как ваша программа работает, что в ней происходит, и в критический момент, когда настанет день ЖО, вы уже будете знать, каким образом пользоваться дампером, пользоваться профайлером, куда копать, где лезть, и вообще научитесь как профессионал использовать весь свой инструмент разработчика в таком шикарном ключе, как анализ дампов или анализ профайлеров. +6651.56 6665.76 "Анатолий Кулаков" Я напомню, что все эти доклады можно будет найти на ютубе в группе dotnet.ru, также все ссылочки у нас будут в шоу-ноутах, поэтому заходите, смотрите, комментируйте, лайкайте, а мы будем вас знакомить с будущими докладами, которые продолжим делать. +6665.76 6691.92 "Анатолий Кулаков" Я напомню, что митапы у нас проводятся во многих городах, в частности, в СПБ, в Санкт-Петербурге мы делаем регулярно каждый месяц, если вы вдруг будете проездом в нашей культурной столице, то посмотрите, может быть, как раз в даты вашего посещения мы будем делать очередной митап, все они бесплатные, интересные, поэтому заходите на огонек, мы всегда рады посетителям других городов, ну и если вы из Петербурга и почему-то никогда не были у нас в гостях, тоже приходите, будем рады каждому. +6691.92 6700.60 "Игорь Лабутин" А если вы хотите что-нибудь рассказать, то мы точно будем рады, заходите, с удовольствием поможем и дадим возможность выступить. +6700.60 6704.48 "Анатолий Кулаков" Ну вот так хорошо и подкаст провели, да, и себя порекламировали. +6704.48 6705.48 "Анатолий Кулаков" Да, куда ж без этого. +6705.48 6706.48 "Анатолий Кулаков" Это все митапы. +6706.48 6726.32 "Игорь Лабутин" Ну да, значит, на этом мы, наверное, будем на сегодня завершать, мы попробовали сделать короткий выпуск у меня на тайминге 1 час 47, что получится после монтажа я не знаю, но больше полутора часов мы точно, видимо, получим подкаст, так что да, наши планы, как всегда, не оправдываются, но как с любыми оценками в программировании, надо умножать. +6726.32 6733.04 "Анатолий Кулаков" Мы подкаст завершать не будем, а будем еще тренироваться и тренироваться, то есть там есть куда расти, перспективы большие. +6733.04 6780.92 "Игорь Лабутин" Чтобы наши оценки совпадали с реальными ситуациями к концу подкаста, но тем не менее, за сегодня мы обсудили, какие у нас бывают подходы к оптимистичным и пессимистичным блокировкам и какие, может быть, альтернативы можно рассмотреть, посмотрели, как сделать довольно низкоуровневый такой полупрофайлер, чтобы понять какие-то внутренности того, как работает в данном конкретном случае HttpClient, порассуждали на тему, что не так с дотнетом в Яндекс.Клаудфункшнз и какой подход выбрать, если вы хотите размещать там дотнет-приложения, посмотрели кратенько на Technology Radar 31 выпуск, поразбирались с тем, как тюнить запросы в EF Core с помощью интерсепторов, ну и кратенько пробежались по всяким разным мелким тулам и статьям. +6780.92 6784.56 "Игорь Лабутин" На этом, кажется, 105-й выпуск подошел к концу. +6784.56 6785.56 "Анатолий Кулаков" Кажется да. +6785.56 6795.56 "Анатолий Кулаков" В общем, всем до новых встреч, подписывайтесь на наши каналы, ставьте комментарии, там лайки, репосты, скинуться на апельсины и кефир можно на Boosty, в общем, все вы знаете. +6795.56 6796.56 "Анатолий Кулаков" До новых встреч, пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-118.txt b/input/Radio/Transcriptions/RadioDotNet-118.txt new file mode 100644 index 0000000..511ef91 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-118.txt @@ -0,0 +1,523 @@ +0.00 10.80 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Радио.нет и выпуск номер 118. +10.80 13.72 "Анатолий Кулаков" В студии его постоянный ведущий Анатолий Кулаков. +13.72 14.72 "Игорь Лабутин" И Игорь Лабутин. +14.72 15.72 "Игорь Лабутин" Всем привет. +15.72 20.24 "Анатолий Кулаков" А за нашими плечами бравые помогаторы, которые поддерживают любимый подкаст. +20.24 39.92 "Анатолий Кулаков" Среди них Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий и Анатолий Крыжановский. +39.92 44.64 "Анатолий Кулаков" Большое спасибо всем, друзья, что поддерживаете нас, а также всем тем, кто пожелал остаться неизвестными. +44.64 47.20 "Анатолий Кулаков" У нас на Boost много всего интересного, приходите, +47.20 48.20 "Игорь Лабутин" смотрите. +48.20 54.80 "Игорь Лабутин" А также нас продолжает поддерживать компания Altenar, разработчик надежных решений для индустрии спортивных данных, которыми пользуются по всему миру. +54.80 66.76 "Игорь Лабутин" В основе большинства продуктов, конечно же, лежит .NET и C#, инженеры работают с высоконагруженным реалтаймом и живо и динамично обсуждают идеи без каких-то длительных и долгих согласований. +66.76 74.08 "Игорь Лабутин" Разработка компании международная, можно качать английский, можно использовать всякие удобные IDE, облачные платформы. +74.08 80.48 "Игорь Лабутин" Ребята активно делятся опытом, проводят митапы, выступают с докладами и следить за их новостями можно в их телеграм-канале. +80.48 93.24 "Анатолий Кулаков" Ну что ж, я думаю, мы с тобой начнем летний выпуск на расслабончике и поболтаем о каком-нибудь кодревью или менеджментах или процессах, а ты первой темой прям хочешь зарядить нам про Garbage Collector. +93.24 94.24 "Анатолий Кулаков" Нормально вообще? +94.24 105.24 "Игорь Лабутин" Да, сегодняшний выпуск, действительно, когда мы готовили темы, я взял, думал, парочку легких статей, ну так, типа обзорно, посмотрю, пробегусь, что-нибудь обзорненько расскажу. +105.24 115.12 "Игорь Лабутин" Оказалось, в общем, что у меня получилось две довольно глубоких статьи, забегая вперед, ну, в общем, у Анатолия не меньше, мне кажется, тоже сегодня такой будет выпуск. +115.12 122.76 "Игорь Лабутин" Ну, Microsoft спит, что-то, ну или отдыхает, не знаю, никаких релизов не делает, никаких превью не выходит, так что перебиваемся, чем можем. +122.76 125.44 "Игорь Лабутин" Будете слушать про Garbage Collector в C#. +125.44 131.16 "Анатолий Кулаков" Я, по крайней мере, со своей стороны старался хоть что-то полегче выбрать, а ты, похоже, даже не старался. +131.16 153.28 "Игорь Лабутин" Не, вообще, взял первое попавшееся, и первое попавшееся это серия статей от Кевина Госса, они на самом деле довольно уже древненькие, он их начал писать еще в начале 25-го года, но у него вышло пять статей, по ощущениям должны быть еще, потому что тема осталась не до конца раскрытой, но даже эти пять уже достойны того, чтобы на них посмотреть. +153.28 200.92 "Игорь Лабутин" И идея заключается в чем, Кевин пытается разобраться в том, как работают разные прикольные штуки в Дотнете и вокруг Дотнета, у него уже была серия статей, мы на нее особо не смотрели, насколько я помню, может я ее где-то упоминал только вкратко о разном, про то, как писать профайлер на C#, там довольно очень глубокая и сложная для такого аудиообзора тема, в этот раз статья или серия статей, точнее, про то, как писать garbage collector на C#, естественно, в практическом смысле статья довольно бесполезна, в смысле вы не будете использовать такой garbage collector нигде в живой работе, это чисто для себя, для того, чтобы поинтересоваться, как же оно все работает внутри и немножко получше узнать внутренности. +200.92 269.68 "Игорь Лабутин" Нечто похожее когда-то делал Конрад Кокоса в виде .next доклада, ну он не только в виде .next доклада, он сам по себе делал garbage collector под названием zero.gc, но тогда он писался все-таки на плюсах, насколько я помню, и был он предназначен для того, чтобы в принципе понять, как можно встроить кастомный garbage collector в .net, а здесь garbage collector написан на C#, и возникает, естественно, когда вы задумываетесь о том, что garbage collector написать на C#, но ведь тот код, который будет написан на C#, тоже требует garbage collector, не получим ли мы здесь рекурсию, и действительно, мы бы эту рекурсию получили, если бы у нас не было такого классного режима, как native auth, который все компилирует в некоторый статический бинарник, который уже не требует никаких внешних зависимостей, и по факту, если вы напишите garbage collector на .net, но скомпилируете его native auth компилятором и получите DLL, то ее вы можете потом закидывать в другое приложение на .net, и у вас внутри вашего приложения на .net будет работать garbage collector, который тоже написан на .net, но внутри native auth бинарника, вот так уж сложно. +269.68 277.04 "Анатолий Кулаков" Это круто, да, когда кто-то будет спрашивать, зачем вам нужен этот native auth, вот нормальный практический пример, чтобы писать good session. +277.04 280.84 "Игорь Лабутин" Давай поспорим со словом нормальный, но практический пример. +280.84 281.84 "Игорь Лабутин" Ладно. +281.84 285.36 "Игорь Лабутин" Почему еще нам нужен native auth? +285.36 312.04 "Игорь Лабутин" Ну, он еще нужен потому, что даже если бы, например, по какой-то причине мы могли бы заиспользовать тот же managed runtime, грубо говоря, под которым работает основное приложение, но дело в том, что этот самый managed runtime инициализируется настолько рано, что там еще нет никакого managed хода, и garbage collector должен быть уже к тому моменту инициализирован, поэтому приходится его писать на чем-то нативном, либо на чем-то, что может быть скомпилировано в нативный код. +312.04 314.60 "Игорь Лабутин" Давайте потихонечку разбираться. +314.60 320.68 "Игорь Лабутин" Для начала нам нужно понять, если мы хотим написать свой собственный garbage collector, нам нужна какая-то API. +320.68 325.80 "Игорь Лабутин" Ну, мы же не можем просто взять и куда-то встроиться, если это что-то не позволяет встраиваться. +325.80 351.88 "Игорь Лабутин" Ну, наверняка опции какие-нибудь есть, да, там патчеры всяких экзешек всегда существовали, но в данном случае мы все-таки пытаемся встроиться в API, и у нас такая возможность есть, начиная с dotnet core 2.1, в дотнете было добавлено API для garbage collector, нам нужно всего лишь сделать делельку, которая содержит всего лишь два метода, gc_initialize и gc_version_info, и, в общем-то, все, дело сделано, звучит очень просто. +351.88 355.00 "Игорь Лабутин" Зачем же нам нужно 5 статей, и это еще не все. +355.00 356.00 "Игорь Лабутин" Что мы делаем? +356.00 369.64 "Игорь Лабутин" Для начала мы делаем, естественно, самый простой hello world, в смысле кода, который хотя бы хоть что-то скомпилируется, будет представлять из себя якобы garbage collector, который ничего не делает, кроме того, что пишет на экран, что меня проинциализировали, и больше ничего. +369.64 393.16 "Игорь Лабутин" Ну что, берем девятый dotnet, создаем class library project, добавляем любой класс, на самом деле, имя там абсолютно неважно, добавляем два метода, поскольку мы в итоге должны получить делельку, которая будет вызываться, ну, по сути, из нативного кода, то нам нужно эти методы выставить не как managed методы в каком-то классе, а как unmanaged методы. +393.16 432.44 "Игорь Лабутин" Для этого в dotnet есть специальный атрибут, называется unmanaged colors only, мы добавляем два метода, помечаем их этим атрибутом, в этот атрибут как раз передается название, под которым его будет видно, мы туда как раз и задаем название gc_initialize и gc_version_info, и делаем ничего, в gc_version_info не делаем вообще ничего, в gc_initialize делаем console.writeline, напоминаю, мы же пишем garbage collector на dotnet, т.е. мы хотим внутри кода использовать managed primitives, т.е. мы пишем console.writeline и что-нибудь там, меня пронициализировали, ну, можно вывести что-нибудь из каких-нибудь аргументов, которые нам передали, но это не обязательно, пусть хотя бы hello world выведется. +432.44 534.48 "Игорь Лабутин" Собираем это все дело dotnet publishing с нужным, соответственно, идентификатором runtime, ну, у Кевина все это на винде дело, поэтому dotnet publish -r windfisx64, копируем эту длл-ку в папочку приложения, вспоминаем какую-нибудь статью Маони, где написано используйте переменную dotnet_gc_name для того, чтобы указать имя длл-ки, а еще есть опция, оказывается, я, кстати, про нее не знал до чтения этой статьи, что можно указать dotnet_gc_path и указать прям полный путь к длл-ке garbage collector, это главное не обязанно лежать в той же папке, где приложение, запускаем и оно замечательно падает, ну, в принципе, это ожидаемо, потому что наш garbage collector не делает ничего, кроме того, что пишет Console.WriteLine, а кроме того, там нужно еще вернуть код возврата, и мы там везде возвращаем явный фейл, то есть, ну, как это, вполне ожидаемо, что dotnet наше приложение падает, но начинаем разбираться, и становится интересно, падает оно не совсем потому, что мы ожидали, вроде как, ну, crash в Console.WriteLine, ну, все, как бы, вроде нормально, но, во-первых, а почему crash в Console.WriteLine, а во-вторых, если внимательно посмотреть на стэк вызова, который приводит к этому Console.WriteLine, то мы увидим, что первый вызов в garbage collector, он происходит в метод gc_version_info, напомним, version_info у нас пустой, но мы каким-то образом оказываемся в gc_initialize, из которого уже вызывается наш Console.WriteLine, что-то не то, и оказывается, что делается следующее. +534.48 567.44 "Игорь Лабутин" Как только мы вызываем gc_version_info из нашего менедж приложения, это все, естественно, ну, как бы, менедж приложения корректно понимает, что нужно загрузить нашу сборку, нашу DLL, но наша DLL это же native-out приложение, поэтому любой вызов в нашу DLL триггерит инициализацию всего native-out рантайма, и он, в общем-то, пытается проинициализировать свой собственный gc, который, напоминаю, вкомпилен внутри native-out бинарника. +567.44 582.12 "Игорь Лабутин" Пока все вроде нормально, ну как бы он бы проинициализировался и дальше бы вызвал наш version_info из нашего gc, но в процессе инициализации этого самого внутреннего gc мы оказываемся в инициализаторе нашего gc, что-то не то. +582.12 583.12 "Игорь Лабутин" Начали разбираться. +583.12 597.00 "Игорь Лабутин" Ну, идея номер один, мы же указали, gc в виде .net подчеркивает gc_name, как его использовать, ну, так, наверное, native-out тоже подхватил эту переменную и к себе тоже загрузил garbage коллектор. +597.00 602.08 "Игорь Лабутин" С одной стороны, вроде разумно, с другой стороны, это вроде как native-out, он внутри себя все должен скомпилить. +602.08 622.36 "Игорь Лабутин" Смотрим повнимательней в исходники .net, к счастью, они нам все доступны, и выясняем, что native-out технически позволяет, его можно явно включить, режим загружает gc внешний, но по дефолту это все выключено, и пока вы не измените csproj, это не включить никакими переменными окружения, то есть это точно не причина. +622.36 642.12 "Игорь Лабутин" Правильная причина заключается в другом, когда мы собираем наш garbage-коллектор.dll, поскольку это native-out, то там есть шаг под названием линковка, кто программировал на плюсах, помнит, сначала компиляция, потом линковка, где-то там в серединке еще какие-нибудь оптимизации могут быть. +642.12 672.28 "Игорь Лабутин" Так вот, когда мы линкуемся, линкер видит вызов, ну ему нужно в том месте, где будет происходить инициализация native-out runtime, нужно вставить вызов к gc-initialize, и у него есть на выбор два gc-initialize, один, который, собственно, прилетел из того managed-on-time, в котором, которым компилится native-out, ну то есть тот, который должен быть, а второй наш, тот самый gc-initialize, который мы сами написали, ну и что вы думаете, выбирает линкер? +672.28 674.64 "Игорь Лабутин" Ну, конечно же, наш, а не тот, который должен. +674.64 684.76 "Игорь Лабутин" В итоге получается, что native-out, код инициализации native-out нашей dll вызывает сам себя, ну gc-initialize в самом себе, по сути. +684.76 691.32 "Игорь Лабутин" Ну и, естественно, падает, потому что какой Console.WriteLine внутри кода, который еще даже не инициализирован до manage-состояния. +691.32 700.68 "Игорь Лабутин" Ну, в общем, как-то что-то не сработало, и пошел Кевин искать проблемы, в смысле, как это все сделать. +700.68 733.88 "Игорь Лабутин" Можно сделать довольно кривоватым способом, ну то есть он работает, он нормальный способ в принципе, это написать небольшой C++-ный враппер, который как раз таки и будет экспозить эти самые методы gc-initialize gc-version-info, внутри нашей dll-ки экспозить их как-нибудь по-другому, там my gc-initialize my-version-info, это тогда решит проблему с линкером в момент сборки нашего garbage-коллектора, а для нашего .NET приложения тестового мы будем указывать этот враппер в качестве gc, а он уже будет динамически подгружать правильную dll-ку. +733.88 742.28 "Игорь Лабутин" Но во-первых, это целых две dll-ки нужно иметь, а во-вторых, это нарушает нашу идею, что типа нам нужно писать на все-таки managed-коде, но в целом это работает. +742.28 801.28 "Игорь Лабутин" Можно сделать очень кривым путем, значит, кривой путь заключается в следующем, давайте включим тот самый поддержку внешнего garbage-коллектора для native-out-приложений, то есть мы внутри нашего css-proj, который для нашего garbage-коллектора, задаем proper-to elc standalone gc-support-vtrue, о, ну хорошо, после этого наше native-out-приложение, ну либо dll-ка, начинает понимать тот самый переменный dotnet_gc_name для загрузки стандартного, ну или любого другого gc, и если в dotnet gc_name указать село gc_dll, это стандартный dotnet-ский garbage-коллектор, то все хорошо, native-out его загрузит, но наше же приложение тоже будет смотреть на эту же переменную, мы же живем в одном процессе, и он тоже загрузит стандартный gc, как бы это не требуется нам, нам нужно, чтобы он загрузил правильный gc, наш кастомный. +801.28 845.32 "Игорь Лабутин" И здесь нашелся очень клевый, ну не клевый, ладно, кривой трюк, который позволил это сделать, смотрите, если вы помните, если вы достаточно давно программируете на dotnet, то может быть помните, что в dotnet раньше все вот эти переменные окружения, которые задают какое-то runtime-поведение, они начинались с префикса com+, com+ там подчеркивает что-нибудь, ну тут gc_name, а более, ну в какой-то момент, не помню в какой версии, был добавлен вот этот самый префикс dotnet, подчеркиваю, и все бы здорово, но наш обычный runtime, он умеет понимать и те и другие, то есть он на самом деле ищет переменные dotnet, подчеркиваю, и com+, подчеркиваю. +845.32 869.24 "Игорь Лабутин" Причем dotnet, подчеркиваю, имеет больший приоритет, то есть если вы зададите две переменных окружения, dotnet gc_name и com+ gc_name, то будет использоваться та, которая с префиксом dotnet, а nativeout, runtime, почему то, не знаю почему, смотрит только на dotnet префиксы, то есть вот nativeout приложению, com+ префикс, нафиг не нужен. +869.24 889.52 "Игорь Лабутин" Это с одной стороны, теперь с другой стороны, напомню, что у нас есть два метода задать переменные, в смысле кастомный garbage collector, либо через gc_name, либо через gc_path, и gc_path вариант имеет более высокий приоритет через gc_name, чем gc_name. +889.52 926.64 "Игорь Лабутин" Внимательный слушатель, наверное, уже понял, хотя я надеюсь, в смысле я сомневаюсь, что такие сходы есть, на слух мне кажется воспринимать это ужасно, что если задать две переменные, одну назвать dotnet gc_name, туда передать кастомный gc, в смысле стандартный gc, а в com+ gc_path передать кастомный gc, то nativeout runtime подтянет dotnet gc_name и туда загрузит стандартный garbage collector, а обычная приложенька за счет того, что gc_path имеет больший приоритет, загрузит com+ gc_path и загрузит кастомный gc. +926.64 934.68 "Игорь Лабутин" Если кто-то еще не запутался, продолжаем дальше, потому что этот кривой способ, Кевин проверил, он работает, но на самом деле есть правильный путь. +934.68 941.88 "Игорь Лабутин" Правильный путь, ну, не знаю, на мой вкус он тоже такой довольно кривоватый, но тем не менее. +941.88 943.60 "Игорь Лабутин" Делаем следующую конструкцию. +943.60 951.40 "Игорь Лабутин" Берем эти функции, которые, напомню, название этих функций, которые мы экспозим из нашего garbage collector, и называем их по-другому. +951.40 953.76 "Игорь Лабутин" Ну, какой-нибудь там my.gc, что-нибудь. +953.76 963.56 "Игорь Лабутин" Пишем msbuildtask, которая переименует эти функции непосредственно перед стадией link_native, и тогда все становится хорошо. +963.56 975.44 "Игорь Лабутин" То есть, функции экспозятся правильно, но в момент линковки там все будет нормально, и они будут все еще со старым названием. +975.44 982.16 "Игорь Лабутин" Короче, способ порекомендован, я так понимаю, каким-то то ли инженером из рантайма, то ли каким-то близким к этому добрую чуваком. +982.16 990.44 "Игорь Лабутин" Способ немножко странный, догадаться до него, ну, не знаю, насколько это можно, видимо, только зная глубоко о рантайме, но тем не менее он работает. +990.44 1006.80 "Игорь Лабутин" Кевин сказал, да, окей, будем использовать этот способ, пытаемся запустить наше приложение, оно теперь наконец-таки пишет нормально, этот самый консольный райтлайн какой-нибудь hello world, ну и дальше, естественно, падает, но это как раз ожидаем, потому что мы, собственно, никакого gc пока еще не реализовали. +1006.80 1011.04 "Игорь Лабутин" Идем дальше, начинаем учиться реализовывать gc. +1011.04 1014.52 "Игорь Лабутин" Первое, что нужно сделать, это уметь анализировать память. +1014.52 1044.88 "Игорь Лабутин" В garbage collector, как я сказал, функций всего две, но это же, как обычно, да, функции-то две, но они там внутри передают четыре поинтера на интерфейсы, из которых один поинтер нам, как разработчикам garbage collector, предоставляет рантайм, он называется igc_to_clr, это методы, которые gc может использовать для контроля над рантаймом, мы их немножко коснемся чуть дальше, и три интерфейса, которые надо реализовать, igc_heap, igc_handle_manager и igc_handle_store, всего три штуки, которые надо реализовать. +1044.88 1072.16 "Игорь Лабутин" С gc_handles, gc_handle_store, там все просто, если только мы не начинаем двигать объекты в памяти, но ни про какой компактинг пока речи не идет, но сама суть gc_handles все-таки нам нужна, это некоторая структура, которая содержит тип handle, адрес, куда ссылается этот handle, и некоторые экстра-инфа, там, набор байтиков, грубо говоря. +1072.16 1088.12 "Игорь Лабутин" С начала первой реализации мы тупо аллоцируем массив на 10 тысяч этих handles, делаем interlock-инкремент индекса как-то каждый раз, когда нужно что-то зааллокейтить, выбираем следующий элемент, если элементы в массиве кончились, фейлим, нафиг, все, приложение, установим память кончилось. +1088.12 1097.44 "Игорь Лабутин" Handle_manager интерфейс, тоже довольно простая штука, это просто набор методов для доступа к handle_store, почему их разделили, не очень понятно. +1097.44 1109.56 "Игорь Лабутин" gc_heap более интересный интерфейс, там в нем всего лишь порядка 88 методов, там чуть больше, чуть меньше зависимости от версии, но нам реально нужно реализовать несколько всего. +1109.56 1126.88 "Игорь Лабутин" Во-первых, мы реализуем метод initialize, это очень важный метод, это собственно тот метод, где garbage_collector пытается понять, посчитать количество куч, вот это вот все, и одно из важных вещей — это место, где мы задаем так называемый write_barrier. +1127.08 1150.20 "Игорь Лабутин" Напомню, из теории, так скажем, garbage_collector в дотанте, или точнее того, как он внутри реализован, те, кто изучал это дело, наверняка сталкивались с такой темой, как cart_table, то есть это некоторая специальная оптимизация, которая позволяет чуть упростить жизнь garbage_collector, чтобы понимать, какие объекты была произведена запись с момента прошлого garbage_collection. +1150.20 1173.40 "Игорь Лабутин" Для того, чтобы это все оптимизировать, runtime пишет этот cart_table, и этот cart_table нужно ему предоставить, но в workstation-варианте, если мы реализуем workstation_gc, его можно немножко не то что обмануть, а сделать так, чтобы этот cart_table никто никогда не писал, в server.gc так не получится, там нужно аллоцировать cart_table, это пока не наш вариант, поэтому в initialization, если мы понимаем, что это server.gc, мы как бы падаем и говорим, мы в таком режиме не работаем. +1173.40 1223.72 "Игорь Лабутин" Дальше, самый главный метод, конечно, alloc, ну тут нужно собственно зааллоцировать, и с ним есть некоторая тонкость, что alloc, он не просто аллоцирует память под то, что попросили, он опять же для оптимизации работает с location-контекстами, то есть runtime работает следующим образом, он у garbage_collector просит некие location-контексты, это фиксированные наборы памяти обычно в x-килобайт, грубо говоря, в эти x-килобайт отдаются памяти, отдаются рантайму, и рантайм в нем сам по большому счету аллокейтит объекты, просто инкрементируя pointer, на каждый thread свой location-контекст, когда location-контекст заканчивается, или если объект, который нужно аллоцировать, слишком большой, рантайм снова приходит в garbage_collector и говорит "да еще". +1223.72 1260.64 "Игорь Лабутин" Вот соответственно нужно все это упражнение с location-контекстами аккуратненько проделать, вернуть, дальше есть еще один не менее важный метод garbage_collect, который пока не будет делать ничего, и вот уже такой garbage_collector, мы можем запустить на нем наше приложение, какое-нибудь тестовое консольное приложение работает, и более того, Кевин даже взял какое-то sample приложение из OrHardCore CMS-ки, и оно даже заработало, то есть если приложение не очень большое и аллоцирует меньше 10000 GCH, так или иначе, то в целом, пока память не кончится, оно даже на таком garbage_collector будет работать. +1260.64 1299.84 "Игорь Лабутин" А вот дальше начинается интересное, с одной стороны, и если вам интересно, как это все работает дальше, я очень советую это начинать с третьей части, идти читать статью, потому что третья часть относится к такой штуке как traversing the trees, то есть напомню, что идея у нас tracing garbage_collector, то есть у нас есть некоторое количество объектов, которые называются корни, или gc_roots, это те объекты, которые как правило лежат в каких-нибудь статических переменных, на стейке, или еще где-то, а дальше нужно уметь обрабатывать эти объекты, если в них есть ссылки на дочерние объекты, нужно уметь ходить по ним, ну и так далее. +1299.84 1314.76 "Игорь Лабутин" А для того, чтобы это делать, нам нужно вообще понимать, что за тип перед нами, какой вообще тип объект, потому что для нас же это просто, нас попросили аллоцировать xbyte, и все, мы не знаем ни типа, ничего. +1314.76 1440.72 "Игорь Лабутин" Осталось бы в менедж-коде, мы же знаем, как у нас расположена в дотнете вся типоинформация, берем, говорим, просто get_type позвать не можем, но мы можем с помощью магии поинтеров куда-то сходить, понять вот это все, но даже поняв, где лежит информация о типе, мы на самом деле ее прочитать нормально не можем, потому что фактически это другой рентайм, то есть наш garbage_collector работает как дотнет-приложение, но оно не имеет доступа к методандам рентайма, в котором работает основное приложение, потому что это два разных рентайма фактически, и у них нет никаких общих типов, поэтому нам надо что-то делать, можно сделать то, что Кевин назвал cooperative way, и даже это реализовал, то есть мы можем сказать, что окей, мы же экспериментируем, это в продакшене не будет использоваться, поэтому в нашем приложении мы можем предоставить метод для получения информации о типе, каким-то образом в jc.dll его закинуть в начале работы приложения, ну и наше приложение, соответственно, наше ГЦ, сможет тогда делать вызовы, они получаются нативные по сути, для того, чтобы выполнить код, который находится в основном приложении, и получить информацию о типе, но тут возникает проблема, код, который мы напишем в основном приложении, он скорее всего будет менеджд, а изнутри garbage_collector менедж код вызывать нельзя, а как правило в этот момент трейды находятся в состоянии, потому что возможно у вас куча там наполовину в каком-нибудь corrupted состоянии, потому что garbage_collector что-то куда-то двигает объекты, менедж код в этот момент запускать никак нельзя, для этого есть специальный режим потока, собственно дождавшись которого garbage_collector и переходит к сборке, но напомню, что у нас есть тот самый интерфейс igc_to_clr, который как раз позволяет сказать, что ага, вот в этом потоке вот сейчас мы возвращаем возможность запускаться менедж коду, выполнить тот самый callback в основное приложение, получить информацию о типе, вернуть обратно правильный, это называется preemptive mode, и после этого дальше заниматься своими garbage_collector делами. +1440.72 1499.22 "Игорь Лабутин" Все хорошо, но с одной стороны требует какие-то работы со стороны приложения, с другой стороны вызывая такой менедж код даже на одном трейде нет никаких гарантий, что код в приложении не пойдет куда-то и не попадет в какое-нибудь странное сломанное место кучи, поэтому есть способ лучше, смотрите, нам нужно смотреть на менедж объекты из unmanaged кода, для этого вообще говоря у нас существует как бы tool, который так уже умеет делать довольно давно и он называется дебаггером, то есть runtime в принципе умеет такое делать через дебаггер API, ну вот как раз таки мы это будем делать, дальше там экрана 3 кода про то, как это сделать через дебаггер API, не буду я уж вам его рассказывать, там довольно такая запутанная логика и интерфейс, в каком порядке что вызвать надо, но в итоге таким образом через дебаггер API у рантайма нашего основного приложения можно добыть информацию о типах. +1499.22 1633.08 "Игорь Лабутин" Хорошо, сделали, переходим к четвертой части, теперь нам нужно еще понимать, для того чтобы делать travers3 это все здорово, но допустим выяснили через travers3 мы отметили каким-то образом все объекты, которые живы, это хорошо, но нам нужно узнать еще про объекты, которые внезапно остались не живы, на них-то ссылок нет, но они лежат в куче, для этого нам нужна операция под названием, как сказать-то, вхождение по куче, walking the heap, то есть нам нужно проитерироваться по всей куче, найти все объекты, они напомню уже последовательно, потому что локатор внутри location контекста тупо incremented pointer, поэтому нам нужно для каждого объекта знать его размер, и для этого тут как раз пригодится информация о типах, нам нужно знать размер каждого объекта, и соответственно аккуратненько это дело пройти по каждому location контексту, найти все объекты, убедиться есть там к нему доступ или нет из рутов, и если нету, то там начинается интересная фаза компактинга, которая пока еще не описана, есть еще две части с татьи, в которые я не буду вдаваться, потому что там уже начинается совсем хардкорный код, который очень сложно описывать голосом, я конечно могу, но зачем, одна часть это сегменты, то есть напомню, что начиная с относительно недавних версий дот наэта, с какой, с шестерки, с семерки, что-то я уже не помню, был включен режим сегментов, это когда мы вместо того, чтобы балансировать большой так называемый ephemeral сегмент, который включал себе и нулевой и первое поколение, и был размером сотни иногда мегабайт, мы живем в небольших сегментах одинакового размера, обычно это 4 мегабайта, но там в зависимости видимо от количества процессоров, битности и объема оперативной памяти может тюниться, и все кучи нулевого первого и второго поколения, ну в смысле объекты нулевого первого и второго поколения, они живут каждый в одинаковых на самом деле сегментах, и некоторые сегменты, например, если мы понимаем, что объект переходит из нулевого сразу во второе поколение, мы просто объявляем, что это сегменты второго поколения, и все, и не нужно ничего никуда двигать. +1633.08 1751.72 "Игорь Лабутин" Так вот, для того, чтобы получше понять всю эту механику, сегменты Кевин тоже сделал, и дальше уже приступил к оптимизации прохода по вот этим вот референс графам, потому что для того, чтобы ходить по графам объектов, нужно вообще понимать, а где у каждого объекта лежат ссылки, напомню, в памяти это же просто массив байт, нам нужна та самая информация о типе, но если мы будем каждый раз полностью парсить всю информацию о типе, это на самом деле довольно дорого, потому что в типе лежит огромное количество информации, вернее не так, в классе вы можете держать огромное количество полей, которые никак не относятся к garbage-коллектору, то есть у вас там будет огромное количество каких-нибудь интов, флагов там, даблов и прочего ненужного структурно, struct-like, так скажем, да, типов, которые никак не влияют на поведение garbage-коллектора, вам нужна только информация, по каким смещениям лежат реальные ссылки на другие потенциальные объекты, для этого есть тоже механизм, для этого используется структуру gcdesk, ну gcdescriptor, который, соответственно, для каждого типа описывает, по каким смещениям, грубо говоря, лежат ссылки на другие потенциальные объекты именно с помощью этой структурки, этой информации, сохраняющейся там, можно оптимально достаточно обходить граф ссылок, это была последняя часть, соответственно, которая у Кевина описана и есть подозрение, что все-таки там какой-нибудь, какой-никакой компактинг или что-то подобное должен появиться, потому что вроде как он планировал сделать нормальный mark and sweep garbage-коллектор, так что либо там все дальше слишком сложно, либо он пока отвлекся на какие-то другие дела, либо еще что-то, но в общем это все, to be continued, следим за новостями, если там будут новые части выходить, но мы, по крайней мере, их упомянем, конечно же, может быть, даже обозреем, если там будет что-то разумное и рассказываемое, а не то, как там в двух последних частях выглядит код, который очень сложно рассказывать. +1751.72 1814.80 "Игорь Лабутин" И общий вывод статей на данный момент примерно такой, для того чтобы понять, как это все работает, это прям очень хороший вариант, при этом видно, как в данном случае API-шка garbage-коллектор, то есть как бы runtime никогда не писался с прицелом на то, что garbage-коллектор будет подменять, из API-шки garbage-коллектор, который между runtime и garbage-коллектором торчат уши прям, ну там нет никакой абстракции, торчат уши нативного родного garbage-коллектора, того, как написано он, и если мы захотим туда встроить что-то другое, что, например, не работает с card-tables, а работает с чем-то другим, это прям не очень понятно, как делать, потому что вот runtime очень тесно и подробно знает про то, как работает нативный обычный .NET-овский garbage-коллектор, так что шансов, что у нас появится какой-то прям супер-пупер другой garbage-коллектор вроде как пока довольно мало, но если вам интересно разобраться в структуре, в том, как это работает, отличный, мне кажется, способ. +1814.80 1820.08 "Анатолий Кулаков" Может быть, знаешь, это и хорошо, что у нас таких шансов довольно мало, не будет мыка выбора. +1820.08 1833.64 "Игорь Лабутин" Может быть, может быть, отсутствие выбора тоже иногда неплохо, если дефолтный вариант работает достаточно неплохо, а у нас он, ну по крайней мере в последние года я не слышал, чтобы были какие-то супербольшие проблемы с перформансом со стороны garbage-коллектора. +1833.64 1847.88 "Анатолий Кулаков" Тем более вот эта связка, когда АГЦ знает хорошо про runtime, она как раз и позволяет делать всякие низкоуровневые оптимизации, которые при большом сроке слоя абстракции точно бы начали течь и давали бы какой-нибудь деградацию перформанса. +1847.88 1849.88 "Игорь Лабутин" Да, возможно так, возможно так. +1849.88 1861.44 "Игорь Лабутин" Ну либо нужно очень тщательно продумывать, как изолировать и абстрагировать ГЦ от runtime и runtime от ГЦ, чтобы он был, а, с одной стороны, позволял оптимизации, б, при этом все-таки было абстрагировано. +1861.44 1862.44 "Игорь Лабутин" Не знаю. +1862.44 1867.16 "Игорь Лабутин" В принципе, в Java как-то сделано и сделано неплохо, насколько я понимаю. +1867.16 1875.48 "Игорь Лабутин" Нормально работает с точки зрения перформанса, ну и у нас, в принципе, неплохо, так что изучаем, смотрим, подождем, чего нам родят дальше в будущем. +1875.48 1878.56 "Анатолий Кулаков" Ну для общего развития тема, безусловно, прекрасная. +1878.56 1880.56 "Анатолий Кулаков" Хорошо, пойдем дальше. +1880.56 1884.36 "Анатолий Кулаков" Я бы хотел рассказать про курсор pagination. +1884.36 1893.00 "Анатолий Кулаков" Вот, в принципе, такой довольно резкий свитч с низковыровневым перформансом на какие-то, больше таки, постраничные веб-аппликушки. +1893.00 1895.20 "Анатолий Кулаков" Но все же. +1895.20 1897.72 "Анатолий Кулаков" Итак, давайте начнем. +1897.72 1899.48 "Анатолий Кулаков" Вообще, для чего нужна пагинация. +1899.48 1902.68 "Анатолий Кулаков" Есть у тебя, Игорь, хорошее русское слово для пагинации? +1902.68 1904.68 "Анатолий Кулаков" То как-то аж противно произносить. +1904.68 1905.68 "Анатолий Кулаков" Постраничный вывод. +1905.68 1906.68 "Анатолий Кулаков" Одно слово. +1906.68 1907.68 "Анатолий Кулаков" Постраничный вывод через дефис. +1907.68 1908.68 "Игорь Лабутин" Постраничность. +1908.68 1909.68 "Игорь Лабутин" Постраничность, да, выводность. +1909.68 1917.92 "Анатолий Кулаков" Короче, в общем, постраничность, выводность нужна современным приложениям. +1917.92 1929.48 "Анатолий Кулаков" Я думаю, с этим никто спорить не будет, потому что мы оперируем большими какими-то блоками данных, большими датасетами, и пользователю неудобно видеть сразу миллиард записей перед глазами, да и вообще бесполезно. +1929.48 1934.08 "Анатолий Кулаков" Поэтому была изобретена такая великая вещь, как постраничность. +1934.08 1949.72 "Анатолий Кулаков" Вы видите данные по страницам, и есть несколько способов как организовать это с точки зрения бэкэнда, фронтэнда, и среди них два самых популярных, это оффсет страничность и постраничность на основании курсора, курсор бейст. +1949.72 1957.36 "Анатолий Кулаков" Оффсет более популярна, ее все знают, я думаю, любого Джуна на собесе спроси про оффсет страничности, он вам обязан ее рассказать. +1957.36 1969.44 "Анатолий Кулаков" А вот курсор бейст уже не так популярный, многие не знают, хотя она имеет ряд бенефитов по сравнению с оффсет постраничностью. +1969.44 1977.36 "Анатолий Кулаков" Например, она позволяет в реальном времени отображать фиды, которые появляются, ну то есть какие-то ивенты, которые идут прямо сейчас. +1977.36 1992.20 "Анатолий Кулаков" Она позволяет реализовать бесконечный скролл, что в принципе невозможно на постраничности, ну некрасиво будет выглядеть на постраничной реализации, и у нее есть некие бенефиты по перформансу. +1992.20 2013.24 "Анатолий Кулаков" Таким образом, курсор бейст постраничность, она очень хорошо применяется, например, для показа в социальных сеточках таймлайна, то есть вот этой стены, которая с бесконечными всякими ивентами, для того, чтобы смотреть какие-нибудь блоги, которые активно появляются у вас с предлазками, и также для того, чтобы работать с большими наборами данных. +2013.24 2015.44 "Анатолий Кулаков" Мы сейчас все это по баряточку рассмотрим. +2015.44 2033.80 "Анатолий Кулаков" Итак, наши примеры будут базироваться на основании таблички с пользовательскими заметками, там будет ссылка на пользователя, боди самой заметки, для нас важны самое главное два поля — это ID-шник, который типогует, и дата у этой заметки, которая была. +2033.80 2044.44 "Анатолий Кулаков" Реализовать мы все это будем на базе данных Postgres, но в принципе-то подходы везде одинаковые, поэтому это можно применить к любой практически базе данных. +2044.44 2055.60 "Анатолий Кулаков" В базе данных у нас для тестов будет миллион записей, мы потом посмотрим execution планы и убедимся, что там, ну посмотрим, что там на уровне перформанса, но пройдемся как бы с самого высокого уровня до самого низкого. +2055.60 2061.80 "Анатолий Кулаков" Итак, начнем с offset-ной постраничности, чтобы понять, как это все вообще работает. +2061.80 2068.92 "Анатолий Кулаков" Обычно offset-ная постраничность требует для вас, для вашего приложения, для вашего бэкэнда, прием двух параметров. +2068.92 2085.04 "Анатолий Кулаков" Первый — это параметр skip и take, который реализуется соответственно в операции skip и take, skip — это то, сколько мы должны записей пропустить, прежде чем отдадим выборку, а второй параметр take рассказывает нам о том, а сколько записей нужно, собственно, взять после того, как мы пропустили skip. +2085.04 2088.16 "Анатолий Кулаков" И таким образом у нас появляется некая страница. +2088.16 2110.80 "Анатолий Кулаков" Вот на таких примитивных двух свойствах мы можем как бы сделать первую страницу, если мы сделаем skip 0 и take 10, мы можем сделать там 50-ю страницу, если мы знаем, что размер страницы 10, мы умножаем на количество элементов, получаем любую страницу и можем автоматически выбрать ту страницу, которую хотим, например. +2110.80 2116.76 "Анатолий Кулаков" И обычно эти параметры почему-то простые, потому что эти параметры один к одному транслируются прямо в SQL. +2116.76 2127.08 "Анатолий Кулаков" В SQL есть кейворды, которые обычно называются offset и limit, и прямо в offset и limit подставляются skip и take, и все, в принципе, вся реализация закончена. +2127.08 2132.20 "Анатолий Кулаков" Если же мы рассмотрим типичную имплементацию нашего, допустим, контроллера. +2132.20 2138.96 "Анатолий Кулаков" Вот есть у нас коллекция, большая, красивая, которую мы хотим вернуть с посторонничной разбивкой. +2138.96 2139.96 "Анатолий Кулаков" Для чего для этого нужно? +2139.96 2160.60 "Анатолий Кулаков" Ну, во-первых, наш контроллер, как я уже сказал, должен принять парочку параметров, или может принимать не skip, take явно, а какие-то более юзер-френдли параметры, например, page и page size, то есть номер страницы, которую хочет посмотреть пользователь, и размер страниц, которыми он хочет листать. +2160.60 2167.56 "Анатолий Кулаков" Я думаю, многие из вас замечали там на каких-нибудь магазинах или поисковиках или еще где-то внизу пишутся странички. +2167.56 2174.36 "Анатолий Кулаков" Первая, вторая, третья страничка, где вы можете перелистнуть результаты вашего поиска или вашей ленты на эти странички. +2174.36 2175.96 "Анатолий Кулаков" Вот это как раз таки есть постраничная навигация. +2175.96 2176.96 "Анатолий Кулаков" Ну, так вот. +2176.96 2181.80 "Анатолий Кулаков" Что же нам, собственно, нужно сделать для того, чтобы реализовать offset-ную постраничность? +2181.80 2193.84 "Анатолий Кулаков" Во-первых, нам нужно определиться с сортировкой, потому что если вы хотите что-то выбрать, первое, второе, третье или десятое, вы обязательно должны понимать, в какой сортировке, в каком разрезе вы это выбираете. +2193.84 2203.20 "Анатолий Кулаков" Вообще, даже если вы в коде у себя используете, например, оператор FIOST, то вы всегда должны задумываться, а FIOST — это откуда, со с кого? +2203.20 2206.36 "Анатолий Кулаков" То есть перед FIOST обязательно должна идти какая-то понятная сортировка. +2206.36 2209.08 "Анатолий Кулаков" Она должна или быть пересказуемой, или вы должны явно ее вызвать. +2209.08 2217.36 "Анатолий Кулаков" Также здесь, если мы хотим пропустить 10 элементов и взять остальные 30, мы должны понимать, а в какой сортировке мы должны пропускать и в какой сортировке мы должны брать. +2217.36 2219.32 "Анатолий Кулаков" Поэтому обязательно должна быть сортировка. +2219.32 2221.72 "Анатолий Кулаков" Это вот просто must-have-правило. +2221.72 2222.72 "Анатолий Кулаков" Вот. +2222.72 2234.12 "Анатолий Кулаков" Другая интересная вещь, что нам необходимо избежать дублирования элементов, а также необходимо избежать пропуск элементов. +2234.12 2238.36 "Анатолий Кулаков" Поэтому у нас сортировка должна быть всегда стабильной и предсказуемой. +2238.36 2239.36 "Анатолий Кулаков" Что это значит? +2239.36 2245.20 "Анатолий Кулаков" Это значит, что если мы просто все наши заметочки отсортируем по дате, для уникальности этого недостаточно. +2245.20 2261.52 "Анатолий Кулаков" Потому что как только у нас будет две одинаковые заметки, и они попадут на середину страницы, допустим, заметка добавилась в 10 минут, 10 секунд и 10 миллисекунд, и вторая заметка тоже вполне может добавиться в 10 минут, 10 секунд и 10 миллисекунд. +2261.52 2266.40 "Анатолий Кулаков" И у них date будет одинаковое с точностью до наносекунды. +2266.40 2268.64 "Анатолий Кулаков" Такое в теории вполне вероятно. +2268.64 2280.12 "Анатолий Кулаков" И когда мы попросим, например, дай мне только все странички с этой датой, то мы вполне можем первую запись взять из дублирующих, а вторую запись из дублирующих не показать пользователю. +2280.12 2282.44 "Анатолий Кулаков" От этого могут быть большие ошибки. +2282.44 2288.36 "Анатолий Кулаков" Поэтому когда мы делаем постраничность, нам обязательно нужно сделать все-таки уникальную сортировку. +2288.36 2296.88 "Анатолий Кулаков" Для этого, если мы хотим, допустим, все-таки показывать странички по датам, наши заметки по датам, все-таки нужно добавить туда 100% уникальное поле. +2296.88 2299.00 "Анатолий Кулаков" В нашем случае это ID-шник ГУИД. +2299.00 2301.76 "Анатолий Кулаков" Поэтому мы сортируем по двум колонкам. +2301.76 2305.44 "Анатолий Кулаков" Во-первых, это дата, ее будет пользователь видеть, вот почему это по дате. +2305.44 2310.80 "Анатолий Кулаков" А во-вторых, это ID-шник для того, чтобы наша сортировка была все-таки уникальной, то есть по сути стабильной. +2310.80 2314.16 "Анатолий Кулаков" ID-шник помогает нам добиться именно стабильности сортировки. +2314.16 2315.64 "Анатолий Кулаков" Ну и дальше. +2315.64 2323.84 "Анатолий Кулаков" Обычно, когда мы показываем пользователю какое-то количество страниц, нам необходимо знать, а сколько всего записей у нас лежит в базе данных. +2323.84 2329.36 "Анатолий Кулаков" Ну, потому что если там всего лежит записи на две странички, мы ему нарисуем внизу циферку 1 и 2. +2329.36 2335.88 "Анатолий Кулаков" Если там миллион страничек, то мы нарисуем там циферку 1 и 2, многоточие там миллион, чтобы он мог переключиться, допустим, на последнюю. +2335.88 2337.64 "Анатолий Кулаков" Или чтобы он мог навигироваться на последнюю. +2337.64 2342.44 "Анатолий Кулаков" Ну, в общем, каким-то образом нам нужно узнать количество записей, сколько лежит в базе данных. +2342.44 2348.92 "Анатолий Кулаков" Поэтому отдельным запросом нам необходимо будет выяснить Total Count, то есть количество записей, которое всего лежит в базе данных. +2348.92 2356.08 "Анатолий Кулаков" Вот, и уже зная там Total Count, уже зная размер страницы, мы, соответственно, можем непосредственно выполнить сам запрос. +2356.08 2370.16 "Анатолий Кулаков" То есть сделать обычный в базу данных query, применить link-оператор skip, и выдать количество элементов, которые нужно пропустить, переменить link-оператор take, который расскажет, а сколько записей нужно взять, и непосредственно уже достанем саму коллекцию. +2370.16 2378.72 "Анатолий Кулаков" При возвращении коллекции мы должны вернуть не только коллекцию, но и, желательно, еще Total Count для того, чтобы UI-ка это тоже красиво как-то обработала, красиво как-то пользователю показала. +2378.72 2386.52 "Анатолий Кулаков" Вот, в принципе, такая вот базовая реализация самого примитивного случая, она существует и есть. +2386.52 2391.16 "Анатолий Кулаков" Давайте еще раз отметим, что здесь концептуально интересного. +2391.16 2394.48 "Анатолий Кулаков" Ну, во-первых, лишний раз хочется остановиться на сортировке. +2394.48 2396.64 "Анатолий Кулаков" Сортировка должна быть консистентной, без этого вы никуда не денетесь. +2396.64 2398.88 "Анатолий Кулаков" И сортировка должна быть уникальной. +2398.88 2403.08 "Анатолий Кулаков" Именно для этого и добавляется в конец обязательно уникальное поле. +2403.08 2404.08 "Анатолий Кулаков" Например, в нашем случае id-шник. +2404.08 2407.80 "Анатолий Кулаков" Если, допустим, мы сортируем изначально не по уникальному полю. +2407.80 2408.80 "Анатолий Кулаков" Обычно так и есть. +2408.80 2412.40 "Анатолий Кулаков" Пользователи не хотят видеть сортировки по какими-то выдуманным уникальным полям. +2412.40 2414.76 "Анатолий Кулаков" Им интересно какой-нибудь дата, тема, еще что-то. +2414.76 2417.52 "Анатолий Кулаков" То есть те поля, которые не обязательно должны быть уникальными. +2417.52 2425.20 "Анатолий Кулаков" Теперь, если мы пойдем глубже в наше приложение, то есть в приложении мы это все реализовали и это все транслируется в SQL. +2425.20 2440.20 "Анатолий Кулаков" В SQL у нас будет типичная операция SELECT FROM, и самое интересное, это будет фильтр, естественно, ORDER BY по дате и по id-шнику, и самое интересное, это как раз фильтр, который транслируется, как я уже говорил, в два стандартных оператора. +2440.20 2445.92 "Анатолий Кулаков" LIMIT и OFFSET, то есть сколько записей нужно пропустить и сколько записей нужно взять. +2445.92 2458.94 "Анатолий Кулаков" И в этом месте как раз заключается самое плохое ограничение данного подхода, потому что в этом месте как раз и образуется Performance Bottleneck. +2458.94 2459.94 "Анатолий Кулаков" Почему образуется? +2459.94 2482.58 "Анатолий Кулаков" Потому что для того, чтобы в базе данных сделать некий лимит, то есть пропустить некий offset, сначала мы offset пропускаем, то есть для того, чтобы в базе данных пропустить какое-то количество записей, допустим 100 записей нужно пропустить, ей необходимо про свои выборки, по сути, все эти 100 записей пройти, то есть скипнуть. +2482.58 2492.42 "Анатолий Кулаков" Таким образом мы получаем такой нормальный индекс оффсета, и для того, чтобы потом, когда мы их пропустили, уже каких-то 10 записей выбрать. +2492.42 2501.90 "Анатолий Кулаков" И самое печальное, что чем больше записей мы пропускаем, тем дольше, по сути, базе данных нужно сделать операции, тем дольше ей нужно поработать. +2501.90 2507.26 "Анатолий Кулаков" На нашей базе данных мы будем тестировать все на миллионе записей, и там это уже вполне видно. +2507.26 2513.46 "Анатолий Кулаков" То есть первая страничка достается нормальная, а уже там какая-то 100-тысячная уже будет доставаться чуть-чуть медленнее. +2513.46 2523.54 "Анатолий Кулаков" Поэтому чем больше ей нужно скипнуть, тем будет запрос вас деградировать больше и больше, тем перформанс будет меньше. +2523.54 2528.66 "Анатолий Кулаков" Дальше у нас появляется следующий минус вот этой постраничного оффсета. +2528.66 2542.22 "Анатолий Кулаков" Это в том, что у нас мы можем пропустить дублирование записей, когда, например, происходит изменение по середине страниц, примерно ту ситуацию, которую я уже описал выше. +2542.22 2548.86 "Анатолий Кулаков" И также мы можем получить неконсистентные результаты, если вдруг несколько потоков меняют наши записи. +2548.86 2558.94 "Анатолий Кулаков" Теперь разберемся с Cursor-based постраничностью, что же она предлагает нам нового, и как она решает те проблемы, которые мы описали выше. +2558.94 2560.62 "Анатолий Кулаков" Давайте посмотрим. +2560.62 2561.62 "Анатолий Кулаков" Прежде всего Cursor. +2561.62 2572.82 "Анатолий Кулаков" Cursor — это некая ссылка, некая точка данных, ссылка на данные, на которых у нас сейчас будет ввестись закладка. +2572.82 2594.94 "Анатолий Кулаков" То есть если вдруг мы постраничность можем сравнить, вот этот курс, оффсет постраничность можем сравнить с какой-нибудь книгой, где мы знаем номер страницы и при этом можем спозиционироваться сразу на нужную страничку, ну и примерно знаем размер страницы, да, поэтому можем предсказать, в каком месте этот номер страницы будет примерно найден. +2594.94 2600.74 "Анатолий Кулаков" То Cursor-based постраничность легче всего представить в виде закладки. +2600.74 2611.58 "Анатолий Кулаков" То есть вот этот курсор — это и есть закладка, которая разделяет наш набор данных на тот, который мы уже прошли и тот, который мы в будущем будем проходить. +2611.58 2615.10 "Анатолий Кулаков" То есть то, что мы уже прочитали, и то, что в будущем собираемся прочитать. +2615.10 2628.90 "Анатолий Кулаков" То есть курсор здесь вполне играет роль такой букмарки, которая рассказывает, какой набор данных мы вернем следующим, вот начиная от этой точки, от этой указывающей точки. +2628.90 2642.14 "Анатолий Кулаков" Если ближе к телу, то обычно курсор идентифицируется каким-нибудь уникальным полем или, если у нас нет уникального поля, то набором нескольких полей, дающих в свою очередь уникальность. +2642.14 2653.26 "Анатолий Кулаков" Ну, в нашем случае вот, например, Data и ID-шник — это тот набор, который даст нам довольно уникальный номер, да, какую-то уникальную позицию. +2653.26 2657.82 "Анатолий Кулаков" И также курсор должен совпадать с методом сортировки. +2657.82 2664.02 "Анатолий Кулаков" То есть если мы сделали курсор по Data и ID-шнику, значит у нас все данные будут сортированы по Data и ID-шнику. +2664.02 2668.02 "Анатолий Кулаков" Это такое ограничение, такой, можно сказать, минус данного подхода. +2668.02 2671.22 "Анатолий Кулаков" Вот, давайте вернемся к нашему предыдущему примеру. +2671.22 2675.14 "Анатолий Кулаков" Будем точно также использовать Data и ID-шник в качестве сортировки. +2675.14 2678.34 "Анатолий Кулаков" Будем считать, что пользователь хочет видеть коррекцию именно в таком виде. +2678.34 2684.76 "Анатолий Кулаков" Что же нам нужно для того, чтобы выполнить сортировку на основе курсора? +2684.76 2688.34 "Анатолий Кулаков" Как я уже сказал, нам нужна вот эта букмарка, вот эта закладка. +2688.34 2691.78 "Анатолий Кулаков" В нашем случае букмарка будет символизироваться двумя полями. +2691.78 2698.46 "Анатолий Кулаков" Это Data и Identifier, то есть, значит, нам нужно принять в качестве аргументов Data и Identifier. +2698.46 2707.06 "Анатолий Кулаков" И нам также необходимо знать размер страницы, поэтому лимит, который обозначает, сколько именно записи мы хотим вернуть, нам тоже нужен. +2707.06 2713.82 "Анатолий Кулаков" Вот три аргумента для нашего контроллера достаточно, чтобы реализовать данный подход, данную стратегию. +2713.82 2722.78 "Анатолий Кулаков" Итак, прежде всего нам нужно понять, что сначала мы страницу начинаем листать или не сначала. +2722.78 2728.26 "Анатолий Кулаков" Если вдруг нам не задали дату и идентификатор, значит, мы начинаем листать страницу сначала. +2728.26 2731.34 "Анатолий Кулаков" Если вдруг нам ее задали, то мы сделаем все очень просто. +2731.34 2750.54 "Анатолий Кулаков" Мы сортируем наши данные по дату, по дату и идентификатору, как мы делали раньше, и просто-напросто сравниваем те значения, которые нам передали, то есть, что дата в таблице должна быть меньше, чем наша дата, которую нам передали, и также идентификатор в таблице должен быть меньше чем или равен тому идентификатору, который нам передали. +2750.54 2763.94 "Анатолий Кулаков" Таким образом, мы отсекаем полностью сортированный набор, отсекаем у него именно тот слой, который мы уже прочитали, и тот слой, который мы дальше будем читать с помощью операторов, больше-меньше. +2763.94 2779.94 "Анатолий Кулаков" После того, как мы отсортировали, после того, как мы установили нашу букмарку, то есть, по сути, where загнали условие меньше или больше нашей букмарки, мы уже можем запросить данные из базы данных. +2779.94 2781.90 "Анатолий Кулаков" Здесь интересен еще один хак. +2781.90 2789.06 "Анатолий Кулаков" Мы должны запросить не тот лимит, который нам передали, например, 10 элементов, а лимит +1. +2789.06 2802.22 "Анатолий Кулаков" Если мы так сделаем, то подобным образом мы можем определить, а есть ли у нас в базе данных еще записи, кроме того, что нас попросили вернуть, кроме вот этих 10, есть ли там 11, 12 и так далее. +2802.22 2830.50 "Анатолий Кулаков" В принципе, нам не важно, сколько их там есть, нам главное сказать, есть ли они или нет, то есть заполнить идентификатор такой, как HasMore на UI-ках, на фронт-энде, вы, наверное, тоже могли встречаться с такой курсорной по страничностью, когда вы крутите вниз и у вас снизу есть кнопочка "подгрузить еще", то есть вы не знаете, сколько там страничек есть, вы не знаете миллион их там, миллиарды или всего две, но у вас есть кнопка "подгрузить еще". +2830.50 2835.74 "Анатолий Кулаков" Если вы эту кнопку нажали, у вас грузится еще одна страница, и там появляется или не появляется эта кнопка. +2835.74 2843.42 "Анатолий Кулаков" Вот как раз HasMore вот этот флаг, он и определяет, будет ли там видна кнопка "подгрузить еще" или это все, больше данных никаких нет. +2843.98 2853.22 "Анатолий Кулаков" Вот загружая Limit+1, мы уже можем понимать, есть ли там возможность нам вернуть еще дополнительный набор или уже нет. +2853.22 2859.22 "Анатолий Кулаков" И второе, что нам нужно сделать, это установить новую букмарку, то есть что мы сейчас прочитали. +2859.22 2872.10 "Анатолий Кулаков" Для этого нам необходимо свойства Date и Identifier увеличить ровно на значение последнего элемента, который мы загрузили из нашего набора. +2872.10 2882.10 "Анатолий Кулаков" Поэтому, если в следующий раз к нам придут обратно с этой датой и с этим идентификатором, мы уже будем знать, что у нас закладка сместилась, и мы будем загружать новую страничку. +2882.10 2888.62 "Анатолий Кулаков" И вернем точно так же клиенту новую закладку в надежде на то, что он нам их сообщит заново и отдаст на вход. +2888.62 2891.38 "Анатолий Кулаков" Что же теперь у нас происходит с SQL? +2891.38 2893.26 "Анатолий Кулаков" Происходит практически то же самое. +2893.26 2905.42 "Анатолий Кулаков" Мы сделаем OrderBy и мы сделаем условие, но самое интересное это в конце происходит, потому что в конце у нас нет offset. +2905.42 2910.66 "Анатолий Кулаков" Мы не определяем с помощью SQL сколько необходимо пропустить записей. +2910.66 2914.42 "Анатолий Кулаков" С помощью SQL мы определяем только лимит, то есть сколько записей нужно забрать. +2914.42 2922.18 "Анатолий Кулаков" Забираем мы их всегда только с нужной закладки, потому что в условии у нас есть WHERE. +2922.18 2928.90 "Анатолий Кулаков" То есть в условии у нас написано, если только дата меньше того, что мы передали, и только идентификатор меньше того, что мы передали. +2928.90 2940.02 "Анатолий Кулаков" Таким образом, мы естественным условием WHERE смещаем нашу букмарку по SQL набору, при этом не используя offset. +2940.02 2941.46 "Анатолий Кулаков" Что это значит? +2941.46 2951.94 "Анатолий Кулаков" На самом деле это очень важное замечание, потому что если у нас нет offset, то значит у нас нет вот этого скана по всему набору данных, который у нас был в начале. +2951.94 2964.98 "Анатолий Кулаков" Оператор WHERE очень эффективно справляется практически direct-seq'ами на необходимую позицию сразу, то есть на необходимую позицию, где нам нужно начинать отрезать, где нам нужно держать лимит. +2964.98 2971.14 "Анатолий Кулаков" Поэтому этот подход более эффективный, чем offset постраничность. +2971.14 2977.26 "Анатолий Кулаков" Второй интересный момент, что нам не нужно количество элементов для того, чтобы сделать курсорную постраничность. +2977.26 2983.06 "Анатолий Кулаков" Как я уже сказал, для нас достаточно понимать, есть ли кнопка загрузить еще или нет этой кнопки. +2983.06 2987.42 "Анатолий Кулаков" То есть можно ли мы вызвать дальше продвижение по закладке или не можем. +2987.42 2991.78 "Анатолий Кулаков" Поэтому у нас нет лишнего запроса, который есть в нашем предыдущем примере. +2991.78 2998.94 "Анатолий Кулаков" Напомню, чтобы сделать offset постраничность, нам нужно сначала запросить общее количество элементов, а потом еще сами элементы. +2998.94 3001.30 "Анатолий Кулаков" То есть по сути в базу данных уходит два запроса. +3001.30 3009.98 "Анатолий Кулаков" Если мы сделаем курсорную постраничность, в базу данных всегда будет уходить один запрос, который намного эффективнее, чем с offset. +3009.98 3021.38 "Анатолий Кулаков" Ну, казалось бы, вообще, красота, бенефиты сплошные и нам нужно писать только на курсорах, но у курсорной постраничности есть свои ограничения и свои минусы. +3021.38 3025.50 "Анатолий Кулаков" Не все так радужно, естественно, в этом мире, поэтому давайте их подробнее рассмотрим. +3025.50 3034.98 "Анатолий Кулаков" Итак, курсорную постраничность сложно использовать, если пользователь захочет динамически менять сортировку. +3034.98 3039.38 "Анатолий Кулаков" Как я уже сказал, курсор сильно зависит от того, как отсортированы данные. +3039.38 3062.42 "Анатолий Кулаков" То есть, если мы данные отсортировали по дате и по айдишнику и пользователь в этот момент захотел вдруг наши заметки отсортировать по названию, то, естественно, наш курсор, наша букмарка по сути теряется, наша закладка больше уже не актуальна, нам теперь нужно заново пересортировать и делать новую закладку, которая уже будет ориентироваться на название. +3062.42 3071.18 "Анатолий Кулаков" Не то чтобы это сложно, но это требует какой-то дополнительной логики в реализации, то есть это нужно как-то программировать, как-то поддерживать. +3071.18 3079.14 "Анатолий Кулаков" Следующий минус курсорной постраничности заключается в том, что мы не можем прыгнуть на какую-то конкретную страницу. +3079.14 3080.58 "Анатолий Кулаков" Иногда пользователи этого хотят. +3080.58 3090.62 "Анатолий Кулаков" В общем, они говорят, что интересующие нас знания находятся на странице 10 и просто так промотать на десятую страницу сразу невозможно. +3090.62 3099.10 "Анатолий Кулаков" Вам необходимо будет пройти все эти десять страниц по очереди, пока вы не домотаете до 50-й страницы. +3099.10 3105.46 "Анатолий Кулаков" В общем, это тоже довольно редкое требование, но оно бывает очень важным. +3105.46 3125.74 "Анатолий Кулаков" Ну и сложность в реализации, потому что вот эту постраничность на основании курсора реализовать немножко сложнее, особенно если мы начинаем загоняться дублями, которые могут появиться посередине страниц, и если мы не хотим пропустить каких-то записей. +3125.74 3140.66 "Анатолий Кулаков" То есть, опять же, вот эта постраничность в конкурентной среде, где данные постоянно меняются, могут вставляться и в первые страницы, и в последние страницы, это довольно сложная проблема, и здесь она будет только еще сложнее. +3140.66 3145.26 "Анатолий Кулаков" Теперь давайте обратимся к экзекьюшен-планам. +3145.26 3150.18 "Анатолий Кулаков" Я не буду вам зачитывать планы, но примерно расскажу про их результаты, которые получились в статье. +3150.18 3154.70 "Анатолий Кулаков" Если вам интересно, почему так произошло, то все планы есть, можно посмотреть. +3154.70 3163.34 "Анатолий Кулаков" Итак, для позиции есть прекрасная команда, которая называется exploit-analyze, которая как раз нам позволяет нарисовать план того запроса, который мы ей передаем. +3163.34 3174.02 "Анатолий Кулаков" И мы будем пробовать запрос, который пропускает offset, делает на 900 тысяч записей и выбирает следующую тысячу записей. +3174.02 3183.46 "Анатолий Кулаков" Проведем для начала ее на offset по страничности, и время в попугаях получается примерно 704 миллисекунды. +3183.46 3188.78 "Анатолий Кулаков" В общем, для нас абсолютное время не очень важно, для нас важно относительно, но 704 миллисекунды. +3188.78 3198.74 "Анатолий Кулаков" И нужно понимать, что чем дальше мы заходим в offset, то есть чем дальнюю страницу мы просим, тем это время будет больше. +3198.74 3205.10 "Анатолий Кулаков" Поэтому примерно на 900-тысячной записи это значение вот такое. +3205.10 3212.18 "Анатолий Кулаков" Если мы возьмем курсорную по страничности, то там будет сразу 40 миллисекунд, то есть 704 против 40. +3212.18 3214.66 "Анатолий Кулаков" Это где-то в 17 раз быстрее. +3214.66 3221.22 "Анатолий Кулаков" Вот почему курсорная по страничности считается более выгодной с точки зрения перформанса. +3221.22 3225.94 "Анатолий Кулаков" И самое прекрасное в этой цифре в том, что она никак не зависит от глубины. +3225.94 3232.62 "Анатолий Кулаков" То есть эти стабильные 40 миллисекунд будут у вас и на первой странице, и они будут у вас на миллионной странице. +3232.62 3237.30 "Анатолий Кулаков" В отличие, опять же, от offset. +3237.30 3238.30 "Анатолий Кулаков" Кажется, что все хорошо. +3238.30 3244.12 "Анатолий Кулаков" То есть у нас там 700 против 40, курсорная выиграла, все прекрасно, давайте жить дальше. +3244.12 3252.62 "Анатолий Кулаков" Но автор решил прооптимизировать запрос, потому что видно было, что по execution-плату видно, что не хватает индекса. +3252.62 3263.10 "Анатолий Кулаков" Естественно, мы выбираем, то есть мы сортируем в курсорной по страничности, мы сортируем по дате и ID-шнику, и по ним же потом и фильтруем в условии. +3263.10 3267.06 "Анатолий Кулаков" То есть очевидно, нам нужен композитный индекс по дате и ID-шнику. +3267.06 3277.42 "Анатолий Кулаков" Автор добавил такой композитный индекс, запустил план заново и выяснилось, что наши прекрасные 40 миллисекунд превратились почти в 300 миллисекунд. +3277.42 3282.46 "Анатолий Кулаков" Если посмотреть на план, то там видно, что этот индекс используется, но используется не очень правильно. +3282.46 3291.70 "Анатолий Кулаков" То есть для базы данных этот набор слишком маленький, и поэтому база данных не соображает, как его нужно использовать правильно. +3291.70 3294.06 "Анатолий Кулаков" Она начинает его использовать посрочно. +3294.06 3305.86 "Анатолий Кулаков" То есть оптимизатор не может определить, что вот этот композитный индекс будет выгоден при сравнении значений из этого индекса. +3305.86 3319.10 "Анатолий Кулаков" Тем не менее оптимизатор может определить, что этот индекс будет выгоден при сравнении именно таблов, то есть тех значений, которые есть в индексе, которые будут сравниваться с таблами. +3319.10 3330.46 "Анатолий Кулаков" В общем, есть в SQL такая прекрасная вещь, как table comparison, когда мы можем сравнивать несколько значений, засунутых именно в таблы. +3330.46 3335.54 "Анатолий Кулаков" С точки зрения, в принципе, C# таблов это тоже оно самое, оно уже подходит. +3335.54 3351.46 "Анатолий Кулаков" То есть мы должны переписать запрос, то есть в условии where мы не должны писать дата меньше какого-то значения и идентификатор меньше значения, мы должны писать table, состоящий из даты идентификатора, меньше ли равен table, состоящего из значений даты и значений идентификатора. +3351.46 3353.34 "Анатолий Кулаков" В общем, Postgres это прекрасно понимает. +3353.34 3358.66 "Анатолий Кулаков" В общем, не знаю, насколько это стандартный синтаксис, наверное, не очень стандартный. +3358.66 3360.42 "Анатолий Кулаков" Скорее всего, это специфика то чисто Postgres. +3360.42 3375.86 "Анатолий Кулаков" В общем, если мы сделаем так, сравним where по таблам, то наши 300 миллисекунд превращаются в 0.66 миллисекунд. +3375.86 3389.82 "Анатолий Кулаков" То есть, напомню, что чистый курсор без индекса у нас был 40 миллисекунд, а если этот курсор с индексом и при этом с переписанными таблами, он занимает 0.6 миллисекунд. +3389.82 3399.94 "Анатолий Кулаков" Если эти 0.6 сравнить с оригинальными offset базами, которые 700 миллисекунд, то разница получается совсем огромная. +3399.94 3406.10 "Анатолий Кулаков" То есть вообще непонятно, как мы живем на offset по страничности до сих пор. +3406.10 3411.02 "Анатолий Кулаков" В общем, как вы поняли, разница просто критическая. +3411.02 3420.18 "Анатолий Кулаков" Но что же вот это tuple сравнение в SQL, как же его можно все-таки использовать в нашем привычном Entity Framework Query? +3420.18 3429.38 "Анатолий Кулаков" В принципе, можно, потому что Postgre Provider предоставляет функцию, которая называется EF_FUNCTIONS_LESS_THAN_OR_EQUAL, и она может принимать как раз туплы. +3429.38 3444.02 "Анатолий Кулаков" То есть вы можете написать query выражение, где написать query where, передать туда EF_FUNCTIONS_LESS_THAN_OR_EQUAL, передать в эту функцию два tuple, и она вам странслирует именно вот такое подобное поведение. +3444.02 3452.82 "Анатолий Кулаков" То есть если вы хотите прям совсем загнаться в performance, то это можно сделать даже через Entity Framework, не нарушая там никаких парадигм, никакие хаки вставлять не надо. +3452.82 3459.10 "Анатолий Кулаков" Ну, нужно будет заложиться на то, что у вас Postgres, то есть завязаться на Postgres, это в принципе более-менее приемлемо. +3459.10 3460.10 "Анатолий Кулаков" Вот. +3460.10 3462.10 "Анатолий Кулаков" Что еще хочется сказать про курсор? +3462.10 3486.58 "Анатолий Кулаков" В принципе, как только вы начинаете более-менее сложно работать с курсором, особенно когда вы пытаетесь поддержать динамическую сортировку, о которой я упоминал ранее, то передавать явно поля, по которым вы делаете курсор, ну вот эту data, id, когда я говорил, они должны поступать на вход в виде букмарка, а потом мы надеемся на то, что клиент нам пришлет их обратно для того, чтобы мы дальше по этому букмарку продолжили наше путешествие. +3486.58 3488.66 "Анатолий Кулаков" В общем, это довольно плохая идея. +3488.66 3495.22 "Анатолий Кулаков" Нельзя надеяться на клиента, потому что клиент — это фронтенд, а фронтенд — это, как известно, безнадежные парни. +3495.22 3497.66 "Анатолий Кулаков" Они могут вам прислать абсолютно все, что угодно. +3497.66 3503.02 "Анатолий Кулаков" Для того, чтобы избежать таких ситуаций, мы можем немножко наш API улучшить, то есть закодировать курсор. +3503.02 3507.38 "Анатолий Кулаков" Мы можем делать маленький утилитный класс, которым назовем, например, курсор. +3507.38 3513.14 "Анатолий Кулаков" Этот класс будет принимать у нас на вход два параметра — дату и идентификатор. +3513.14 3521.46 "Анатолий Кулаков" Дальше внутри этого курсора, то есть сам этот курсор, мы можем засериализовать, например, JSON-сериал с сериалайзером и закодировать, например, в B64. +3521.46 3526.50 "Анатолий Кулаков" Для особых параноиков можно, наверное, зашифровать, но у нас, в принципе, такой задачи не стоит. +3526.50 3528.42 "Анатолий Кулаков" Поэтому B64 вполне достаточно. +3528.42 3535.86 "Анатолий Кулаков" Это очень хорошая кодировка, не просто потому, что ее нельзя просто так подменить. +3535.86 3539.66 "Анатолий Кулаков" Ну, подменить можно, но, опять же, никто этим заниматься скорее всего не будет. +3539.66 3542.34 "Анатолий Кулаков" Это хорошая кодировка, которая дает вам несколько преимуществ. +3542.34 3547.58 "Анатолий Кулаков" Во-первых, мы получаем одно значение вместо двух, а в общем случае там может быть далеко не два значения. +3547.58 3554.94 "Анатолий Кулаков" Если мы, например, сориентируем по пятю полям или по шестью полям, то заставлять все их передавать в UI, это было бы довольно странно. +3554.94 3559.26 "Анатолий Кулаков" Поэтому мы получаем одно значение вместо многих значений. +3559.26 3561.22 "Анатолий Кулаков" Это очень важный плюс. +3561.22 3566.42 "Анатолий Кулаков" Следующий важный плюс — у нас получается скрытие информации от UI. +3566.42 3572.86 "Анатолий Кулаков" То есть UI не нужно знать, в какие поля, в какие параметры, в какие query-аргументы ему необходимо засунуть. +3572.86 3586.86 "Анатолий Кулаков" У него есть одно значение, он его от backend получил, он его в backend должен вернуть, никак не изменяя, ничего туда не прописывая, никак местами он их поменять не забудет, никак переставить не запомнит, никак половину значения не отбросит. +3586.86 3593.30 "Анатолий Кулаков" В общем, одно понятное монолитное значение, которое никаким образом внутрь он заглядывать в которое не должен. +3593.30 3598.18 "Анатолий Кулаков" И еще один плюсик — это в том, что мы зашифровали в B64. +3598.18 3620.98 "Анатолий Кулаков" Это значит, что это такое url-friendly значение получилось, то есть мы его вполне можем использовать в url-ах красивенько, без всяких эскейпов, в отличие, допустим, от какой-нибудь обычной строки, если бы мы сортировали или делали бы курсор по названию страницы, в этой названии страницы были бы латинские буквы, и это все превратилось бы в ужасную некрасивую строчку. +3620.98 3624.82 "Анатолий Кулаков" А так, в B64 строчка будет красивенькая, всегда параметр будет один. +3624.82 3629.74 "Анатолий Кулаков" Ну и что, что немножко стал побольше, потому что там было JSON, довольно не страшно. +3629.74 3635.94 "Анатолий Кулаков" Поэтому хорошая тема — это сразу делать курсор каким-нибудь зашифрованным одним классиком. +3635.94 3643.98 "Анатолий Кулаков" Итак, если подводить итоги, то у нас есть два популярных метода постраничности — это offset и курсор. +3643.98 3659.12 "Анатолий Кулаков" У offset есть свои преимущества, в частности, он намного проще, намного понятнее новичкам и намного более прост в реализации, но при этом он от 17 раз медленнее, чем следующий вариант. +3659.12 3699.96 "Анатолий Кулаков" Курсорная постраничность прекрасна тем, что у нее всегда будет лучше перформанс, если вы захотите загнаться, то перформанс улетит вообще в потолок, а самое главное, наверное, преимущество в том, что ее перформанс не деградирует, если у вас страницы будут длинные и большие, то есть на больших датасетах, скорее всего, без курсорной постраничности вы просто умрете, поэтому у нее перформанс не деградирует, и это хорошо, с помощью нее можно организовать бесконечный скролл, допустим, если у вас данные все время добавляются, там, например, пишутся какие-то логи, то для постраничной вам все-таки нужно знать, какая у вас страница сейчас активная, а какая неактивная. +3699.96 3712.68 "Анатолий Кулаков" Для курсорной же постраничности вам необходимо просто знать, есть ли следующая запись или не следующая запись, в общем, это намного больше соответствует такому бесконечному скроллу, например, ленты социальных новостей в вашей социальной сеточке. +3712.68 3724.28 "Анатолий Кулаков" Но при этом более сложная имплементация, и нет, например, навигации на конкретную страницу, невозможно спозиционироваться на какую-то конкретную страницу быстро и эффективно, без промотки. +3724.28 3734.40 "Анатолий Кулаков" В общем, вот такие две альтернативы, я надеюсь, что если вы раньше не использовали курсорную постраничность, то теперь вы хотя бы задумайтесь в каких-то местах, может быть, она вам будет нужна. +3734.40 3761.04 "Игорь Лабутин" Да, отличный обзор, мне кажется, много чего рассмотрено, плюсы, минусы, посмотрите на то, как структурированы ваши данные, по каким полям вы хотите сортировать, сколько часто меняет сортировки пользователь, потому что если он понажимал "еще-еще-еще" и поскролил, а потом сказал "нет, теперь хочу сортировать по-другому", то он опять вернется на первую страничку по сути своей. +3761.04 3771.16 "Игорь Лабутин" Ну и в целом, наверное, мне, честно говоря, даже нечего добавить к этому, смотрите на требования и давайте разбираться. +3771.16 3776.96 "Игорь Лабутин" Какая из постраничностей вам подходит, блин, интересное слово. +3776.96 3783.68 "Анатолий Кулаков" Ну зато хорошо, в принципе, отражает, не самый плохой перевод, я хочу сказать, мы сталкивались с намного хужими. +3783.68 3800.52 "Анатолий Кулаков" В принципе, да, чем больше паттернов, тем больше вы таких шаблонов знаете, которые есть, чем больше плюсов и минусов вы знаете, тем более правильным инструментом вы будете пользоваться, вы не будете микроскопом забивать гвозди, поэтому знайте, имейте в арсенале и попробуйте на ближайшем случае, если вам понадобится. +3800.52 3801.52 "Игорь Лабутин" Действительно. +3801.52 3863.80 "Игорь Лабутин" А мы пойдем изучать другие паттерны и давай вернемся немножко в дотнет, к нашему одному из довольно редких, но не менее любимых авторов Стивен Клире, который ну тоже довольно давно уже, почти больше полугода назад написал статью, которая была шестой частью к некоторой серии статей про cancellation, про отмены, про то, как правило, работать с cancellation токенами, и я уже думал, ох, мы наверное что-то пропустили, где же остальные предыдущие 5, оказалось, что остальные предыдущие 5 начались еще в 2022 году, и как-то они видимо очень лениво выходили, может быть мы даже что-то про них рассказывали, но я уже не помню, было это давно, я в итоге по поводу выхода шестой статьи и нескольких месяцев лежания ее в нашем бэклоге решил, что все-таки пора наконец-таки взяться и не ждать еще года, пока выйдет седьмая часть, и немножко сделать обзор того, как же правильно работать с cancellation в дотнете, по мнению Стивена Клире. +3863.80 3988.96 "Игорь Лабутин" Начнем мы с обзора, с того, что вообще вспомнил, что такое cancellation и зачем он нужен, и какой он бывает в дотнете, ну идея cancellation понятна, мы начинаем какую-то операцию и нам по какой-либо причине, внешне либо еще какой-либо, ну как правило внешне для выполняемого кода нужно ее отменить, пользователь там передумал, тайм-аут наступил, еще что-то случилось, а в дотнете используется так называемая кооперативная, хотел сказать многозадачность, нет, кооперативный подход к отмене, cancellation, то есть что это значит, это значит, что нет никакого, ну кроме thread abort, способа принудительно прервать какую-либо операцию, но можно передать некоторый токен внутрь операции, изучая который, операция будет понимать, пора ли ей прерваться или все-таки можно еще работать, и это действительно так и работает, то есть у нас есть некоторое негласное, вполне гласное, такое задокументированное правило, что есть объект, на самом деле структурка, cancellation токен, его нужно принимать в методах, которые готовы, так сказать, поддерживать идею отмены, и передавать его дальше вниз по методам, которые вызываете вы, если они его принимают, как правило, этот токен передается последним параметром, у него обычно задается дефолтное значение, которое присваивается cancellation_token.none, это специальный токен, который никогда не может быть отменен, и при этом те токены, которые могут быть отменены, они могут быть отменены ровно один раз, то есть cancellation токен, будучи единожды отменен, больше уже не переходит никогда обратно в неотмененное состояние, при этом метод, который принимает cancellation токен, не обязан на него реагировать, это только подразумевает намерение или, ну, допустим, некоторые гарантии хотел сказать, нет, не гарантии, а именно намерение, и может быть этот метод отреагирует на cancellation токен, например, только в части своих путей исполнения, а в части не будет реагировать, но тем не менее, если он принимает, то лучше туда передавать. +3988.96 4010.28 "Игорь Лабутин" Значит, с точки зрения того, что происходит, если cancellation таки срабатывает, ну, как правило, выбрасывается operation_consult_exception, которым нужно что-то сделать, вероятно на том уровне, где вы запросили cancellation, но никак не иначе, мы про это подробнее поговорим. +4010.28 4033.56 "Игорь Лабутин" Сразу же в первой же статье Стивен предупреждает от одной довольно важной ошибки, сейчас не так часто она нужна, не так часто мы делаем task_run, но тем не менее, если вы по какой-то причине делаете task_run, то метод task_run тоже принимает cancellation токен, и многие думают по ошибке, что этот токен как раз таки будет влиять на то, как выполняется task, но это далеко не так. +4033.56 4039.80 "Игорь Лабутин" Task_run, точнее токен, который принимает task_run, относится только к той части, которая scheduled эту task для исполнения. +4039.80 4046.20 "Игорь Лабутин" Как только task засcheduled, этот токен больше не используется, внутри task нужно тогда использовать какой-то другой токен, т.е. +4046.20 4061.44 "Игорь Лабутин" либо передать этот токен туда аргументом, либо его через замыкание туда запихнуть, но в общем внутри, то, что вы передаете в task_run, туда этот токен никуда не попадает и по большому счету его туда передавать особо никогда и не надо, потому что task_run редко выполняется настолько долго, что его нужно канцелять. +4061.44 4066.12 "Игорь Лабутин" Итак, давайте рассматривать все по частям. +4066.12 4069.88 "Игорь Лабутин" Часть первая — это то, как мы можем запросить cancellation. +4069.88 4092.72 "Игорь Лабутин" Значит, тут все просто, нам откуда-то нужно взять cancellation токен, чтобы его передать, либо мы его получили снаружи и тут тогда, ну в большинстве случаев вы его просто передаете и дальше, там есть некоторые варианты, мы про них чуть позднее поговорим, но если вы, например, сами являетесь вызывающей стороной и ни откуда снаружи этого токена у вас нет, вам нужно его откуда-то создать. +4092.72 4114.72 "Игорь Лабутин" Для этого используется специальный класс, он называется cancellation_token_source, он как раз используется для того, чтобы создавать cancellation токены, вы можете их создать много из одного cancellation_token_source, но как только вы заканцелите этот самый token_source, то все токены, которые из него были созданы, тоже будут объявлены cancelled, заканцеленными. +4114.72 4141.16 "Игорь Лабутин" Дальше вы можете, например, захотеть запросить cancellation через какой-то timeout, ну, в принципе, можно сделать просто отдельный таймер, который, соответственно, в нужный момент просто вызовет cancellation_token_source.cancel и в принципе это будет работать, но для этого есть специальный метод cancel_after, который как раз принимает time_span и позволяет задать время, через которое cancellation_token_source будет заканцелен. +4141.16 4151.48 "Игорь Лабутин" Можно, как я сказал, вручную вызвать cancel, например, такое использовалось в UI-приложениях, когда пользователь нажимает на кнопку cancel, вы как раз вызываете cancellation_token_source.cancel. +4151.48 4194.12 "Игорь Лабутин" И важная штука при работе с cancellation_token_source, надо помнить, что большая часть методов возвращает, во-первых, сам cancellation_token_source является idisposable объектом, то есть его нужно почистить, ну, а также часть методов тоже возвращает idisposable объект, который тоже неплохо бы диспозить для того, чтобы все почистили, чтобы всякие связанные таймеры и прочие такие штуки тоже правильно почистились, они висели бы вечно и не пытались канцелить, особенно если они используют какие-нибудь лямбды, которые захватили какую-нибудь переменную, в которой лежит ваш тяжелый объект, то за счет таких cancellation_token_source с какими-нибудь лямбдами, которые туда передали, мы посмотрим чуть позднее, зачем это может быть надо. +4194.12 4204.72 "Игорь Лабутин" Эти объекты будут, наверное, навечно в каком-то смысле забенены в памяти, потому что cancellation_token_source будет не задисположен. +4204.72 4215.68 "Игорь Лабутин" Ну, вроде как, более-менее на базовом уровне вы поняли, как нам создать cancellation_token, но мы его, вероятно, как-то передали. +4215.68 4226.56 "Игорь Лабутин" А дальше нужно понять, предположим, что мы хотим понять вообще за cancellation_operation, не cancellation_operation, что вообще с ней делать. +4226.56 4234.68 "Игорь Лабутин" Как я сказал, в большинстве случаев, когда операция будет заканцелена, вам прилетит operation_cancel_exception. +4234.68 4250.56 "Игорь Лабутин" Клири настоятельно рекомендует никогда его не кетчить, кроме случая, если вы действительно та самая топ-левел операция, которая и запросила cancellation, потому что, как правило, все промежуточные операции вообще понятия не имеют, что делать с этим operation_cancel_exception. +4250.56 4260.84 "Игорь Лабутин" Кетчить и хендлить его не надо, но, может быть, у вас есть какой-то очень редкий случай, нужно, не знаю, освободить какой-то супер-важный объект, но его доловите и пробрасывайте дальше. +4260.84 4261.84 "Игорь Лабутин" Тут без вариантов. +4261.84 4269.20 "Игорь Лабутин" Отдельно надо сказать про такое исключение, как task_cancel_exception. +4269.20 4277.68 "Игорь Лабутин" Некоторые API-шки начинают выкидывать его вместо operation_cancel_exception, особенно, если какая-нибудь async API-шка, она же считает, что она же с task-ами работает, нужно обязательно выкинуть task_cancel_exception. +4277.68 4287.80 "Игорь Лабутин" Тут совет простой, просто забудьте, что такой класс существует, это наследник operation_cancel_exception, если вам что-то надо делать, работайте с operation_cancel_exception, он гораздо более универсальный. +4287.80 4291.08 "Игорь Лабутин" task_cancel_exception не нужен вам. +4291.08 4305.12 "Игорь Лабутин" И в, собственно, operation_cancel_exception есть property, cancellation токен, который вы можете в вашем вызывающем коде попробовать на него посмотреть в handle исключения и что-то решить на его основе. +4305.12 4317.36 "Игорь Лабутин" Так вот, во-первых, оно может быть не поставлено, во-вторых, не факт, что оно поставлено, но по дизайну там должен оказаться токен, из-за которого произошло, собственно, исчезновение. +4317.36 4318.36 "Игорь Лабутин" Но на самом деле это может быть не так. +4318.36 4328.00 "Игорь Лабутин" Есть ряд сценариев, в котором это свойство будет либо вообще не поставлено, либо поставлено на совершенно другой токен, который не имеет отношения к тому, из-за которого все началось. +4328.00 4331.40 "Игорь Лабутин" Поэтому совет простой, просто игнорьте это поле. +4331.40 4351.32 "Игорь Лабутин" Если вам нужно проверить явно, что это именно вы вызвали cancellation, то проверьте состояние самого cancellation токен-сурса, который у вас тоже рядышком есть, потому что, напомню, что ловить такое исключение нужно только в том уровне, где вы сами же вызвали cancel, то есть там, где вы владеете cancellation токен-сурс. +4351.32 4355.20 "Игорь Лабутин" Вроде бы более-менее разобрались, что можно делать снаружи. +4355.20 4360.44 "Игорь Лабутин" Теперь давайте посмотрим, что делать внутри метода, который принял cancellation токен. +4360.44 4366.24 "Игорь Лабутин" Ну, во-первых, можно и даже нужно периодически опрашивать этот самый cancellation токен. +4366.24 4385.16 "Игорь Лабутин" Особенно, если вы делаете что-то в цикле, то вы внутри каждой либо там, не каждой итерации цикла, в зависимости от того, насколько у вас нагруженная каждая итерация, добавите метод cancellation_token.throw_if_cancellation_requested, он внутри себя сам проверит состояние токена и выкинет исключение. +4385.16 4386.36 "Игорь Лабутин" Как часто это надо делать? +4386.36 4397.40 "Игорь Лабутин" Ну, тут вопрос вашего приложения, если это UI-ное приложение, надо смотреть, насколько оно там, не знаю, отзывчивый пользовательский интерфейс и насколько быстро вы хотите, чтобы на cancellation была реакция. +4397.40 4407.84 "Игорь Лабутин" Если это какое-то бэкэндное число-дробилка, которое просто иногда должно проверить, не пора ли ей отменить задачу, потому что она больше неактуальна, может быть, это можно делать пореже. +4407.84 4410.12 "Игорь Лабутин" Тут надо тестировать и смотреть сами. +4410.12 4414.08 "Игорь Лабутин" Что делать нельзя, ну, точно нельзя, не рекомендуется? +4414.08 4436.32 "Игорь Лабутин" Во-первых, у токена есть такое свойство, называется is_cancellation_requested, так вот, крайне не рекомендуется писать цикл, например, в виде while_ne_is_cancellation_requested, что-то делаем, то есть мы не проверяем и не кидаем исключения, а просто проверяем, не заканцелился, если заканцелился, то типа прекратили цикл и вышли. +4436.32 4465.64 "Игорь Лабутин" Проблема с этим методом в том, что вызывающая сторона понятия не имеет, вы вышли, потому что вы закончили все делать, и, например, можно как-то полагаться на результат того, что вы сделали, или вы заканцелились, потому что токен оказался cancelled, в общем, не очень понятно и вызывающая сторона тоже придется тогда проверять после вызова вас, писать throw_is_cancellation_requested, прежде чем обращаться к результатам, это не очень хорошо, поэтому старайтесь is_cancellation_requested не использовать, особенно в таком варианте. +4465.64 4492.84 "Игорь Лабутин" Дальше можно сделать более интересным способом, особенно это полезно, если у вас какая-то асинхронная работа, и у вас нет какого-то явного цикла, например, то вы можете зарегистрировать callback, у cancellation токена есть метод register, который принимает лямбду и возвращает, конечно же, is_possible, лямбда это callback, который будет вызван сразу, как только cancellation токен перейдет в состояние cancelled. +4492.84 4513.60 "Игорь Лабутин" Причем, если вы регистрируете такую лямбду на токене, который уже заканцелен, а такое может возникнуть, например, в момент какой-нибудь гонки, то в этом случае метод ваш, ну если лямбда, которую вы передали, будет вызвана прямо сразу изнутри метода register, синхронно, без какого-либо ожидания, без там всего, без какого-либо thread pool. +4513.60 4523.88 "Игорь Лабутин" То есть тут тоже надо внимательно смотреть, что вы делаете в этой самой лямбде, очень желательно не кидать никаких исключений из этой лямбды, ну и смотреть, чтобы не получил каких-нибудь странных дедлоков. +4523.88 4526.92 "Игорь Лабутин" Помните, что из register эта лямбда может быть сразу вызвана тут же. +4526.92 4550.52 "Игорь Лабутин" То, что вам вернули в виде is_possible, нужно обязательно в нужный момент почистить, проще всего, конечно, это делать через using var, современную конструкцию, чтобы при выходе из функции у вас все почистилось, потому что если не почистите, то в cancellation токе не зависнет лямбда, если эта лямбда закепчерил какое-то состояние вашего объекта, ваш объект, соответственно, будет зависнут в памяти. +4550.52 4561.36 "Игорь Лабутин" Callback, естественно, не гарантируется, что когда-либо будет вызван, то есть может быть так, что токе не законсолится никогда и поэтому callback никогда не вызовется. +4561.36 4581.16 "Игорь Лабутин" Для того, чтобы решить проблему того, что эти callbacks вызываются синхронно, а может быть вы там хотите какую-нибудь асинхронную штучку вызвать, для этого появился в 2008 метод cancelAsync, который делает следующим образом, он все зарегистрированные callbacks, а их можно зарегистрировать несколько, кидает на исполнение на threadPool и завершается. +4581.16 4588.96 "Игорь Лабутин" То есть не факт, что он, насколько я помню, нет гарантии, что callbacks завершатся до выхода из метода cancelAsync. +4588.96 4602.04 "Игорь Лабутин" Более того, если вы несколько раз позовете cancelAsync и он понимает, что он уже один раз эти все таски послал выполняться на threadPool, то он вернется мгновенно и сразу же не дожидаясь окончания их исполнения. +4602.04 4609.40 "Игорь Лабутин" То есть cancelAsync в общем случае не гарантирует, что все callbacks выполнились, но они будут выполняться на threadPool и зато. +4609.40 4611.32 "Игорь Лабутин" Может быть это чем-то поможет. +4611.32 4624.04 "Игорь Лабутин" Ну и последний интересный момент, который как раз таки может сломать немножко ситуацию с exception и токенами, то про что я говорил чуть выше, это связывание cancellation token sources. +4624.04 4639.20 "Игорь Лабутин" То есть если у вас есть cancellation token source, который мы хотим создать, то мы можем его создать таким образом, что он будет заканцелен, если токен, указанный ему, тоже будет заканцелен. +4639.20 4650.48 "Игорь Лабутин" То есть вы таким образом создаете связанный cancellation token source, который будет заканцелен и токены которого тоже будут заканцелены, если заканцелится исходный токен. +4650.48 4658.56 "Игорь Лабутин" Для этого используется метод createLinkedTokenSource и туда передается просто cancellation token. +4658.56 4665.52 "Игорь Лабутин" Когда cancellation token, который передали, канцеляется, то, соответственно, связанный с ним cancellation token source тоже канцеляется. +4665.52 4670.68 "Игорь Лабутин" Это аналоговызовы метода cancel и все токены от него тоже, естественно, являются cancelled. +4670.68 4685.32 "Игорь Лабутин" В этот метод вы можете передать, на самом деле, любое количество cancellation token, и тогда ваш cancellation token source будет заканцелен в том случае, если хотя бы один из внешних токенов заканцелится. +4685.32 4695.24 "Игорь Лабутин" В принципе, это можно использовать, например, для логики вида там, если заканцелилась какая-нибудь операция A или операция B, заканцель нашу тоже. +4695.24 4701.76 "Игорь Лабутин" То есть вы передаете два токена от A и от B в ваш cancellation token source, и он заканцелится, если хотя бы A или B заканцелятся. +4701.76 4703.44 "Игорь Лабутин" Это может быть полезно для этого. +4703.44 4716.20 "Игорь Лабутин" Либо это может быть полезно, если вы, например, в рамках какого-то внешнего токена, cancellation токена, создаете ваш внутренний с какими-то более строгими требованиями, ну, строгими ограничениями. +4716.20 4740.84 "Игорь Лабутин" Это так, например, работает Poly, то есть Poly, когда он получает cancellation token внешний, у него, например, есть некоторые, ну, политика retrieve, скажем, и retrieve - это штука, которая должна там с какими-то timeout, с как-то отработать, и, возможно, эти timeout влезут в общий большой timeout внешнего cancellation токена, поэтому Poly делает простую штуку. +4740.84 4751.48 "Игорь Лабутин" Она создает внутри cancellation token source с этим самым timeout, который говорит там, cancel after нужный timeout, и заодно создает его как linked к внешнему cancellation token. +4751.48 4790.08 "Игорь Лабутин" Поэтому, если эта операция будет отменена снаружи, то Poly автоматически свои токены тоже отменит, и если же у Poly сработает timeout по его внутреннему токену, внешний токен все еще останется неканселенным, но зато внутри Poly выкинется operation canceled exception, и дальше либо Poly сама может его обработать, и, например, повторить операцию, если не из расходного количества попыток, либо выкинуть его наружу дальше и выяснить, что да, все canceled, потому что там timeout, вот это все, то есть можно так использовать для каких-то более тонкой настройки внутренних токенов. +4790.08 4820.20 "Игорь Лабутин" И именно в этом сценарии у вас получится ситуация, что вроде бы, например, вы сказали cancel снаружи на вашем cancellation token source, на каком-то внешнем, внутри не сработал какой-то связный внутренний linked cancellation token source, и именно его токен будет записан в operation canceled exception property cancellation token, а вы снаружи, ну как бы видите токен, но он как бы вообще не относится к вашему, это какой-то внутренний токен от внутреннего токен сорса, поэтому cancellation token и не надо использовать. +4820.20 4844.72 "Игорь Лабутин" Вот такие вот рекомендации, в целом, ну тема с одной стороны простая, казалось бы, что там токен передали, на него периодически смотри, выкидывай наружу, но вот есть интересный момент из cancel after с linked токен сорсами и из cancellation token source в целом, с концепцией, которая может позволить в принципе построить довольно сложные системы на всем этом cancellation. +4844.72 4845.72 "Игорь Лабутин" Такие дела. +4845.72 4866.92 "Анатолий Кулаков" Вообще удивительно, как, знаешь, такая довольно примитивная концепция, ну типа, вот тебе токен, давай с ним сделаешь что-нибудь, и все, то есть это по сути булевый флажок же, да, ну вот булевый флажок отменился, операция или не отменилась, и вот как на основе этого булевого флажка можно сильно так себе усложнить жизнь, сколько можно всего навертеть, как их можно слинковать, какие проблемы туда записать. +4866.92 4869.32 "Анатолий Кулаков" Удивительно, поражаемся этому сложному миру. +4869.32 4891.72 "Игорь Лабутин" Ну, с одной стороны, да, с другой стороны, ну довольно неплохо оно вписано в .NET, да, понятно, что это лишний параметр, который можно было бы там каким-нибудь async local, грубо говоря, передавать, да, и не захламлять сигнатуру функции лишним параметром, но с другой стороны, это в каком-то смысле явный контракт, да, вот я потенциально поддерживаю cancellation. +4891.72 4904.48 "Анатолий Кулаков" Ну, да, да, в этом плане, наверное, тут явность лучше, чем неявность, несмотря на то, что действительно с cancellation токенами очень много мусора появляется в нашем коде, но пока довольно терпимо. +4904.48 4910.20 "Игорь Лабутин" Ну вот, примерно так, есть ли у нас ещё что-нибудь лёгкенькое для, так сказать, отдохнуть? +4910.20 4927.68 "Анатолий Кулаков" Да, да, безусловно, я предлагаю продолжить говорить про cancellation токенами, и у меня тут тоже есть хорошая тема про cancellation, так сказать, продолжим, уже не от Стиффена Клэри, от другого автора, но тем не менее, тоже вполне полезная. +4927.68 4952.32 "Анатолий Кулаков" Касается она того, каким же образом нам нужно отменять async enumerable, то есть это уже не такая какая-то общая тема, не такой какой-то общий подход, как cancellation токены у Клэри, но при этом async enumerable - это довольно мощная вещь, и как правильно с ним работать - это тоже довольно важная штука, в общем, давай немножко углубимся вот в эту узкую тему, ну, прежде всего начнём с печки. +4952.32 5002.12 "Анатолий Кулаков" Современные приложения, безусловно, должны уметь работать с большими данными, как мы выяснили в предыдущем обзадце, в предыдущей теме, и одним из возможностей работать с этими большими данными является естественная синхронность, потому что ты можешь как раз обрабатывать данные не все сразу, а чуть-чуть там по кучкам, по каким-нибудь группкам, и поэтому очень важно уметь итерироваться по этим данным, именно не загружая всё сразу, а загружая, например, по страницам, как мы с тобой обсудили, но важно не только по этим страницам уметь загружать, но ещё и отдавать, а отдавать хотелось бы не прямо по страницам, а может быть даже с точностью до одной записи, то есть страница тоже может быть большой, и зачем нам ждать, пока она вся подгрузится, допустим, из тысячи записей, если мы хотим там начать с первой уже смотреть. +5002.12 5015.00 "Анатолий Кулаков" И вот как раз в C# восьмом появился прекрасный интерфейс, называется iAsyncEnumerableAt, который позволяет нам как раз-таки оперировать с асинхронными стриминговыми сценариями. +5015.00 5019.28 "Анатолий Кулаков" Что же это такое за чудо-зверь iAsyncEnumerableAt? +5019.28 5031.76 "Анатолий Кулаков" Ну, прежде всего, это интерфейс, интерфейс, который позволяет вам пройтись по какому-то набору элементов, и самое главное - сделать это асинхронно, не просто пройтись, а их вернуть. +5031.76 5047.36 "Анатолий Кулаков" Вся эта концепция описывается двумя интерфейсами, очень похожи, естественно, на iEnumerable, поэтому если вы понимаете, как iEnumerable и ForEach работают внутри, то и эта новая концепция не составит для вас никакого труда. +5047.36 5061.92 "Анатолий Кулаков" То есть первый интерфейс это iAsyncEnumerableAt, у которого есть один-единственный метод - getAsyncEnumerator, который этот метод принимает один-единственный параметр - это CancellationToken, и возвращает, как не трудно догадаться, AsyncEnumerator. +5061.92 5067.72 "Анатолий Кулаков" И второй интерфейс в этой концепции - непосредственно сам AsyncEnumerator, у которого два метода. +5067.72 5085.10 "Анатолий Кулаков" Первый метод - это MoveNextAsync, который позволяет продвинуться по набору дальше, то есть на следующую запись, и Current, который синхронно возвращает вам текущий элемент, который мы получили благодаря продвижению по набору из предыдущего метода. +5085.10 5090.32 "Анатолий Кулаков" В общем, и эти два интерфейса прекрасно описывают всю концепцию асинхронного стриминга. +5090.32 5110.28 "Анатолий Кулаков" Данный подход очень гибок и позволяет вам организовать прежде всего асинхронный проход по вашей коллекции, то есть по вашим элементам, и возвращение асинхронного результата, при том возвращение этого результата, который сейчас именно доступен, а не какой должен быть в конце. +5110.28 5115.24 "Анатолий Кулаков" То есть, допустим, если у вас большая коллекция на тысячу элементов, то вы можете возвращать элементы по одному. +5115.24 5126.28 "Анатолий Кулаков" Первый элемент вы получили, вернули его потребителю, в этот момент получаете следующий элемент, а потребитель параллельно может обрабатывать первый элемент, к которому вы его вернули. +5126.28 5131.16 "Анатолий Кулаков" Ну, и также эта концепция позволяет обрабатывать канцеляцию, то есть отмену. +5131.16 5135.68 "Анатолий Кулаков" Как вы поняли, наверное, из предыдущей темы, что отмена – это довольно важная штука. +5135.68 5138.76 "Анатолий Кулаков" В нашем случае, когда важна отмена? +5138.76 5150.56 "Анатолий Кулаков" Отмена важна, например, когда пользователь навигируется по какой-то страничке, страничка начинает загружаться, и в этот момент он решает прекратить навигацию, допустим, в браузере и закрывает страничку. +5150.56 5154.40 "Анатолий Кулаков" По-хорошему, на сервер должна отправиться отмена. +5154.40 5161.80 "Анатолий Кулаков" Если отмена не отправится, то, по сути, сервер будет работать зря, потому что все равно результат, который он наработает, показать будет некому. +5161.80 5170.76 "Анатолий Кулаков" Пользователь закрыл необходимую страничку, поэтому он может там работать, работать, работать, насобирать миллионы данных, отослать их, сериализовать, отослать их назад клиенту, но там их никто не примет. +5170.76 5174.76 "Анатолий Кулаков" Поэтому самым разумным здесь будет это прекратить сервер работать и не тратить зря ресурсы. +5174.76 5185.72 "Анатолий Кулаков" Или, например, мы выполняем какой-нибудь запрос в поисковике, нажали на поиск, и поиск оказался слишком долгим, потому что мы ищем среди какого-то большого набора данных. +5185.72 5186.72 "Анатолий Кулаков" Пользователь не выдержал и отменил его. +5186.72 5194.12 "Анатолий Кулаков" Опять же, если сервер не прекратит обработку, он зря потратит время, потому что пользователь уже не хочет видеть этот результат, он его уже все равно не увидит. +5194.12 5214.32 "Анатолий Кулаков" Если, допустим, у нас не пользователь какое-нибудь взаимодействие между двумя серверами, и один сервер А вызывает сервер Б, и точно так же мы на сервере Б запускаем какой-то страшный, длинный, мощный, долгий отчет, он начинает пилить ресурсы, подогревать процессор в потолок, и вдруг сервер А перехотел его ждать. +5214.32 5217.44 "Анатолий Кулаков" Ну, или просто, например, завершился с ошибкой там и умер. +5217.44 5218.44 "Анатолий Кулаков" Электричество не отключили. +5218.44 5222.68 "Анатолий Кулаков" Опять же, серверу Б нет никакого смысла пылесосить все эти данные. +5222.68 5224.84 "Анатолий Кулаков" Их никто не увидит, они ему не нужны. +5224.84 5227.64 "Анатолий Кулаков" Здесь надо рассчитывать на канцеляцию. +5227.64 5230.00 "Анатолий Кулаков" Вот почему канцеляция – это очень важно. +5230.00 5238.68 "Анатолий Кулаков" Без нее ваши ресурсы, скорее всего, будут зря расходоваться, или может вполне до утечки ресурсов произойти какие-то проблемы. +5238.68 5254.44 "Анатолий Кулаков" Или приложение будет плохо отвечать, потому что оно вместо того, чтобы обрабатывать актуальные запросы, которые нужны прямо сейчас каким-то другим потребителям, оно будет обрабатывать те запросы, которые никто не ждет, которые по идее должны были бы отмениться, и тратить на них больше и больше ресурсов. +5254.44 5260.36 "Анатолий Кулаков" Вот почему нужно канцеляцию всегда предусмотреть в вашем приложении, всегда по ней проходиться и всегда везде учитывать. +5260.90 5267.38 "Анатолий Кулаков" А теперь давайте же разберемся, как работает канцеляция в нашем асинхронном энумераторе. +5267.38 5272.30 "Анатолий Кулаков" Здесь включается магия потребителя. +5272.30 5283.38 "Анатолий Кулаков" Как вы, наверное, знаете, обычный ForEach, когда вы запускаете стандартный кейворд в C#, на самом деле под капотом делает немножко, ну, «множко» различной магии. +5283.38 5296.86 "Анатолий Кулаков" Он не просто идет по коллекции, он ищет у коллекции тот же самый энумератор, запрашивает его, начинает вызывать методы moveNext, начинает вызывать методы current, и все это под капотом. +5296.86 5300.30 "Анатолий Кулаков" То есть вы этого не видите в вашем C# коде, если не воспользуетесь декомпилятором. +5300.30 5303.86 "Анатолий Кулаков" То есть вот это происходит магия внутри ForEach. +5303.86 5315.22 "Анатолий Кулаков" В принципе, такая же точная магия происходит внутри await ForEach, то есть асинхронной версии ForEach, которая работает с вот этим асинхронным итератором, асинхронным энумератором. +5315.22 5323.04 "Анатолий Кулаков" Проблема здесь заключается в том, что как только вы запускаете ForEach, у него нет нормального способа принять cancellation токен. +5323.04 5329.02 "Анатолий Кулаков" А как мы уже сказали, cancellation токен принимать важно, особенно когда мы говорим про асинхронные операции. +5329.02 5338.54 "Анатолий Кулаков" Представьте, вы запустили асинхронный ForEach над коллекцией, у которой там миллион записей, и вот где-то на 101-й захотели его отменить. +5338.54 5339.54 "Анатолий Кулаков" Как это сделать? +5339.54 5365.82 "Анатолий Кулаков" Если бы у нас был обычный метод, который мы вызываем, например, метод get_async_enumerator, этот метод get_async_enumerator принимает в качестве параметра cancellation токен, как я упоминал ранее, но мы не имеем напрямую доступ к этому методу, и его неявно вызывает компилятор, когда разворачивает ForEach, поэтому никакого приличного способа передать туда у нас нет cancellation токен. +5365.82 5370.62 "Анатолий Кулаков" Для этого существуют специальные хаки, методы и магия. +5370.62 5392.78 "Анатолий Кулаков" Хаки заключаются в следующем, как только вы вызываете какой-то метод, который возвращает вам асинхронный enumerator, у этого метода есть, у результата работы этого метода есть специальный метод, который называется view_cancellation, и вот в этот view_cancellation вы уже можете передать асинхронный cancellation токен, который отменит вам вот эту асинхронную операцию. +5392.78 5413.18 "Анатолий Кулаков" То есть как передать его мы вроде выяснили, вот нам специально придумали метод, чем этот метод магический, чем он такой отличается от остальных, а тем, что понимает компилятор, то есть компилятор, когда начнет вам вызывать вот этот асинхронный enumerator, он уже будет учитывать вот этот view_cancellation метод и возьмет оттуда cancellation токен, но он столкнется с другой проблемой. +5413.18 5433.94 "Анатолий Кулаков" Он не знает, куда засунуть этот cancellation токен, потому что на самом деле мы же, когда реализуем асинхронную коллекцию, мы на самом деле не имплементируем iAsyncEnumerable, который умеет принимать cancellation токен, нет, давайте немножко остановимся на этом месте и подумаем, а как мы реализуем клиента, который возвращает асинхронную коллекцию. +5433.94 5434.94 "Анатолий Кулаков" Все очень просто. +5434.94 5435.94 "Анатолий Кулаков" Обычно с помощью yield_return. +5435.94 5440.58 "Анатолий Кулаков" Это самый легкий, самый понятный, самый красивый способ организации асинхронных коллекций. +5440.58 5444.74 "Анатолий Кулаков" У нас есть некий метод, допустим, который возвращает iAsyncEnumerable. +5444.74 5447.46 "Анатолий Кулаков" И как мы его реализовываем? +5447.46 5453.30 "Анатолий Кулаков" Мы просто внутри начинаем писать какой-то длинный фуррич, какую-то загрузку данных, какое-то что-то еще. +5453.30 5459.88 "Анатолий Кулаков" И как только нам становится доступен первый элемент, мы делаем yield_return, этот первый элемент, один единственный. +5459.88 5467.34 "Анатолий Кулаков" Так вот, именно в этом цикле, именно в этом моменте загрузки нам важен cancellation токен, вот сюда мы его должны принять. +5467.34 5468.34 "Анатолий Кулаков" Как же это сделать? +5468.34 5481.34 "Анатолий Кулаков" Если мы просто определим параметр cancellation_token внутри этого метода, то магии не произойдет, потому что на самом деле компилятор понятия не имеет, это тот cancellation_token, который он должен передать в этот аргумент или не тот. +5481.34 5485.86 "Анатолий Кулаков" А если у вас там будет два аргумента, которые принимают cancellation_token, в какой из них он должен засунуть? +5485.86 5490.66 "Анатолий Кулаков" Ну то есть нам как разработчикам кажется, что вопрос довольно плевый. +5490.66 5491.98 "Анатолий Кулаков" Бери, засовывай куда можешь. +5491.98 5500.30 "Анатолий Кулаков" Но компилятор должен работать детерминистично, он не может себе засовывать cancellation_token и куда не попадя, ему нужны специальные понятные правила. +5500.30 5517.98 "Анатолий Кулаков" Поэтому вот в качестве второй такой магии, чтобы подсказать компилятору, а куда засовывать вот этот cancellation_token в наш метод генератора, по сути, который генерирует вот этот выхлоп, есть специальный атрибут, который называется enumerator_cancellation_attribute. +5517.98 5533.34 "Анатолий Кулаков" И вот если вы в вашем методе, который возвращает i_async_enumerable, будете принимать cancellation_token и навесите на этот cancellation_token атрибут enumerator_cancellation, то вот тогда вся магия сработает. +5533.34 5543.94 "Анатолий Кулаков" Компилятор будет знать, как развернуть forage, компилятор будет знать, как из этого forage взять cancellation_token нужный, и компилятор будет знать, как его передать в генератор, из которого получается уже i_async_enumerable. +5543.94 5553.74 "Анатолий Кулаков" Вот такая вот длинная большая цепочка позволяет компилятору правильно пробросить cancellation_token через всю эту магию. +5553.74 5556.82 "Анатолий Кулаков" Почему cancellation_token атрибут очень важен? +5556.82 5568.30 "Анатолий Кулаков" Ну потому что он без него на самом деле компилятор не может понять, как раскрывать forage и как передавать этот cancellation_token из forage в генератор. +5568.30 5578.02 "Анатолий Кулаков" Он настолько важен, что даже существует отдельный warning C# компилятора, но этот warning срабатывает не всегда. +5578.02 5601.06 "Анатолий Кулаков" В принципе, warning довольно понятный, он вам говорит, что вы завели асинхронный итератор, и у этого асинхронного итератора есть cancellation_token, но этот cancellation_token не помечен специальным атрибутом, поэтому идите его и пометьте. +5601.06 5603.26 "Анатолий Кулаков" Ну то есть, хороший warning. +5603.26 5609.94 "Анатолий Кулаков" Единственная проблема в том, что случается он не всегда, а случается он только при совпадении определенных звезд. +5609.94 5612.62 "Анатолий Кулаков" В общем, какие-то условия. +5612.62 5616.70 "Анатолий Кулаков" Ну, во-первых, ваш метод должен возвращать async_enumerable, это нормально. +5616.70 5628.10 "Анатолий Кулаков" Во-вторых, ваш метод должен уже содержать cancellation_token в виде параметра, и этот cancellation_token не должен быть помечен атрибутом enumerator_cancellation_attribute, и вот только тогда вам выдастся warning. +5628.10 5630.78 "Анатолий Кулаков" Ну то есть, это в принципе хорошо, это лучше, чем ничего. +5630.78 5643.54 "Анатолий Кулаков" Ну, гораздо было бы приятнее, если бы вы получали этот warning даже не имея параметра cancellation_token, чтобы вы явно знали, что возвращая async_enumerable, вы всегда должны были бы принимать cancellation_token. +5643.54 5655.42 "Анатолий Кулаков" То есть, в общем, на первом шаге хотелось бы ранее получать это предупреждение, потому что если вы хотя бы добавили cancellation_token, то значит вы уже умные программисты, вы уже предусмотрели эту ситуацию, вы уже это знали и к этому додумались. +5655.42 5661.82 "Анатолий Кулаков" В общем, то, что вы забудете атрибут, ну да, есть такая вероятность, что вы забудете атрибут, компилятор вам в этом поможет, хорошо. +5661.82 5673.14 "Анатолий Кулаков" Но было бы неплохо, если бы он даже предупреждал бы о том, что на том этапе, когда вы даже не засунули туда cancellation_token, уже мог бы бросать warning и говорить, что давайте, чуваки, засунем cancellation_token. +5673.14 5677.14 "Анатолий Кулаков" В общем, ну ладно, допустим, может быть мы к этому тоже когда-нибудь придем. +5677.14 5682.86 "Анатолий Кулаков" Хорошо, что хотя бы так, хорошо, что хотя бы здесь компилятор нам помогает и хотя бы на этом уровне что-то делает. +5682.86 5698.74 "Анатолий Кулаков" Ну, в заключении, async_enumerable - это очень важный интерфейс, он как раз помогает нам закрыть ту большую дыру, которая была у нас в асинхронном программировании, то есть асинхронные коллекции, которые мы можем возвращать не дожидаясь, пока вся коллекция прокрутится. +5698.74 5703.74 "Анатолий Кулаков" Это вообще прекрасный интерфейс и очень часто где юзается, особенно в какой-нибудь потоковой обработке данных. +5703.74 5721.46 "Анатолий Кулаков" enumerable_cancellation_attribute - это критически важный компонент этого интерфейса, было бы неплохо, если бы обязательно все программисты помнили, что при реализации этого интерфейса вам необходимо принимать этот cancellation_token и помечать его правильным атрибутом и как он работает и для чего это было сделано. +5721.46 5732.34 "Анатолий Кулаков" Тогда вы полностью убедитесь, что ваш мультипоточный асинхронный flow работает правильно, корректно и отменится в нужный момент и не будет зря жрать ресурсы. +5732.34 5738.74 "Игорь Лабутин" Действительно, хорошее дополнение к cancellation, к теме про cancellation вообще в целом. +5738.74 5743.86 "Игорь Лабутин" Мне кажется, на этом мы полностью со всех сторон обсудили. +5743.86 5750.22 "Анатолий Кулаков" Да, покрыли знатно, я думаю, наверное, наш летний лёгкий выпуск можно завершать. +5750.22 5758.82 "Игорь Лабутин" Да, наверное, я тоже так думаю, а лёгких тем не осталось, будем ждать каких-нибудь тяжёлых тем, типа там новые идут на превью или что-нибудь в таком духе, но поглядим. +5758.82 5793.26 "Игорь Лабутин" А так мы сегодня посмотрели, как написывается свой собственный garbage collector на C#, но не до конца пока такой, неполноценный, но тем не менее хорошо работающий, посмотрели на pagination, она же постраничность в разных вариантах, курсорная и с оффсетами, узнали всё про cancellation от guru всякого async, асинка cancellation и прочего task-based подходов Стивена Клире, а также посмотрели на async enumerable, как в него правильно пропихивать cancellation токены. +5793.26 5796.22 "Игорь Лабутин" На этом на сегодня, я думаю, всё. +5796.22 5808.98 "Анатолий Кулаков" Да, всем большое спасибо, что были с нами, не забывайте, у нас есть Boosty, у нас есть комментарии, у нас есть почта, пишите любой фидбэк, будем всегда рады, шары, репосты, рассказывания друзьям и всё такое, всем до новых встреч, пока! +5808.98 5809.58 "Игорь Лабутин" Всем пока! diff --git a/input/Radio/Transcriptions/RadioDotNet-119.txt b/input/Radio/Transcriptions/RadioDotNet-119.txt new file mode 100644 index 0000000..9bee9d9 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-119.txt @@ -0,0 +1,707 @@ +0.00 11.00 "Анатолий Кулаков" Приветствую, дорогие слушатели, в эфире радио Дотнет, выпуск номер 119. +11.00 16.00 "Анатолий Кулаков" В нашей студии ее постоянный ведущий Анатолий Кулаков. +16.00 18.00 "Игорь Лабутин" И Игорь Лабутин, всем привет. +18.00 21.00 "Анатолий Кулаков" Жаркое такое лето, что уже начинаю слова путать. +21.00 27.00 "Анатолий Кулаков" Но в принципе нас поддерживают наши бравые помогаторы, и за это им огромное спасибо. +27.00 50.00 "Анатолий Кулаков" Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко, Антон, та самая Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин и Евгений Асташев. +50.00 52.00 "Анатолий Кулаков" Огромное спасибо, друзья, всем, кто нас поддерживает. +52.00 57.00 "Анатолий Кулаков" А если не поддерживаете, заходите, подумайте, может, вы захотите оказаться в этом списке. +57.00 64.00 "Анатолий Кулаков" Кстати, у нас на Boosty есть еще как-нибудь болтальные клубы, разговорные клубы. +64.00 70.00 "Анатолий Кулаков" Если вдруг кто не наболтался или не наслушался наших голосов, мы там еще дополнительно собираемся. +70.00 81.00 "Анатолий Кулаков" И недавно мы записали такие интересные разговоры, как собеседование и рынок .NET, где мы обсуждали различные вакансии и что там сейчас требует от кандидатов. +81.00 89.00 "Анатолий Кулаков" У нас была интересная лекция по GitLab CI, где мы подробно прошлись и разобрали его возможности. +89.00 92.00 "Анатолий Кулаков" Довольно мощная тулза оказалась. +92.00 100.00 "Анатолий Кулаков" И также обсуждали книгу Эванса "Domain Driven Design" и делились своим опытом, насколько она соответствует практике и действительности. +100.00 113.00 "Анатолий Кулаков" В общем, подобные дискуссии мы ведем довольно часто, поэтому если вам интересно поболтать на абстрактные темы около программистки, то милости просим, тоже подписывайтесь, заходите, смотрите, читайте, слушайте. +113.00 122.00 "Анатолий Кулаков" Ну а мы с вами сегодня здесь собрались для того, чтобы обсудить, что же там интересного произошло в мире .NET за те пару недель, которые мы с вами не виделись. +122.00 133.00 "Игорь Лабутин" Но прежде чем мы это обсудим, мы напомним, что нас все еще поддерживает компания Altenar, которая разрабатывает масштабируемые и надежные решения для индустрии спортивных данных, которыми пользуются по всему миру. +133.00 139.00 "Игорь Лабутин" Конечно же они пишут на .NET и на C#, работают с высоконагруженным реалтаймом. +139.00 146.00 "Игорь Лабутин" Разработка компании международная, можно качать английский, можно использовать удобные EDE, наверное даже ходить в офис, где есть кондиционеры. +146.00 154.00 "Игорь Лабутин" И возможно для каких-то наших слушателей это будет очень актуально, как Толя сказал, у нас вполне жарковато в эти дни. +154.00 159.00 "Игорь Лабутин" Для сотрудников, которые вносят большие вклады, возможно продолжение карьеры в европейском офисе. +159.00 164.00 "Игорь Лабутин" Следить за новостями компании можно в телеграм-канале. +164.00 169.00 "Анатолий Кулаков" Все, заканчиваем путаться и переходим непосредственно к темам. Что там у нас сегодня? Микрософт порадовал? +169.00 181.00 "Игорь Лабутин" Микрософт выкатил нам .NET 10 превью 6 и мы естественно сейчас начнем разбираться, что же там новенького и насколько там много новенького. +181.00 186.00 "Игорь Лабутин" Спойлер, не очень много новенького, ну точнее новенького там много, но это все какое-то помелочь в основном. +186.00 190.00 "Игорь Лабутин" Давайте подряд по порядку. Как обычно начинаем с библиотек. +190.00 198.00 "Игорь Лабутин" И из библиотеки в основном изменения коснулись работы с JSON, с сериализацией и десериализацией. +198.00 224.00 "Игорь Лабутин" Во-первых, появилась новая опция под названием allow duplicate properties, которая подразумевает, что поведение десериализатора, оно будет разным, ну точнее оно будет таким, что если эту опцию поставить в false, а по дефолту она в true, то он соответственно не будет разрешать вам десериализовать JSON, в котором есть одинаковые ключи. +224.00 228.00 "Игорь Лабутин" То есть поля с одинаковыми названиями ключей на одном и том же уровне. +228.00 235.00 "Игорь Лабутин" По дефолту такое можно, естественно у вас в вашу десериализованную объект будет попадать последнее значение, которое встретилось. +235.00 238.00 "Анатолий Кулаков" Он не будет разрешать, ты имеешь ввиду, он будет с ошибками подать? +238.00 247.00 "Игорь Лабутин" Ну скорее всего да, я думаю, что это будет ошибкой десериализации, так же как если бы он был какой-нибудь там неправильно форматированный, ну в смысле не закрывающий скобочек не хватает или еще что-то. +247.00 252.00 "Игорь Лабутин" И кроме того, вдобавок к этому добавили новый пресет. +252.00 295.00 "Игорь Лабутин" Как вы знаете, вы можете задать JSON Serializer Options так, как вы хотите, а есть еще пресеты, там точка default, и вот появилась новая точка strict, который устанавливает некоторые, ну скажем так, безопасные дефолты, а именно он не разрешает десериализовывать JSON, у которых есть мемберы, для которых нет, условно говоря, принимающей стороны, то есть если у вас есть объект, в котором есть два поля A и B, а вам пришел JSON с полями A, B и C, и вы поставите JSONUnmappedMemberHandling.dislow, ну такую опцию, то тогда такой JSON нельзя будет десериализовать, такой объект будет требоваться точное соответствие. +295.00 308.00 "Игорь Лабутин" С одной стороны, вроде как это странно для меня, JSON вроде как у нас, это одно из правил обратной совместимости, поля вроде можно добавлять, но тем не менее, наверное, в каких-то сценариях это важно. +308.00 311.00 "Игорь Лабутин" В общем, вот эта опция ставится. +311.00 322.00 "Анатолий Кулаков" Это точно не public API, да, когда ты там от внешнего мира рассчитываешь, что они тебе могут прислать лишние поля, это, наверное, какие-то такие внутренние, там, сохранения в базу, которые ты полностью контролируешь, или какие-то внутренние обмены, что-нибудь такое. +322.00 325.00 "Игорь Лабутин" Да, дальше allow duplicate properties, то самое будет стоять false. +325.00 335.00 "Игорь Лабутин" Дальше он будет проверять case sensitivity, когда будет искать property, то есть будет соответствие полное по регистру подходить. +335.00 341.00 "Игорь Лабутин" И будут включены две опции, respect nullable annotations, respect required constructor parameters. +341.00 350.00 "Игорь Лабутин" Напомню, что раньше JSON deserializer не смотрел на nullable аннотации и вполне мог записать null в поле, которое помечено, что оно не nullable. +350.00 365.00 "Игорь Лабутин" Теперь это все будет, если вы поставите strict, оно будет правильно хендлиться, причем они, то, что называется read-compatible с настройкой default, то есть если вы что-то засериализовали с помощью настройок default, то это можно прочесть через strict. +365.00 367.00 "Игорь Лабутин" Так что особых проблем с переходом не будет. +367.00 378.00 "Игорь Лабутин" А вот если вам что-то действительно присылает вообще снаружи неизвестное, непонятное, не то, что вы сами десериализовали, то там, конечно, strict может быть слишком уж строгим. +378.00 380.00 "Игорь Лабутин" Погоди, то есть читает он не strict, да? +380.00 386.00 "Игорь Лабутин" Нет, читает он strict, но то, что пишется с помощью дефолта, гарантированно прочтется strict. +386.00 389.00 "Игорь Лабутин" В смысле, что у тебя дефолт не умеет записывать duplicate properties. +389.00 392.00 "Игорь Лабутин" У тебя никогда после дефолта не будет duplicate properties. +392.00 397.00 "Анатолий Кулаков" А respect nullable, он же дефолт, по-моему, не респектит nullable ни разу. +397.00 398.00 "Анатолий Кулаков" При записи? +398.00 399.00 "Анатолий Кулаков" Да, при записи. +399.00 401.00 "Игорь Лабутин" А как он может не респектить nullable? +401.00 410.00 "Игорь Лабутин" При записи у тебя предполагается, что ты не можешь положить null в nullable поле. +410.00 414.00 "Анатолий Кулаков" А, ну, в принципе, да, если ты сам респектишь, то, наверное, он тоже... +414.00 421.00 "Игорь Лабутин" Да, нет, естественно, если ты через reflection проставишь все криво в обход всех этих аннотаций, то понятно, что даже дефолт не спасет тут. +421.00 423.00 "Игорь Лабутин" Тут понятно, да, но... +423.00 427.00 "Анатолий Кулаков" В общем, мне нравится strict, в принципе, хорошие у него такие ограничения прям такие. +427.00 429.00 "Анатолий Кулаков" Я бы воспользовался даже. +429.00 449.00 "Игорь Лабутин" Ну вот, дальше я уже говорил, что, по-моему, в позапрошлом, в четвертом превью, начали добавлять постквантумную криптографию, что бы это ни было в практическом смысле, вот ее потихонечку добавляют теперь в Windows CNG, это Cryptography Next Generation, если я правильно помню, механизм Винды. +449.00 463.00 "Игорь Лабутин" Напомню, что в .NET есть, соответственно, реализации, так скажем, кроссплатформенные, но в том числе стандартный класс умеет бандиться к платформенным реализациям тех или иных примитивов, да, криптографии. +463.00 466.00 "Игорь Лабутин" Он, соответственно, начинает добавлять потихонечку виндовую поддержку. +466.00 472.00 "Игорь Лабутин" Если вы вдруг пользуетесь постквантумной криптографией, напишите нам, расскажите, что это такое. +472.00 476.00 "Игорь Лабутин" Зачем это может быть надо в практической жизни, уже прямо сейчас в превью версии .NET. +476.00 478.00 "Игорь Лабутин" Это все по библиотекам. +478.00 484.00 "Игорь Лабутин" Дальше идет рантайм. В рантайме потихонечку работают над перформансом. +484.00 486.00 "Игорь Лабутин" Над чем же еще им работать? +486.00 493.00 "Игорь Лабутин" Во-первых, улучшили код-генерацию для аргументов в виде структур. +493.00 504.00 "Игорь Лабутин" В чем идея? Иногда мы какие-то классы, в смысле какие-то объекты, пытаемся с точки зрения оптимизации объявлять не классами, а структурами. +504.00 509.00 "Игорь Лабутин" Классический пример - объект-точка с двумя координатами. +509.00 515.00 "Игорь Лабутин" Она тогда не локетится в хиппи, если нет боксинга, но про это чуть позднее. +515.00 518.00 "Игорь Лабутин" Передается через значения. +518.00 521.00 "Игорь Лабутин" В некоторых случаях она может даже передаваться через регистры. +521.00 525.00 "Игорь Лабутин" В определенном смысле даже экономия в этом плане - место в стейке. +525.00 528.00 "Игорь Лабутин" И вообще ничего не нужно аллоцировать, все через регистры прям здорово передается. +528.00 531.00 "Игорь Лабутин" Все замечательно, за одним-единственным исключением. +531.00 559.00 "Игорь Лабутин" Если у вас, например, два интовых поля в структуре, а регистры у вас 64-битные, и вы по, допустим, какому-то calling convention runtime понимает, что нужно передать оба 32-битных значения в один 64-битный регистр, то до текущего момента требовалось взять эту структурку, записать ее просто в память куда-то, оттуда из памяти прочитать в регистр и после этого только передать. +559.00 561.00 "Игорь Лабутин" Это, понятно, некоторый overhead. +561.00 571.00 "Игорь Лабутин" Сейчас JIT научился это все самостоятельно делать без необходимости промежуточной памяти, то есть сразу из нужного места структуры, если она правильно выровнена, все кидать в регистр. +571.00 576.00 "Игорь Лабутин" Еще где-то какую-нибудь долю микро... нет, не микро, наносекунды выиграли. +576.00 581.00 "Игорь Лабутин" Но тем не менее, в общем-то структурные аргументы стали лучше быстрее. +581.00 587.00 "Игорь Лабутин" А также улучшили то, что называется loop inversion, то есть разворачивание циклов. +587.00 599.00 "Игорь Лабутин" Разворачивание в данном случае, я сначала, когда начал читать часть статьи, думал, что это про то самое, что если у вас есть for от 0 до 10, то его разворачивают с 10 до 0, но это на самом деле не оно. +599.00 612.00 "Игорь Лабутин" Это про то, что если у вас есть цикл while condition и дальше какое-то тело, то JIT гораздо более эффективно переписать его в формате if condition и внутри if do, потом тело и потом while condition. +612.00 624.00 "Игорь Лабутин" То есть condition, казалось бы, проявляется два раза, но вот эта вот смена while на do while, она сильно помогает дальнейшим оптимизациям вокруг циклов. +624.00 626.00 "Анатолий Кулаков" Интересно, почему? +626.00 634.00 "Игорь Лабутин" Ну, потому что в do while у тебя бранчинг в конце, а в while у тебя бранчинг в начале. +634.00 639.00 "Игорь Лабутин" И это с точки зрения именно вида дерева, ну как это, синтаксического? +639.00 650.00 "Игорь Лабутин" Это не синтаксическое, конечно, но в каком-то смысле синтаксического дерева того, с чем работает JIT, ну это IR, то, что называется intermediate representation. +650.00 654.00 "Игорь Лабутин" Оно гораздо более легко обрабатывается всякими разными алгоритмами. +654.00 658.00 "Игорь Лабутин" А я напоминаю, что у JIT довольно немного времени, чтобы это все сделать. +658.00 668.00 "Игорь Лабутин" Несмотря на всякую нашу tiered компиляцию и то, что в принципе JIT может тратить побольше времени сейчас, все равно у него там нету многих секунд на то, чтобы что-то анализировать, и все равно надо побыстрее. +668.00 673.00 "Игорь Лабутин" И код сейчас написан так, что do while оптимизируется гораздо лучше, чем while. +673.00 677.00 "Игорь Лабутин" И это не значит, что надо писать весь код теперь на do while. +677.00 680.00 "Игорь Лабутин" Пишите, как обычно, JIT теперь умеет все сам. +680.00 684.00 "Анатолий Кулаков" Да-да-да, а то может кому-то хочется все while развернуть. +684.00 687.00 "Игорь Лабутин" Да, руками делать этого не надо. +687.00 694.00 "Игорь Лабутин" Это может, кстати, даже в каком-то смысле испортить оптимизацию JIT, я не уверен. +694.00 697.00 "Игорь Лабутин" Хотя не знаю, может быть он нормально к этому отнесется. +697.00 699.00 "Игорь Лабутин" Дальше, SDK. +699.00 705.00 "Игорь Лабутин" В SDK тут, наверное, самые большие изменения, они касаются следующего. +705.00 713.00 "Игорь Лабутин" Ну, во-первых, если вы публикуете .NET Tool, то я, ну, все мы пользуемся, да, .NET что-нибудь. +713.00 718.00 "Игорь Лабутин" Да, .NET Run, .NET там, какой-нибудь EF, Migrate и так далее. +718.00 721.00 "Игорь Лабутин" Да, это все публикуется в виде .NET Tool. +721.00 732.00 "Игорь Лабутин" Напомню, что это просто какие-то пакеты, которые качаются, и внутри определенным образом запакован библиотека, который содержит нужный для вас исполнимый код. +732.00 745.00 "Игорь Лабутин" Так вот, теперь можно в один пакет запихивать тулы для разных runtime идентификаторов, и .NET Command Line сам поймет, какой из них достать из пакета, и, соответственно, поставить вам в систему и его дальше использовать. +745.00 750.00 "Игорь Лабутин" Для тех, кто пишет тулы, это гораздо, мне кажется, более приятный экспириенс. +750.00 767.00 "Игорь Лабутин" Если, ну, понимаете, вы можете просто опубликовать обычную .NET Nuget сборку универсальную, а можете как-то скомпилировать, например, native-out версии для разных платформ и запаковать их в один Nuget и поставить все нужное. +767.00 775.00 "Игорь Лабутин" Дальше, помимо того, что теперь тулы можно делать вот так вот, можно теперь их не устанавливать. +775.00 786.00 "Игорь Лабутин" Я помню, что сейчас, чтобы заиспользовать какой-нибудь .NET Tool, вы сначала должны сказать .NET Tool install, и дальше либо локально, либо глобально, и только после этого вы можете его использовать. +786.00 800.00 "Игорь Лабутин" Теперь появилась команда .NET Tool exec, которая принимает, собственно, путь к тому, что надо заисполнить, где найти сам тул, саму команду, и прекрасно исполняет без необходимости установки. +800.00 804.00 "Игорь Лабутин" Что может быть полезно в каком-нибудь, не знаю, в CI/CD, например, где вам... +804.00 809.00 "Игорь Лабутин" Ну, вы можете, конечно, поставить, но если все исполняется в докере, то смысла в этом большом нету. +809.00 813.00 "Игорь Лабутин" Все равно все дропнется после того, как билд закончится. +813.00 821.00 "Игорь Лабутин" Поэтому если вам нужен какой-то одноразовый тул, который один раз исполните, больше не надо, то вот .NET Tool exec теперь вполне для этого подходит. +821.00 826.00 "Игорь Лабутин" А поскольку .NET Tool exec писать слишком долго, то есть теперь еще и специальный скриптик. +826.00 832.00 "Игорь Лабутин" Он называется dnx, и что-то мне кажется, что эту аббревиатуру я уже видел где-то в отношении .NET. +832.00 835.00 "Игорь Лабутин" Только я не могу вспомнить, к чему она. +835.00 837.00 "Игорь Лабутин" Что-то с рантаймом было связано тоже. +837.00 841.00 "Игорь Лабутин" Ну, короче, теперь можно писать dnx и дальше название тула, и что сделать. +841.00 846.00 "Игорь Лабутин" И это будет, по сути, аналогом .NET Tool exec, вот это все. +846.00 850.00 "Игорь Лабутин" Ну, это просто специальный скриптик, который тоже, на самом деле, написан на .NET. +850.00 854.00 "Игорь Лабутин" То, что тула написаны на .NET, ее, может быть, будут расширять дальше. +854.00 856.00 "Игорь Лабутин" Пока это просто оберточка простая. +856.00 858.00 "Игорь Лабутин" Дальше. +858.00 880.00 "Игорь Лабутин" Вообще, вокруг Command Line, похоже, Microsoft делает все больше и больше, потому что появилась новая опция --cli-schema у .NET Tool, которая нужна для того, чтобы дропнуть в output, в стандартный output, JSON в описание того, что tool умеет делать. +880.00 885.00 "Игорь Лабутин" То есть это, грубо говоря, набор всех команд, которые в этом туле есть, плюс все опции и аргументы. +885.00 889.00 "Игорь Лабутин" Полезно, если вы что-то хотите автоматизировать или еще что-то с этим сделать. +889.00 895.00 "Анатолий Кулаков" А какой-нибудь стандартный формат для описания вот этой схемы существует, или они что-то сами придумывали? +895.00 897.00 "Игорь Лабутин" Ну, нет, там просто JSON. +897.00 900.00 "Игорь Лабутин" Прямо совсем индустриального стандарта я не знаю. +900.00 904.00 "Игорь Лабутин" Нет, там какой-то JSON, который вот они придумали, что там есть список команд. +904.00 907.00 "Игорь Лабутин" У каждой команды есть список опшенов и список аргументов. +907.00 914.00 "Игорь Лабутин" Ну, и для каждого аргумента и опшена, соответственно, указаны обязательно, и необязательно типа название и какое-то описание. +914.00 916.00 "Игорь Лабутин" Ну, грубо говоря, так. +916.00 919.00 "Анатолий Кулаков" Не, ну просто проблема, она как бы понятная. +919.00 922.00 "Анатолий Кулаков" У тебя есть множество шелов, и эти шеллы хотят делать интеллисенс. +922.00 927.00 "Анатолий Кулаков" Чтобы сделать интеллисенс, они должны знать, какие параметры есть, какие у них там тип принимают и так далее. +927.00 929.00 "Анатолий Кулаков" Ну или красиво там раскрасить, допустим. +929.00 930.00 "Анатолий Кулаков" Да. +930.00 938.00 "Анатолий Кулаков" В общем, и все шеллы сейчас, грубо говоря, ручками заводят сами себе схемы какие-то, раскрашивают под каждую тулу и так далее. +938.00 951.00 "Анатолий Кулаков" Если бы появился индустриальный стандарт какой-то, который рассказывает, каким образом вот эти аргументные командные строки можно выцепить, и каждая командная строка бы их поддержала, то шеллам совсем жить бы легко стало. +951.00 953.00 "Игорь Лабутин" Ну, пока я такого не слышал. +953.00 956.00 "Игорь Лабутин" Каждый шелл живет сам по себе. +956.00 968.00 "Игорь Лабутин" И кажется, Майкрософт здесь просто придумала n+1 стандарт описания или просто взяла какой-то простейший вариант джейсона, минимально необходимый для того, чтобы это все описать, и все. +968.00 971.00 "Игорь Лабутин" Никаких я не видел попыток стандартизации вокруг этого. +971.00 973.00 "Игорь Лабутин" Но, может быть, я что-то не знаю. +973.00 981.00 "Анатолий Кулаков" Ну, если она, типа, может во всех своих тулзах, там во всей операционной системе как-нибудь это протащит, поддержит, то, может, остальные тоже потянутся. +981.00 983.00 "Анатолий Кулаков" Просто хорошее движение такое, в нужную сторону, в правильную. +983.00 984.00 "Игорь Лабутин" Поглядим, поглядим. +984.00 985.00 "Игорь Лабутин" Да. +985.00 1002.00 "Игорь Лабутин" Дальше напомню, что у нас появилась возможность запускать файлики без необходимости компиляции и вообще создания csproj, то есть вы можете создать cs-файлик специальными директивами через решеточку в начале файлика прописать там всякие импорты и все такое прочее, и запустить. +1002.00 1010.00 "Игорь Лабутин" Это все уже было доступно в прошлом превью, или даже на превью назад, ну, не принципиально, в общем, к текущему. +1010.00 1012.00 "Игорь Лабутин" Это не новость для текущего превью. +1012.00 1016.00 "Игорь Лабутин" А вот в текущем превью очень сильно эту возможность прокачали. +1016.00 1031.00 "Игорь Лабутин" Во-первых, теперь можно запаблишить такую одну файловую программу сразу в nativeout, то есть можно не dotnetrun, там app.cs, а dotnetpublish.app.cs, вы получите сразу executable на вашей платформе. +1031.00 1032.00 "Игорь Лабутин" Это первое. +1032.00 1034.00 "Игорь Лабутин" Второе, можно референсить проект. +1034.00 1048.00 "Игорь Лабутин" То есть вы можете в вашем app.cs написать теперь решетку .project и дальше ссылочку, просто путь в файловой системе, там classlib/classlib.csproj и зареференсите, соответственно, csproj. +1048.00 1053.00 "Игорь Лабутин" Он будет собираться, как будто вы из вашего основного проекта зареференсили csproj. +1053.00 1055.00 "Игорь Лабутин" И это может быть полезным. +1055.00 1060.00 "Игорь Лабутин" Я так понимаю, что это было добавлено в основном ради запросов в так сказать комьюнити. +1060.00 1074.00 "Игорь Лабутин" Если у вас есть, например, какая-нибудь, ну, допустим, либо полезная, ну, какой-нибудь там, не знаю, fluentvalidation, тот самый, тот же самый, да, какой-нибудь, короче, либо, и вы хотите накидать каких-нибудь примеров, которые пользователь может просто позапускать. +1074.00 1085.00 "Игорь Лабутин" Вы, соответственно, пишете такие однофайловые программки примеров, в каждом из которых делаете ссылку на основную либу, прямо на csproj в вашем же гитхаб-репозитории. +1085.00 1091.00 "Игорь Лабутин" И таким образом вы можете легко делать однострочные приложения. +1091.00 1092.00 "Игорь Лабутин" Вот. +1092.00 1094.00 "Игорь Лабутин" Ой, не однострочные, а однофайловые, конечно же. +1094.00 1096.00 "Игорь Лабутин" Пока еще не однострочные. +1096.00 1120.00 "Игорь Лабутин" Дальше, внутри этого самого однофайлового приложения теперь доступны специальный образом информация о том, как назывался ваш, путь, короче, к вашему файлу и к директории, через system.appcontext.getdata, передавая туда два специальных названия, это entry_point_file_path и entry_point_file_directory_path, вы можете получить пути. +1120.00 1127.00 "Игорь Лабутин" Но при этом, если вы ваш app.cs запаблишите в nativeout или конвертнете в полный проект, то эти штуки уже недоступны. +1127.00 1132.00 "Игорь Лабутин" Они доступны только вот если вы запускаете через .NET Run, грубо говоря, app.cs. +1132.00 1140.00 "Игорь Лабутин" А самая главная фишка — это то, что называется, у них называется enhanced Shebang support. +1140.00 1142.00 "Игорь Лабутин" На самом деле смысл в следующем. +1142.00 1148.00 "Игорь Лабутин" Сейчас для того, чтобы запустить однофайловое приложение, вам нужно написать .NET Run app.cs. +1148.00 1154.00 "Игорь Лабутин" Shebang, напомню для тех, кто не знает, это штука, которую вы можете написать в начале файла. +1154.00 1156.00 "Игорь Лабутин" Решетка — восклицательный знак. +1156.00 1163.00 "Игорь Лабутин" И дальше после этого вы пишете исполнимую команду, которую нужно применить для того, чтобы этот файл запустить. +1163.00 1172.00 "Игорь Лабутин" Все линуксовые системы в среднем ровно так работают, то есть используют эту Shebang-команду для того, чтобы запускать. +1172.00 1180.00 "Игорь Лабутин" То есть когда вы, допустим, просто запустите в командной строке ./app.cs, он посмотрит в app.cs, возьмет первую строку. +1180.00 1193.00 "Игорь Лабутин" Если он там увидит решетку восклицательный знак, он возьмет все, что после и добавит туда название вашего запускаемого файла и эту штуку попытается запустить. +1193.00 1202.00 "Игорь Лабутин" Проблема в том, что нам же нужно указать .NET Run и потом только туда дописать имя программы, которую вы запускаете. +1202.00 1205.00 "Игорь Лабутин" Но при этом кто такой .NET тоже неизвестно. +1205.00 1208.00 "Игорь Лабутин" В разных системах этот самый .NET может быть разный. +1208.00 1217.00 "Игорь Лабутин" Поэтому один из способов, как вы это можете сделать на линуксовых системах, например, вы пишете в Shebang-е usr.bin.env.probel.net. +1217.00 1221.00 "Игорь Лабутин" Usr.bin.env - стандартная программа, которая найдет какой-нибудь .NET в вашем окружении. +1221.00 1227.00 "Игорь Лабутин" Но проблема дальше возникает в том, что по сути нам сейчас нужно написать теперь usr.bin.env.probel.net.probel.run. +1227.00 1233.00 "Игорь Лабутин" И не все системы поддерживают вот такие многоаргументные Shebang-и. +1233.00 1235.00 "Игорь Лабутин" Поэтому в итоге сделали следующее. +1235.00 1240.00 "Игорь Лабутин" Вы можете теперь писать не .NET Run app.cs, а просто .NET.probel.app.cs. +1240.00 1242.00 "Игорь Лабутин" И этого будет достаточно. +1242.00 1245.00 "Игорь Лабутин" Более того, можно не указывать расширение .CS. +1245.00 1247.00 "Игорь Лабутин" То есть вы можете написать .NET app. +1247.00 1251.00 "Игорь Лабутин" Он сам найдет файлик под названием app.cs в текущей директории и запустит его. +1251.00 1266.00 "Игорь Лабутин" И в итоге это означает, что теперь, если вы можете написать файл hello.cs, в первой строчке написать Shebang, соответственно, решетку, сказать, например, usr.bin.env.probel.net, во второй строчке какой-нибудь там Console.WriteLine.hello. +1266.00 1271.00 "Игорь Лабутин" Сохраните этот файл в формате, в виде имени, просто hello. +1271.00 1275.00 "Игорь Лабутин" Точнее, вы можете сохранить его в виде hello.cs. +1275.00 1279.00 "Игорь Лабутин" А можете даже просто сохранить его в виде скрипта под названием hello. +1279.00 1283.00 "Игорь Лабутин" И запустить его просто ./hello. +1283.00 1287.00 "Игорь Лабутин" И ваша Linux-операционная система все найдет. +1287.00 1289.00 "Игорь Лабутин" .NET сам поймет, что можно .CS не указывать. +1289.00 1291.00 "Игорь Лабутин" Он посчитает этот .CS файликом. +1291.00 1293.00 "Игорь Лабутин" И, короче, все запустит. +1293.00 1303.00 "Игорь Лабутин" И фактически мы получаем возможность сделать исполнимый файлик прямо на .NET без необходимости писать .CS расширение, а просто в виде программки ./hello. +1303.00 1309.00 "Игорь Лабутин" Мне кажется, это практически финальный вариант того, как можно писать скрипты на шерпе. +1309.00 1311.00 "Анатолий Кулаков" Ну, смело-смело. +1311.00 1313.00 "Анатолий Кулаков" А что, если у тебя файлик называется run? +1313.00 1316.00 "Анатолий Кулаков" Он что делает? Запустит файлик или запустит команду .NET run? +1316.00 1317.00 "Игорь Лабутин" Не знаю. +1317.00 1321.00 "Игорь Лабутин" Возможно, попробует запустить run .CS. +1321.00 1326.00 "Игорь Лабутин" Если такого нету, скажет, ну, команда run, ей не хватает аргумента. +1326.00 1328.00 "Игорь Лабутин" Я не пробовал, честно скажу. +1328.00 1329.00 "Анатолий Кулаков" Ну, тогда результат непредсказуемый будет. +1329.00 1332.00 "Анатолий Кулаков" Типа, если он найдет случайно файлик в текущей директории, то запустит файлик. +1332.00 1333.00 "Анатолий Кулаков" Если не найдет, запустит что-то другое. +1333.00 1334.00 "Анатолий Кулаков" Как-то непредсказуемо. +1334.00 1335.00 "Анатолий Кулаков" Все так. +1335.00 1338.00 "Игорь Лабутин" Возможно, там есть какие-то явные на эту тему ограничения. +1338.00 1341.00 "Игорь Лабутин" Возможно, run всегда будет запускать команду. +1341.00 1348.00 "Игорь Лабутин" Я бы сказал, что это, наверное, более логичное поведение, потому что вряд ли ты будешь делать тулу или скрипт, который просто называется run. +1348.00 1350.00 "Игорь Лабутин" Хотя для скрипта название хорошее. +1350.00 1351.00 "Игорь Лабутин" Не поспоришь. +1351.00 1354.00 "Анатолий Кулаков" Ну, и команды, они-то могут добавляться. +1354.00 1359.00 "Анатолий Кулаков" У тебя твой скрипт сегодня выполнялся, а завтра добавилась команда с именем твоего скрипта, и он выполняться перестал. +1359.00 1361.00 "Анатолий Кулаков" Тоже не очень хорошие перспективы. +1361.00 1362.00 "Игорь Лабутин" Это правда. +1362.00 1363.00 "Игорь Лабутин" Не знаю, как решили. +1363.00 1364.00 "Игорь Лабутин" Надо будет посмотреть. +1364.00 1366.00 "Игорь Лабутин" Ничего не скажу сейчас. +1366.00 1375.00 "Анатолий Кулаков" Мне кажется, гораздо лучше решение было бы, если бы они как раз завели себе отдельный экзешник, который называется какой-нибудь dnx, и в шибанг бы вставляли именно этот dnx. +1375.00 1380.00 "Анатолий Кулаков" Тогда не было бы никаких вопросов с другими какими-то командами, параметрами, поиском, еще чем-то. +1380.00 1390.00 "Анатолий Кулаков" Потому что мы точно знаем, что этот экзешник, ну, что этот dnx, предположим, используется только для того, чтобы запускать скриптовые c# файлики. +1390.00 1392.00 "Анатолий Кулаков" И все, и тут вопросов вообще никаких нет. +1392.00 1393.00 "Анатолий Кулаков" Может. +1393.00 1395.00 "Анатолий Кулаков" Зачем они начали сюда .NET как-то подковыриваться? +1395.00 1409.00 "Игорь Лабутин" Возможно, они это делают, чтобы пока на, ну, как бы, используя стандартный вариант, без необходимости писать какой-то отдельный тулзень, обкатать это все до конца, а к релизу-таки сделать отдельную тулу. +1409.00 1411.00 "Игорь Лабутин" Вполне допускаю, что и так. +1411.00 1419.00 "Анатолий Кулаков" Ну, вот оставить вместе с cs, это, в принципе, довольно безопасно, потому что по окончанию cs ты всегда можешь распознать, это команда или файлик ты ищешь. +1419.00 1423.00 "Анатолий Кулаков" Ну, без расширения это будет просто какая-то адовая яма. +1423.00 1427.00 "Игорь Лабутин" Ну вот, посмотрим-посмотрим, во что это превратится в момент релиза. +1427.00 1434.00 "Игорь Лабутин" Так, из новостей еще по ASP.NET, ну, в основном тут всякий Blazor улучшение. +1434.00 1450.00 "Игорь Лабутин" Из неблэйзерных - это то, что ASP.NET довольно активно внутри использует всякие мемори-пулы для того, чтобы там массивы байтов, понятно, под реквесты, респонсы и прочие штуки, значит, себе хранить. +1450.00 1466.00 "Игорь Лабутин" Так вот раньше, если какие-то из мемори-пула он память достал, и вернул в пул, то если, например, у вас был какой-то период большой нагрузки, когда из этого пула доставали большое количество памяти, большое количество памяти в него вернули, они там висели и никак не использовались. +1466.00 1476.00 "Игорь Лабутин" Сейчас теперь появилась логика, что если у вас приложение ничего не делает, то есть если какое-то время из мемори-пула память не нужна, она оттуда начинает потихонечку очищаться и возвращаться в системе. +1476.00 1480.00 "Игорь Лабутин" Ну, в принципе, наверное, логичное поведение, почему бы и нет. +1480.00 1486.00 "Игорь Лабутин" Отдельный вопрос, как они понимают, что приложение IDLE, это надо изучать. +1486.00 1488.00 "Игорь Лабутин" Не знаю, кстати, ничего не было на эту тему. +1488.00 1492.00 "Игорь Лабутин" А также можно теперь для SPNet вот этот самый мемори-пул подменять. +1492.00 1494.00 "Игорь Лабутин" Появился специальный интерфейс iMemoryPoolFactory. +1494.00 1510.00 "Игорь Лабутин" Во-первых, вы можете его к себе просто заинжексить и из него доставать нужные вам мемори-пулы, а можно и заинжексить свою реализацию iMemoryPoolFactory, и тогда SPNet Core будет использовать вашу мемори-пулу, если вы, например, хотите какой-то странной реализации мемори-пула. +1510.00 1532.00 "Игорь Лабутин" Ну, в общем, про WebAssembly, ой, про WebAssembly, про Blazor особо рассказывать не буду, тут какие-то довольно точечные улучшения, типа там форм-валидации улучшились, там not found handler правильно работает теперь даже, когда у вас стриминг начался, диагностики в очередной раз улучшили и так далее. +1532.00 1540.00 "Игорь Лабутин" А еще из неблэзерных штук добавили PASKEY, авторизацию и поддержку его в SPNet Core Identity. +1540.00 1546.00 "Игорь Лабутин" Это штука, которая построена на новых современных стандартах WebAuthn и FIDO2. +1546.00 1556.00 "Игорь Лабутин" И если вы возьмете Blazor WebApp Template, тут тоже не обошлось без Blazor, там прям есть встроенная поддержка и менеджмента этих PASKEY-ов, и функциональности логина. +1556.00 1562.00 "Игорь Лабутин" Поэтому, если интересно посмотреть, берите Blazor WebApp Template на последнем превью и там, смотрите, там все будет. +1562.00 1575.00 "Игорь Лабутин" Ну и наш любимый IProblemDetails, про который мы много раз уже рассказывали, и теперь нормально дружит с Minimal API, можно кастомизировать, короче, что там возвращается из Minimal API, странно, что это раньше было нельзя сделать. +1575.00 1595.00 "Игорь Лабутин" А больше, собственно, новостей в этом релизе нет, но в MAUI там, как обычно, какие-то небольшие инхансменты есть, которые оказались достойной пары ссылок в статье про новые, новую версию, но больше ничего. Не в C#, не в F#, не в EF, никаких существенных новостей я не нашел. +1595.00 1601.00 "Анатолий Кулаков" Ну, кстати, уже лето, уже должны какие-то большие выкатывать в куски, неужели это всё? +1601.00 1603.00 "Анатолий Кулаков" Может, ничего нам больше такого не готовят? +1603.00 1607.00 "Анатолий Кулаков" Это же у нас LTS будет, правильно я понимаю? +1607.00 1609.00 "Анатолий Кулаков" Да, четный LTS. +1609.00 1615.00 "Анатолий Кулаков" Может, они сосредоточились просто на перформансе и стабилизации, чтобы ничего в этом LTS не нарушить? +1615.00 1623.00 "Игорь Лабутин" Либо выгодится в сентябре-октябре какой-нибудь убер-мега-фичу, типа экстендженов, которые еще раз что-нибудь поменяют. +1623.00 1625.00 "Игорь Лабутин" Экстенджены сейчас есть, насколько я помню, правильно? +1625.00 1627.00 "Игорь Лабутин" Их же никуда не откатили. +1627.00 1631.00 "Анатолий Кулаков" Да, пока они есть. Они с уродским синдексом, но всё-таки пока вроде не откатывают. +1631.00 1633.00 "Игорь Лабутин" Ну вот, поглядим. +1633.00 1641.00 "Игорь Лабутин" Не знаю пока. Кажется, что общий вайп такой, что что-то, наверное, готовят, но что - пока непонятно. +1641.00 1645.00 "Игорь Лабутин" И как-то, кстати, знаешь, поймался я сейчас на мысли? +1645.00 1647.00 "Игорь Лабутин" Помнишь, я рассказывал про Aspire? +1647.00 1649.00 "Игорь Лабутин" Как его там называлось? +1649.00 1651.00 "Игорь Лабутин" Не... +1651.00 1653.00 "Игорь Лабутин" Roadmap. Вот, я вспомнил это слово. +1653.00 1655.00 "Игорь Лабутин" Aspire Roadmap. +1655.00 1659.00 "Игорь Лабутин" Про то, что они обещали там релизы раз в месяц, вот это всё, и что-то как-то... +1659.00 1661.00 "Анатолий Кулаков" По-моему, не было. +1661.00 1667.00 "Игорь Лабутин" Либо я пропустил, и он был такой майнер, но что-то мне кажется, что мы уже два выпуска не рассказывали про Aspire. +1667.00 1669.00 "Игорь Лабутин" Ничего. Так что... +1669.00 1673.00 "Игорь Лабутин" Ну, кстати, ну, лета, отпуска, наверное, всё-таки тоже как-то влияет. +1673.00 1677.00 "Анатолий Кулаков" Роадмот подстраивается под отпуска. Конечно. +1677.00 1681.00 "Игорь Лабутин" И под хайп там искусственный интеллект, да, вот это всё. +1681.00 1683.00 "Игорь Лабутин" Такие дела. +1683.00 1685.00 "Анатолий Кулаков" Ладно, давай не будем о плохом. Давай. +1685.00 1687.00 "Анатолий Кулаков" Вернёмся к доброму вечному. +1687.00 1689.00 "Анатолий Кулаков" Предлагаю поговорить про DDD. +1689.00 1695.00 "Анатолий Кулаков" Как бы о чём ещё можно в таким жарким погодой рассуждать, кроме о том, как сделать красиво. +1695.00 1701.00 "Анатолий Кулаков" Мы же помним, что в C# нет никаких проблем, кроме того, как рефакторить чистую архитектуру и DDD. +1701.00 1703.00 "Анатолий Кулаков" Так вот, почему бы нам приступить? +1703.00 1711.00 "Анатолий Кулаков" Хотелось бы рассказать о интересном практическом примере, как можно отрефакторить анемичную модель под всякие DDD-каноны. +1711.00 1731.00 "Анатолий Кулаков" И переделать анемичную модель в богатую модель. В общем, звучит как-то страшно, то есть я думал, что на слух не очень удобно будет приниматься рефакторинг, но в принципе статья довольно хорошо описывает сами концепции, в которых необходимо мыслить, куда необходимо думать, и кода в ней довольно-таки немного, поэтому я думаю о сильном. +1731.00 1737.00 "Анатолий Кулаков" Тем более у нас слушатели все опытные, они уже умеют представлять и компилировать коды в голове, поэтому проблем особо, думаю, не будет. +1737.00 1755.00 "Анатолий Кулаков" Погнали! Итак, что же такое у нас, в чем собственно проблема? Ну, представьте, залезаете вы в какой-нибудь ваш старый Legacy SharpCode, и самым больным местом, обычно, на который вы натыкаетесь, это всякие анемичные модели. +1755.00 1759.00 "Анатолий Кулаков" Например, представим, какой-нибудь OrderService, который, естественно, отвечает за ордеры. +1759.00 1763.00 "Анатолий Кулаков" И обычно в этом классе напихано абсолютно все, что только возможно. +1763.00 1765.00 "Анатолий Кулаков" Этот OrderService делает все. +1765.00 1783.00 "Анатолий Кулаков" Он определяет цену всех своих элементов, определяет скидки, которые доступны клиентам, лезет на склад, смотрит остатки, пишет в базу, читает с базы, в общем, берет на себя абсолютно всю ответственность, которая только есть, и работает он прекрасно до тех пор, пока не сломается. +1783.00 1787.00 "Анатолий Кулаков" Но как только он сломается, то починить его будет довольно сложно. +1787.00 1793.00 "Анатолий Кулаков" Ну и вообще, вот эта вся структура, когда у нас все запихнуто в один сервис, она довольно такая нестабильная. +1793.00 1795.00 "Анатолий Кулаков" Ну, например, очень сложно на нее писать тесты. +1795.00 1801.00 "Анатолий Кулаков" Потому что у тебя одноменный код очень сильно переплетен с инфраструктурным кодом. +1801.00 1807.00 "Анатолий Кулаков" Поэтому такую штуку тестировать практически нереально. Тесты, скорее всего, будут сложнее, чем этот код вместе взятый. +1807.00 1819.00 "Анатолий Кулаков" И как только вы видите вот такую большую свалку всего подряд в одном методе или в одном классике, то это верный признак тому, что вы столкнулись с анемичной моделью. +1819.00 1827.00 "Анатолий Кулаков" Анемичная модель - это как раз-таки такой подход, когда ваши классики, ваши сущности просто содержат данные, и все. +1827.00 1833.00 "Анатолий Кулаков" А вот логика, которая обрабатывает эти данные, они никогда не владеют. +1833.00 1835.00 "Анатолий Кулаков" Логика обычно размазана везде. +1835.00 1843.00 "Анатолий Кулаков" То есть у вас есть какой-то сервис по добавлению новых ордеров, он там что-то делает, как-то валидирует, как-то проверяет эти ордеры, а может и не валидирует вообще. +1843.00 1867.00 "Анатолий Кулаков" Потом есть какой-нибудь сервис про перемещение ордеров, у него там какая-то логика есть, и вот все это размазано по вашему огромному приложению. И если вы вдруг задаетесь целью поменять поведение ордера, то флаг вам в руки и большую удачу, потому что у вас скорее всего это не получится, тем более что тестов нет. В общем, любые изменения с такими классами, с такими анемичными моделями обычно приводят к ужасающим последствиям. +1867.00 1879.00 "Анатолий Кулаков" Ну, жизнь еще более-менее сладка, когда у вас довольно маленькое приложение, когда действительно там нужно пару точек на экране нарисовать и линию между ними провести, тогда анемичные модели еще более-менее терпимы. +1879.00 1893.00 "Анатолий Кулаков" Но если вы нормальный интерпрайз-разработчик, и у вас как бы вокруг множество команд, множество интерпрайза, и множество перекладываний джессонов, то там с анемичными моделями жить довольно сложно. +1893.00 1901.00 "Анатолий Кулаков" И в этот момент люди переходят, осознают, что тяжкую дорогу они выбрали, и переходят все-таки к богатой доменной модели. +1901.00 1903.00 "Анатолий Кулаков" Вот. +1903.00 1919.00 "Анатолий Кулаков" И вот мы с вами попытаемся несколько базовых концепций, несколько базовых шагов определить, а как же туда переходить. Ну, прежде чем мы начнем переходить, давайте все-таки какую-нибудь стартовую точку обозначим, то есть что мы имеем на данный момент. +1919.00 1933.00 "Анатолий Кулаков" Допустим, у нас есть OrderService, выше обозначенный, и разберем один его метод. Я думаю, одного нам будет достаточно. Итак, есть метод PlaceOrder, который как раз-таки создает новый ордер и запихивает в него элементы. +1933.00 1937.00 "Анатолий Кулаков" Какие-то покупки, которые в рамках этого ордера совершаются. +1937.00 1947.00 "Анатолий Кулаков" Данный метод, представим, что принимает идентификатор кастомера и список элементов, которые необходимо засунуть нам в этот ордер. +1947.00 1953.00 "Анатолий Кулаков" Что на текущий момент у нас есть? Старый такой весь анемичный сервис. +1953.00 1969.00 "Анатолий Кулаков" Анемичный сервис у нас по легенде достает кастомера по его идентификатору из базы данных, создает ордер пустой, заполняет все поля у этого ордера необходимыми значениями. Например, присваивает кастомер ID для этого ордера. +1969.00 1973.00 "Анатолий Кулаков" Дальше он может пробежаться по всем айтамам, которые необходимо заполнить. +1973.00 1977.00 "Анатолий Кулаков" Создать все эти айтамы. +1977.00 1987.00 "Анатолий Кулаков" Также он может, например, проверить, что у нас есть необходимое число товаров на складе, которые мы хотим добавить к ордеру. +1987.00 1989.00 "Анатолий Кулаков" Если их нет, то бросить какое-нибудь исключение. +1989.00 1993.00 "Анатолий Кулаков" Он также может проверить цену у этих товаров. +1993.00 1995.00 "Анатолий Кулаков" Например, применить какой-нибудь дисконт. +1995.00 1997.00 "Анатолий Кулаков" То есть, какую-нибудь скидочку. +1997.00 2009.00 "Анатолий Кулаков" Если у кастомера является VIP-клиент и он любит скидочки, то есть мы можем на основании кастомера применить какую-то скидку к этому товару и уже непосредственно добавить в конце к ордеру. +2009.00 2027.00 "Анатолий Кулаков" Дальше нам необходимо подсчитать, сколько все-таки стоит полноценный ордер со всеми своими товарами, со всеми своими документами. И можно еще даже у кастомера проверить, здесь же хватает ему ли денег на то, чтобы купить этот ордер, чтобы оплатить этот ордер. То есть не превысил ли кастомер свой денежный лимит. +2027.00 2029.00 "Анатолий Кулаков" Все это делается в одном методе. +2029.00 2037.00 "Анатолий Кулаков" После того, как успешно все вот эти параметры проверены, все валидации и процедуры сделаны, ордер сохраняется в базу данных. +2037.00 2041.00 "Анатолий Кулаков" База данных у нас представлена здесь с Entity Framework. +2041.00 2045.00 "Анатолий Кулаков" И на этом метод свою работу завершает. +2045.00 2049.00 "Анатолий Кулаков" Как вы поняли, как бы в этом методе смешано абсолютно все. +2049.00 2069.00 "Анатолий Кулаков" У нас размазаны правила абсолютно где угодно, абсолютно везде. То есть этот метод отвечает и за скидки, и за наличие на складе товара, и за проверяет кредитный лимит нашего клиента. В общем, слишком много правил на него наложено. +2069.00 2071.00 "Анатолий Кулаков" Так это приводит к очень большой связанности. +2071.00 2083.00 "Анатолий Кулаков" Потому что вот этот ордер-сервис, он обязан знать абсолютно про все, что касается ордера. Те же самые цены, те же самые остатки на складах. +2083.00 2091.00 "Анатолий Кулаков" Тот же самый Entity Framework сюда пролез. То есть мы непосредственно общаемся практически с голой базой данных. +2091.00 2105.00 "Анатолий Кулаков" И если мы вдруг задумаемся, как бы этот метод протестировать, то это будет довольно-таки сложно. Потому что для тестирования этого метода нам необходимо замокать очень много сложных сущностей. Ну, самая первая проблема, которая у нас возникнет, это база данных. +2105.00 2111.00 "Анатолий Кулаков" За это замокать Entity Framework результативно хорошо и качественно у вас не получится. +2111.00 2115.00 "Анатолий Кулаков" Потом ему нужно замокать прайсинг. +2115.00 2125.00 "Анатолий Кулаков" То есть сервис для предоставления цен, сервис для предоставления остатков. Ему необходимо замокать сервис, который рассказывает, какие кастомеры являются, какая у кастомеров скидка. +2125.00 2133.00 "Анатолий Кулаков" Вот это все. В общем, каждый такой тест, ему будет необходимо мокать огромную кучу зависимостей. +2133.00 2153.00 "Анатолий Кулаков" И так как это все внутри одного метода написано, то код комплексити у такого теста, у такого метода очень большой, и тестировать его очень сложно будет. То есть у нас огромная вариативность различных моковых параметров будет на входе. В общем, результативо получите очень хрупкий юнит теста. +2153.00 2183.00 "Анатолий Кулаков" Что же мы хотим делать? Ну, прежде всего мы хотим перенести все правила именно внутрь домена. Все доменные правила. И хотим оставить на уровне аппликейшена, то есть на уровне вот этого ордер сервиса, только возможности оркестрации нашими доменными сущностями. Чтобы все было на своих местах, и чтобы все читалось и использовалось довольно гибко, правильно и тестибельно. +2183.00 2191.00 "Анатолий Кулаков" Для того, чтобы нам посуществить следующий рефакторинг, нам необходимо задекларировать и придерживаться некоторых принципов. +2191.00 2197.00 "Анатолий Кулаков" Обозначим эти принципы. Итак, прежде всего нам нужно поместить варианты как можно ближе к данным. +2197.00 2203.00 "Анатолий Кулаков" Такие штуки, например, как остатки, как скидки, как кредиты. +2203.00 2213.00 "Анатолий Кулаков" В общем, все это должно жить рядом с теми данными, и с той логикой, которой эти данные владеют. +2213.00 2217.00 "Анатолий Кулаков" В нашем случае это агрегат ордера. +2217.00 2223.00 "Анатолий Кулаков" Внутри ордера должна жить логика, которая определяет, сколько скидок и по какой цене это все продавать. +2223.00 2229.00 "Анатолий Кулаков" И поведение, то есть сама логика определения, должна быть там же, где и данные. +2229.00 2233.00 "Анатолий Кулаков" Так как данные у нас хранятся в ордере, значит и поведение должно быть именно там. +2233.00 2237.00 "Анатолий Кулаков" То есть все это нам нужно снести в агрегат ордера. +2237.00 2245.00 "Анатолий Кулаков" Также следующий принцип это то, что мы должны рассказывать, что мы хотим делать, но не показывать, как мы это хотим делать. +2245.00 2255.00 "Анатолий Кулаков" Например, если мы посмотрим на наш метод в сервисе, который добавлял ордер, то его читать довольно сложно. +2255.00 2267.00 "Анатолий Кулаков" Он состоит из строк, которые рассказывают о том, что нам нужно посчитать общее количество элементов, как-то добавить, как-то посчитать кредит, каким-то образом записать в базу данных. +2267.00 2291.00 "Анатолий Кулаков" В общем, это все довольно-таки низкоуровневые операции. Хотелось бы видеть просто метод, который создает ордер, добавляет туда какие-то элементы и все. То есть более читабельный такой он должен быть, более понятный и более красивый. Также мы хотим придерживаться принципов, что рефакторить нам надо некими кусочками. Мы не хотим зайти туда, разворотить весь код и большим куском все переписать. +2291.00 2305.00 "Анатолий Кулаков" Мы должны выбирать какие-то маленькие части и потихонечку их переносить. И после каждого переноса желательно, чтобы код оставался целостным и компилируемым. В общем, это нам поможет такими маленькими кусочками совершать какие-то поступательные действия. +2305.00 2311.00 "Анатолий Кулаков" Может быть даже в промежутках запускать тесты, если бы мы смогли их написать, которые подтверждают, что мы идем правильным путем. +2311.00 2333.00 "Анатолий Кулаков" Дальше нам необходимо соблюдать баланс между чистотой и прагматизмом. То есть если вы добавляете какие-то строчки кода, то они должны быть зачем-то нужны. Не просто потому, что чисто архитектурой это красиво или мы хотим, чтобы все было по лучшим канонам, по лучшим практикам. Они должны приносить какое-то понятное value. +2333.00 2341.00 "Анатолий Кулаков" То есть код становится читабельным, код становится безопасным, код становится более тестируемым. То есть мы должны понимать, зачем мы это делаем. +2341.00 2349.00 "Анатолий Кулаков" И каждый раз, когда мы натыкаемся на какое-то непонятное правило, непонятный код, непонятные условия, мы должны всегда задавать себе вопрос. +2349.00 2353.00 "Анатолий Кулаков" А может ли домен владеть этим кодом? +2353.00 2355.00 "Анатолий Кулаков" Может ли домен владеть этой логикой? +2355.00 2359.00 "Анатолий Кулаков" И если мы говорим "да", то мы, не сомневаясь, переносим эту логику в домен. +2359.00 2373.00 "Анатолий Кулаков" То есть если у вас встречается какая-то сложная стратегия, и вы можете перенести это в домен, то надо перемещать это в домен. То есть мы максимально стараемся логики переместить в домен. Именно там ей место, возле доменной логики, как ни странно. +2373.00 2375.00 "Анатолий Кулаков" Начнем мы, пожалуй, с самого главного. +2375.00 2379.00 "Анатолий Кулаков" Это создание самого объекта, создание самого ордера. +2379.00 2381.00 "Анатолий Кулаков" И валидация его входных параметров. +2381.00 2385.00 "Анатолий Кулаков" Прежде всего необходимо сделать, чтобы агрегат мог сам себя построить. +2385.00 2389.00 "Анатолий Кулаков" И не просто построить, а построить с необходимыми ему вариантами. +2389.00 2403.00 "Анатолий Кулаков" Для этого обычно делается статический метод create, которому передаются все необходимые для построения аргументы. Таким образом мы получаем единственную точку входа, который может воспользоваться аппликейшн или другие сервисы. +2403.00 2409.00 "Анатолий Кулаков" И эта точка входа нам быстро дает понять, хорошо ли она прошла, то есть успешно ли создан ордер или нет. +2409.00 2415.00 "Анатолий Кулаков" Или мы можем в ней упасть. И в принципе это тоже хорошо, потому что упадем мы в ней довольно быстро. +2415.00 2421.00 "Анатолий Кулаков" Всю валидацию, все агрегаты, все инварианты мы должны запихнуть внутрь ордера. +2421.00 2425.00 "Анатолий Кулаков" И таким образом мы улучшим тестируемость. +2425.00 2427.00 "Анатолий Кулаков" Давайте посмотрим, как это можно было бы сделать. +2427.00 2451.00 "Анатолий Кулаков" Прежде всего нам нужно в класс ордер добавить статический метод create, как я уже говорил. В качестве параметра предлагается передать ему довольно громоздкую конструкцию. Например, кастомера, который создает этот ордер, элементы, которые необходимо в ордер добавить, а также сюда засовывается pricing_service для определения цен и inventory_service для того, чтобы определять остатки на складе. +2451.00 2455.00 "Анатолий Кулаков" В общем, в доменную сущность передаются сервисы. +2455.00 2473.00 "Анатолий Кулаков" Далее, что мы делаем? Мы прежде всего создаем саму структуру ордера, в конструктор ей передаем обязательные параметры. Мы точно знаем, что ордер в принципе пустым-то может быть без единого элемента, но вот без кастомеров ордеры точно не существуют. Поэтому мы делаем обязательный приватный конструктор, который требует кастомера. +2473.00 2487.00 "Анатолий Кулаков" Таким образом, мы гарантируем. Некий вариант у нас уже появляется. Мы гарантируем, что у ордера всегда есть кастомер, потому что он передается в конструктор, не как раньше присваивался в публичное поле, и кто-то ему присвоит, а кто-то нет. В общем, теперь у нас ордеры красавцы, они всегда с конструкторами. +2487.00 2493.00 "Анатолий Кулаков" Дальше мы пробегаемся по всем элементам и начинаем элемент перед добавлением проверять. Проверяем, что он есть на складе. +2493.00 2495.00 "Анатолий Кулаков" Если на складе его нет, выбрасываем exception. +2495.00 2521.00 "Анатолий Кулаков" Ежели на складе он есть, рассчитываем его цену и добавляем уже непосредственно к ордеру. И мы добавляем к ордеру не как раньше мы добавляли у ордера была какая-то лист публичный. К этому публичному листу все, кто угодно, могли добавлять любые элементы, какие угодно. Могли не только добавлять, могли, кстати, и удалять, что еще хуже. Вот здесь же у нас у ордера появляется метод, который называется addItem. +2521.00 2545.00 "Анатолий Кулаков" И только этот метод может добавлять к нашему уже приватному листу, где содержатся все элементы. То есть мы теперь скрыли вот эту функцию публичного доступа к нашим элементам произвольно, кому угодно. У нас есть публичный метод addItem. Пожалуйста, добавлять мы можем, при том со строго определенной сигнатурой, с обязательными параметрами, с обязательными флажочками, которые еще внутри себя могут чего-то еще проверить. +2545.00 2553.00 "Анатолий Кулаков" И дальше же в этом методе создания ордера мы вызываем метод проверки кредитного лимита для данного кастомера. +2553.00 2555.00 "Анатолий Кулаков" В принципе, и все. Довольно чистенький, понятный метод. +2555.00 2565.00 "Анатолий Кулаков" Создание, заполнение, проверка лимита и возвращение из этого метода статического экземпляра созданного ордера. Для того, чтобы Service Application мог с ним что-нибудь там поделать. +2565.00 2569.00 "Анатолий Кулаков" Мог что-то рассказать дальше по пайтлайну пробросить. +2569.00 2579.00 "Анатолий Кулаков" Так, что же мы получили в конце-то концов? Получили мы понятную единую точку входа, которая падает, если вдруг что-то пошло не так. +2579.00 2597.00 "Анатолий Кулаков" То есть, если раньше вы могли записать какие-то непонятные значения туда, допустим, какое-нибудь отрицательное количество товара записать в ордер, и это вполне бы записалось, потому что этих проверок могло вполне не быть, и когда-нибудь потом бы вы упали, то здесь уже такое не прокатит. +2597.00 2601.00 "Анатолий Кулаков" Здесь ордер сам отвечает за все свои инварианты. +2601.00 2605.00 "Анатолий Кулаков" И при добавлении нового элемента нужно обязательно проверить какое-нибудь количество. +2605.00 2615.00 "Анатолий Кулаков" То есть, мы получили метод, который в случае невалидных данных у вас очень быстро свалится и не пустит приложение работать дальше с невалидным ордером. +2615.00 2623.00 "Анатолий Кулаков" Один из самых главных концепций домена Dreaming Design это в том, что ваша богатая сущность, она всегда должна быть валидной. +2623.00 2631.00 "Анатолий Кулаков" То есть, если она создалась, то внутри нее все инварианты находятся под валидным состоянием. +2631.00 2635.00 "Анатолий Кулаков" Невозможно создать невалидный объект. Он должен падать при создании. +2635.00 2639.00 "Анатолий Кулаков" И здесь мы это уже как раз и собрали. +2639.00 2649.00 "Анатолий Кулаков" Теперь приложение не занимается больше микроменеджментом, то есть, оно не смотрит на всякие скидки, наличие на складе и так далее. Это мы отдали все непосредственно ордеру. +2649.00 2659.00 "Анатолий Кулаков" И самое главное, что мы получили, это мы перешли из процедурного языка в объектно-ориентированный, потому что мы воспользовались инкапсуляцией. +2659.00 2671.00 "Анатолий Кулаков" У нас теперь внутри ордера зашита вся та логика, которая необходима для его создания. То есть, он теперь сам знает, что такое валидный ордер, он теперь сам себя умеет создавать, и мы получили прекрасный пример инкапсуляции. И это прекрасно. +2671.00 2679.00 "Анатолий Кулаков" Значит, мы уже постепенно превращаемся из каких-нибудь PHP-шников в нормальных C# разработчиков, которые пишут на объектно-ориентированном языке программирования. +2679.00 2689.00 "Анатолий Кулаков" Но здесь, конечно, есть самый, наверное, спорный момент во всей статье. Это инжектирование сервисов внутридоменного метода. +2689.00 2695.00 "Анатолий Кулаков" Как я уже сказал, метод Create в данном примере принимает PricingService и InventoryService. +2695.00 2701.00 "Анатолий Кулаков" То есть, по сути, сервисы, которые обычно в повседневном коде никогда в домен не проникают. +2701.00 2709.00 "Анатолий Кулаков" Автор оправдывает это тем, что это было осознанное решение, и зачем это было сделано. +2709.00 2729.00 "Анатолий Кулаков" Он говорит, что это помогает держать логику, непосредственно бизнес-логику, там, где она должна быть, рядом с бизнес-данными. Потому что каким образом общаться с этими сервисами остатков на складе или ценами, в принципе, никто, кроме домена, знать не может. +2729.00 2739.00 "Анатолий Кулаков" Потому что именно домен владеет данными, и о том, как с этими ценами обращаться, ну и, соответственно, логика обращения с этими ценами должна быть тоже в нем. +2739.00 2749.00 "Анатолий Кулаков" Чтобы все вокруг могли оркестрировать только те, то поведение, которое касается, которое относится к ним. +2749.00 2763.00 "Анатолий Кулаков" А вот ордер должен сам понимать, как общаться со своими ценами, как общаться со своими остатками. Именно поэтому и ордеру отдаются все эти интерфейсы, и именно для ордера они проваливаются внутрь. +2763.00 2775.00 "Анатолий Кулаков" Здесь решается типичная трилема DDD, когда мы понимаем, что необходимо пожертвовать или перформансом, или читабельностью для того, чтобы это все могло работать. +2775.00 2783.00 "Анатолий Кулаков" Ну вот автор решил, что он нарушит немножко такие договоренности, когда домены ничего не знают ни про какие сервисы. +2783.00 2799.00 "Анатолий Кулаков" И при этом здесь нужно признать, что логика в этом какая-то есть. То есть, когда у нас сущность является автономной, то есть вот этот подход он делает сущность автономной. Когда она является автономной, прежде всего у нас появляется очень хороший способ ее тестировать. +2799.00 2809.00 "Анатолий Кулаков" У нее есть понятный список зависимостей, этот список зависимостей довольно чистый, ну то есть она принимает только или домены сущности, или интерфейсы, которые легко мокаются. +2809.00 2813.00 "Анатолий Кулаков" И поэтому тесты на это, на все написать довольно легко и просто. +2813.00 2827.00 "Анатолий Кулаков" Поэтому тестабельность здесь выросла в разы. В общем, код довольно непривычен, но если разбираться, то плюсов у него, наверное, все-таки больше, чем минусов, поэтому имеет право на жизнь. Погнали дальше. +2827.00 2869.00 "Анатолий Кулаков" Итак, теперь мы должны спрятать внутреннее состояние. Я уже много раз упомянул некие инварианты, которые у нас есть в каждой сущности. Инварианты - это некие гарантии, которые сущность транслирует наружу. Например, она говорит, что у меня есть заказы, и эти заказы, допустим, можно только добавлять. Удалять их невозможно, ну потому что мы это пока не заимплементировали, в общем, и удалять их невозможно. Но те заказы, которые есть, они обязательно все валидные. Мы помним, что все сущности, если они созданы, то значит они будут валидными. Раньше этот инвариант невозможно было соблюсти, потому что раньше наш ордер был просто какой-то публичной структурой, в которую мог добавлять, удалять и изменять заказы, все кто угодно, товары в заказе, все кто угодно. +2869.00 2875.00 "Анатолий Кулаков" Сейчас же мы инкапсулируем в себя эти инварианты, это значит, что мы должны список всех заказов скрыть. +2875.00 2877.00 "Анатолий Кулаков" Это должна быть приватная переменная. +2877.00 2891.00 "Анатолий Кулаков" Мы внутри, естественно, можем ее менять, как захотим, но вот снаружи никто до нее доступаться не должен. Поэтому теперь это приватная переменная и мы можем выставить метод, который называется addItem. +2891.00 2903.00 "Анатолий Кулаков" Этот метод должен, опять же, принимать все необходимые параметры для того, чтобы добавить item и не просто его принимать и добавлять, а проводить все необходимые проверки и трансформации. +2903.00 2911.00 "Анатолий Кулаков" Например, мы можем проверить здесь уже, что количество товара, которое мы пытаемся добавить, больше нуля. +2911.00 2913.00 "Анатолий Кулаков" Если это не так, выбрасываем исключение. +2913.00 2923.00 "Анатолий Кулаков" Также мы можем проверить, что если кастомер у нас вдруг является VIP-клиентом, то мы ему небольшую скидочку можем набросить. Все вот эти проверочки мы можем здесь сделать. +2923.00 2935.00 "Анатолий Кулаков" И все остальные там проверки, например, проверить, что у кастомера достаточно лимита на счете и так далее, мы тоже можем сюда инкапсулировать внутри ордера. Все это внутри него может быть. +2935.00 2941.00 "Анатолий Кулаков" Но все это можно сделать отдельными методами, которые понятные, читабельные, красивые, даже тестируемые. +2941.00 2947.00 "Анатолий Кулаков" И мы здесь снова столкнемся с одним из самых гениальнышим изобретением ООП, которое называется инкапсуляция. +2947.00 2959.00 "Анатолий Кулаков" То есть мы скрыли вот это вот поле со всеми заказами внутрь, теперь его никто снаружи не может изменять, и это один из примеров прекрасной инкапсуляции, когда мы полностью контролируем то, что происходит внутри нашего класса. +2959.00 2963.00 "Анатолий Кулаков" И таким образом наш класс невозможно привести в невалидное состояние. +2963.00 2967.00 "Анатолий Кулаков" Он всегда будет под контролем, всегда будет валидный. +2967.00 2987.00 "Анатолий Кулаков" И вот тест, который мы получили, это self-protection, то есть как раз когда домен полностью отвечает за свою консистентность, вместо того, чтобы какие-то сервисы раньше могли изменять произвольные его поля на любые произвольные другие значения. В общем, сейчас такого делать абсолютно невозможно, менять можно только через публичные методы, поэтому он сам себя защищает. +2987.00 3003.00 "Анатолий Кулаков" И мы наконец-то воспользовались истинным ООП, потому что теперь у нас данные располагаются там же, где и поведение над этими данными, то есть поведение рядышком с данными, что и, собственно, декларирует собой объектно-ориентированное программирование. +3003.00 3007.00 "Анатолий Кулаков" А не просто какое-то программирование на структурах и функциях, которое у нас было раньше. +3007.00 3019.00 "Анатолий Кулаков" И мы опять же продолжаем упрощать application application service теперь сфокусирован именно на координации, вместо того, чтобы знать про какие-то бизнес-правила. +3019.00 3041.00 "Анатолий Кулаков" Что же это значит такое, что он сконцентрирован на координации и в нем нет никаких правил? Все очень просто. Если мы после вот этих наших парочек рефакторингов посмотрим, а что же у нас, собственно, осталось в нашем order-сервисе в методе placeOrder, то осталось у него довольно-таки мало. Во-первых, он должен загрузить кастомера из базы данных, потому что база данных все-таки в домен у нас никогда не протекает. +3041.00 3053.00 "Анатолий Кулаков" Он должен загрузить кастомера, проверить, что он есть, а также он должен смапить в некие входящие DTOшки с товарами уже во что-то более приличное, более приемлемое. +3053.00 3065.00 "Анатолий Кулаков" Он должен вызвать наш order через статический метод create, передавив все необходимые параметры, в том числе price-сервис и inventory-сервис, который он у себя получал через Dependency Injection. +3065.00 3077.00 "Анатолий Кулаков" И сохранить order в базу данных, по сути, новый созданный order. На самом деле это все, то есть загрузка из базы данных, сохранение в базу данных и какой-то базовый маппинг. +3077.00 3091.00 "Анатолий Кулаков" Вот все, что у нас осталось на плечах Application Layer того же сервиса. То есть, по сути, только оркестрация. Никаких скидок, никаких цен, никаких остатков, ни кастомеров, ни випов. +3091.00 3101.00 "Анатолий Кулаков" Ничего этого здесь нет. Вся логика у нас отлично спрятана в доменной модели, которая полностью ее управляет и полностью ее контролирует. +3101.00 3105.00 "Анатолий Кулаков" Что же у нас было перед тем, как мы приступили к нашему гениальному рефакторингу? +3105.00 3131.00 "Анатолий Кулаков" Было то, что у нас сервис знал про очень много всего. Например, про цены, про остатки, про кредиты, про лимиты и так далее. Также у нас была возможность писать только очень сложные тесты, где бы мы мокали базу данных, Entity Framework и прочие такие большие сложномокательные сущности. +3131.00 3137.00 "Анатолий Кулаков" И у нас было очень сложное добавление новых правил. +3137.00 3153.00 "Анатолий Кулаков" Если бы мы захотели к ордеру добавить какое-то новое поведение, новые правила, новые параметры, то нам бы пришлось перелопатить абсолютно все сервисы, которые есть в нашем приложении. А таких сервисов может быть много и код у них дублируется, и иногда дублируется не так, как нам хочется. В общем, с этим связаны куча проблем. +3153.00 3155.00 "Анатолий Кулаков" После нашего рефакторинга все стало намного проще. +3155.00 3171.00 "Анатолий Кулаков" Агрегат владеет всеми бизнес-правилами, то есть внутри него собраны все возможные поведения, методы, данные, которые вам нужны, которые вам могли бы понадобиться. То есть вам больше не нужно бегать по всему вашему приложению и искать все возможные ваши сервисы. +3171.00 3177.00 "Анатолий Кулаков" Вы заходите в ордер, и там все, что вам нужно, обязательно уже есть. +3177.00 3179.00 "Анатолий Кулаков" В сервисах остается только оркестрация. +3179.00 3199.00 "Анатолий Кулаков" Поэтому в них очень малая вероятность, что там будет какое-то важное дублирование, очень малая вероятность, что нужно что-то будет вам переделать или перенести. Вообще, они получаются довольно тупыми. Поэтому все тестирование, вся логика, все изменения будут именно в доменных моделях. +3199.00 3203.00 "Анатолий Кулаков" И у нас, соответственно, получаются довольно чистые доменные модели. +3203.00 3221.00 "Анатолий Кулаков" Потому что все необходимые зависимости мы принимаем через публичные методы. Когда нам даже необходимы были вот эти интерфейсы с прайсинг-сервисом, мы их явно принимали через публичный метод. Таким образом, никакой зависимости от базы данных у нас нет. +3221.00 3237.00 "Анатолий Кулаков" А раз нет зависимости от базы данных, значит на них очень легко будут писаться тесты. И, соответственно, доменные модели можно легко и красиво протестировать. Так как у них все параметры явные, все моки явные, то тесты тоже должны быть довольно простыми и читабельными. +3237.00 3243.00 "Анатолий Кулаков" И большинство изменений получилось изолировано внутри этого агрегата. +3243.00 3253.00 "Анатолий Кулаков" В этих тестах нам уже не нужно писать, тестировать абсолютно все поля, все их поведение, что будет, если мы удалим товары вдруг из нашего ордера. +3253.00 3255.00 "Анатолий Кулаков" Вот этой всей глупости делать не нужно. +3255.00 3265.00 "Анатолий Кулаков" Потому что ордер декларирует определенные методы. Вот он сказал, что меня можно создавать и в меня можно добавлять какие-то элементы. Все. Больше у него никаких внешних методов не торчит. +3265.00 3267.00 "Анатолий Кулаков" Ничего другого с ним сделать нельзя. +3267.00 3271.00 "Анатолий Кулаков" Кастомера нельзя удалить, товар нельзя удалить, изменить количество тоже нельзя. +3271.00 3279.00 "Анатолий Кулаков" Поэтому тесты нам необходимо писать не на абсолютно все, что только придет в голову, а только на тот публичный контракт, который он явно декларирует. +3279.00 3289.00 "Анатолий Кулаков" То есть вот это и изоляция всей логики внутри, инкапсуляция необходимых данных и публичный контракт тоже очень сильно упрощают читабельность и очень сильно упрощают жизнь. +3289.00 3295.00 "Анатолий Кулаков" Мы четко понимаем, что он умеет, четко понимаем, как это тестировать и как с ним общаться. +3295.00 3303.00 "Анатолий Кулаков" Итак, в результате того, что мы перенесли логику ближе к нашим данным, мы уменьшили, например, область изменений. +3303.00 3309.00 "Анатолий Кулаков" То есть если вы захотите добавить новую функциональность, мы уже знаем, куда пойти и четко ее там добавить. +3309.00 3317.00 "Анатолий Кулаков" Мы сделали бизнес-правила более явными, положив их в явное место и не размазывая по разным сервисам, и сделали наш класс более тестируемым. +3317.00 3333.00 "Анатолий Кулаков" А также вот всем вот этим рефакторингом мы открыли для себя большой дивный мир различных пест-практисов и тактических шаблонов, таких как валидация, события, варианты и множество-множество других. +3333.00 3339.00 "Анатолий Кулаков" То есть там уже можно довольно хорошо развернуться и сделать довольно сложную логику, опять же, если она вам нужна. +3339.00 3369.00 "Анатолий Кулаков" Но при этом нужно не забывать, что никаких больших рефакторингов при этом делать не нужно. Все наши действия были довольно атомарными, довольно понятными, поэтому вы должны взять какой-то один концепт, стартовать с него, отрефакторить и потом взять следующий какой-то концепт. И так потихонечку, потихонечку можно подобные штуки переделывать и, не торопясь, преобразовать всякий анимичный сервис, анимичные модели в богатые доменные модели и как раз в сервис оркестраторы. +3369.00 3381.00 "Анатолий Кулаков" Благодаря подобным действиям даже какой-нибудь старый, уже неподдерживаемый страшный кот вполне можно оживить и придать ему бодрости и хорошую поддерживаемость, самое главное, и тестируемость. +3381.00 3391.00 "Анатолий Кулаков" В общем и, может быть, ваши Legacy-проекты уже будут выглядеть не как страшные неподдерживаемые монстры, а новые красивые, DDD-образные, хипстерские хорошенькие, богатые сервисы. +3391.00 3393.00 "Игорь Лабутин" Ну да, неплохие рекомендации. +3393.00 3397.00 "Игорь Лабутин" Я как-то применял подобное в паре проектов. +3397.00 3399.00 "Игорь Лабутин" Вполне хорошо работало. +3399.00 3403.00 "Игорь Лабутин" Действительно помогает, главное, вовремя остановиться с этими семьями. +3403.00 3409.00 "Анатолий Кулаков" Да, главное не пытаться вычесывать всего по стандартным канонам уже, когда это не имеет особого смысла. +3409.00 3411.00 "Игорь Лабутин" Да. Давай пойдем дальше. +3411.00 3453.00 "Игорь Лабутин" Я когда-то обещал, что я постараюсь вчитаться в всякий Escape Analysis, что происходит в дотнете, я попробовал это сделать, почитал просто статью, которая тут недавно вышла, про DotNet 9 Escape Analysis, а также прочитал runtime-доку на эту тему, и получилось примерно следующее, то, о чем я сейчас вам расскажу. Ну, во-первых, надо понимать, что в стандартном дотнете-интервью вопрос про то, что value-типы, они живут либо на стеке, либо на куче, если они забоксились, а reference-типы живут только на куче, все, теперь это неправда, теперь и те, и другие могут жить и на стеке, и на куче, и надо очень аккуратно подходить к вопросу, когда и где, и что это может жить. +3453.00 3459.00 "Игорь Лабутин" А еще, на самом деле, они могут жить во всяких специальных кучах, типа в какой-нибудь Frozen HIPAA и так далее, но это уже вообще отдельная тема. +3459.00 3469.00 "Игорь Лабутин" Причем это как бы такое ограничение раньше, оно было в самом CLR, то есть это не какая-то особенность C#, а именно это прям особенность нашего рантайма. +3469.00 3497.00 "Игорь Лабутин" При этом куча, она более дорогая, понятное дело, она больше, несомненно, но при этом по ней должен гулять горбач коллектор, доступ к куче в отличие от стека потенциально более дорогой, в том плане, что это вроде и там, и там память, но с хорошей вероятностью стека у вас будет где-то совсем рядышком, это тоже память, но она будет скорее всего рядышком в каких-нибудь кышах процессора, или еще что-нибудь в таком духе, а куча, ну мало ли где там лежит ваш объект, далеко. +3497.00 3525.00 "Игорь Лабутин" Вот, поэтому все рантаймы, вероятно, пытаются сделать так, чтобы если вам объект нужен все-таки как объект, но он нужен на очень короткое время и гарантированно не уйдет куда-то далеко и надолго, то желательно бы его попробовать лоцировать прямо на стеке, то есть это будет все еще объект, но он будет лежать на стеке. Там есть дальнейшая, понятно, оптимизация, когда объект раздербанивается на отдельные поля, но это про другое немножко. +3525.00 3551.00 "Игорь Лабутин" Для того, чтобы решить, что объект можно положить на стек, а не в кучу, нужно сделать следующее. Нужно всего лишь убедиться, что ссылка на такой объект не покинет пределы функции, потому что как только она покинет пределы функции, если, точнее, она покинет пределы функции и лежит при этом на стеке, то выйдя из этой функции стек фрейм почистится и уже будет указывать эта ссылка на какой-то мусор в стеке, куда там будут какие-то следующие функции что-то писать. +3551.00 3557.00 "Игорь Лабутин" Так делать нельзя, потому что у нас безопасная среда, поэтому этот escape analysis как раз-таки очень важен. +3557.00 3571.00 "Игорь Лабутин" Насколько далеко мы можем отпустить ту или иную переменную, насколько она уходит и насколько она потенциально где-то модифицируется, причем надо понимать, что уходит это не обязательно значит возвращается из этой функции. +3571.00 3597.00 "Игорь Лабутин" Это может означать, что вы на этой переменной вызвали какой-то метод, то есть на переменной класса вызвали метод, а внутри этого метода this был сохранен в какое-нибудь статическое поле или какой-нибудь там написали на него ивент с захватом контекста в общем много чего может произойти, из-за чего переменная у вас на самом деле уйдет куда-то наружу. То есть это не так просто, как кажется. +3597.00 3617.00 "Игорь Лабутин" Поэтому все это надо делать, причем делать это надо в runtime, напомнить, что это делает jit, а не собственно c# компилятор, а jit, штука, которая должна работать довольно быстро, шустро, и поэтому у нас есть еще проблема performance, как это все делать быстро, поэтому слишком сложно логику тоже туда не вписать. +3617.00 3683.00 "Игорь Лабутин" Понятное дело, что когда это все было давным-давно, речи об этом не было вообще, потому что jit у нас был один, он должен был работать просто быстро, и любая задержка в jit приводила к тому, что у вас код фактически компилировался медленнее, и следовательно исполнялся более медленно в самом начале работы приложения. Сейчас, когда у нас есть tiered jit, соответственно с этим попроще, первую версию можно сделать попроще, а дальше спокойненько в бэкграунде оптимизировать, но тоже не хотелось бы тратить, понятное дело, ресурсы CPU на то, что там где-то в бэкграунде секундами компилировать какой-то код. Майкрософт довольно консервативно в этом смысле подходит к вопросу, не стал делать там все сразу с наскоку, поэтому в девятом дотнете у нас появились только value типы, которые забокшенные, и только такие типы смогли складываться на стэк, потом только добавились массивы таких типов, ну и вот сейчас то, что я последнее рассказывал, это немножко вокруг асинковых стэть-машин начинают с этим делом работать, но пока еще там тоже далеко. +3683.00 3703.00 "Игорь Лабутин" Надо понимать, что боксинг у нас все равно происходит, то есть это не то, что мы как бы просто кладем переменную на стэк и все, значения нет, у нас все равно есть боксинг, все равно создается объект, вот это все как положено, но просто он лежит на стэке, чтобы рантайм все еще работал как надо с учетом блокировок и прочего, например. +3703.00 3707.00 "Игорь Лабутин" Блокироваться на таких объектах все еще можно, насколько я понимаю. +3707.00 3723.00 "Игорь Лабутин" При этом, хотя казалось бы, мы смотрим всего лишь на какой-то очень простой сценарий, да, вот у нас есть value тип, который потенциально боксится, надо убедиться, что он не покидает объект, который забоксился, не покидает скоп функции. +3723.00 3735.00 "Игорь Лабутин" На самом деле JIT настолько замороченный, в смысле, что он очень сложный, что даже казалось бы, довольно простые изменения функций сильно влияют на то, как JIT может что-то оптимизировать. +3735.00 3749.00 "Игорь Лабутин" Например, если мы возьмем метод, который делает простую штуку, он говорит, давайте мы будем принимать какой-нибудь iIntNumber, вызывать на этом number getInt и возвращать результат. +3749.00 3751.00 "Игорь Лабутин" Ну, в принципе, понятная штука. +3751.00 3829.00 "Игорь Лабутин" И в целом, если мы говорим, что берем какую-нибудь структуру, боксим и передавая в такую функцию, поскольку там принимается iIntNumber, то эта структура, очевидно, забоксится, должна забокситься, чтобы быть переданной, потому что JIT же не знает, что там внутри делается. А дальше начинается интересно. Если вы, например, в вашей функции заведете такую переменную и вызовете функцию getNumberFromStruct два раза подряд, просто напишите одну и ту же строчку два раза подряд, то все нормально. JIT понимает, что он что-то забоксил, но это что-то, оно передается в функцию, которая безопасна в каком-то смысле, она ничего не делает, она только никуда не сохраняет ничего, возвращает только результат, все хорошо, два раза подряд вызвали, ничего страшного, никто никуда не убег, можно спокойно лоцировать на стэке, но если вы то же самое, те же два раза вызовете, но только в виде for цикла, то есть for от 0 до 2, не включая 2, понятно, да, и вызов этот getNumberFromStruct, тот же самый переменный, то все, это уже не подвластно JIT, это уже лоцирует на heap, вместо того, чтобы лоцировать на стэке. Чуть ниже расскажу, почему. Там есть интересные моменты. +3829.00 3835.00 "Игорь Лабутин" Так, в чем, собственно, вообще проблема? +3835.00 3861.00 "Игорь Лабутин" И теперь мы переходим уже к дизайн-доку, тому, как там написано. Я вообще в целом рекомендую всем, кто хочет побольше узнать про escape analysis, и про то, какие трудности возникают с ним для того, чтобы быстренько и легко это все написать в JIT, почитайте, там довольно последовательная история, я не смогу ее рассказать всю, там некоторые детали очень уж специфичные, требуют внимательного вглядывания в код, но общие идеи я расскажу. +3863.00 3865.00 "Игорь Лабутин" В чем, по сути, с чем борются? +3865.00 3873.00 "Игорь Лабутин" Какой у нас основной кейс, пожалуй, наверное, самый популярный, который как раз-таки этот самый escape analysis призван решить? +3873.00 3875.00 "Игорь Лабутин" Это, конечно же, итерирование. +3875.00 3907.00 "Игорь Лабутин" Если мы берем какую-нибудь коллекцию, куда-то ее передали, по каким-нибудь вашим код-конвеншенам вам нужно обязательно в принимающих аргументах объявлять максимально абстрактный тип, то есть это будет, скорее всего, IEnumerable тогда, а передаете вы какой-нибудь массив или лист, и понятно, что если вы делаете просто forage по листу или по массиву, то там внутри будут структурные итераторы и с ними все будет хорошо, но если вы передаете IEnumerable, то компилятор технически не знает, что там вообще-то лист или массив, и может там иногда лист, иногда массив, и ему надо что-то делать с этим. +3907.00 3919.00 "Игорь Лабутин" А если бы можно было понять в рантайме уже в момент jita, что эта переменная никуда не убегает, то неважно, что там аллоцируется, мы аллоцируем на стеке и никакого overheadа не будет. +3919.00 3953.00 "Игорь Лабутин" Более того, мы же не только аллоцируем сам энумератор, энумератор мы аллоцировали, это хорошо, но у энумератора есть еще методы moveNext, плюс энумераторы некоторые реализуют IDisposeable, это значит, там будет tryFinally и вызов метода dispose, и все вот эти вызовы в результате требуют некоторого количества overhead, и все они, в общем-то, производятся через интерфейсы, и поэтому требуют оптимизации, потому что иначе это все дорого и печально. +3953.00 3955.00 "Игорь Лабутин" Вот. +3955.00 3977.00 "Игорь Лабутин" Казалось бы здесь, раз я говорю, что вызовы через интерфейсы, у нас же есть ProfileGuidedOptimization, которая может много чего порешать, если она понимает, что у нас 90% времени происходит вызов метода через интерфейс для одного и того же типа, то это дело через специальную конструкцию, которая сравнивает тип объекта. +3977.00 3995.00 "Игорь Лабутин" Будет происходить более оптимально, будет происходить напрямую уже у статически известного типа, ну, статически в момент джета, понятное дело, но все равно это не сильно помогает, то есть это помогает улучшить скорость работы, но не идеально. +3995.00 4031.00 "Игорь Лабутин" И, по сути, в статье рассматривается следующее, там есть несколько вариаций кода, но самая простая вариация кода - это такая, у нас есть функция, которая возвращает какой-то массив, результат от этой функции мы присваиваем в IEnumerableAtInt, объявляем некоторую переменную сумму и дальше в цикле пробегаемся по всем элементам этого IEnumerable под названием o, ну то есть object, и суммируем все результаты, поскольку это IEnumerableAtInt, там можно написать sum+=i и возвращаем сумму. +4031.00 4045.00 "Игорь Лабутин" Казалось бы, все нормально, o у нас никуда не девается из функции, это просто итератор IEnumerable, в смысле, который доступен только внутри forEach, больше за пределами forEach он никак не используется, казалось бы, оптимизировать не хочу. +4045.00 4053.00 "Игорь Лабутин" Начнем с того, что когда это все доходит до jita, код выглядит не как эти простые четыре строчки, а все-таки гораздо более сложно. +4053.00 4087.00 "Игорь Лабутин" То есть, во-первых, мы действительно объявляем некоторую переменную, куда присваиваем результат функции getArray, объявляем локальную переменную sum, потом объявляем локальную переменную IEnumerator, потом мы, предполагая, что enumerator может требовать dispose, начинаем блок try, внутри мы делаем цикл while moveNext, делаем getCurrent в переменную локальную, потом присваиваем, в смысле, увеличиваем сумму на эту локальную переменную, потом finally вызываем dispose на итера, на enumerator, и потом возвращаем сумму. +4087.00 4091.00 "Игорь Лабутин" Довольно развесистый, там уже try, finally появилось, в общем, циклы какие-то. +4091.00 4093.00 "Игорь Лабутин" Ну, цикл был for it, но он в while превратился. +4093.00 4099.00 "Игорь Лабутин" Тот самый, который, на самом деле, оптимально делал do while. +4099.00 4109.00 "Игорь Лабутин" И все это в итоге выливается в четыре вызова интерфейсов и в try, finally, ну и цикл. +4109.00 4111.00 "Игорь Лабутин" Что происходит в итоге? +4111.00 4121.00 "Игорь Лабутин" jit первым делом в tier0 либо в нулевом тире он делает некую инструментацию. +4121.00 4131.00 "Игорь Лабутин" На каждом месте, где мы вызываем интерфейс, вызов делаем через интерфейс, добавляется некоторая проверка и собирается статистика. +4131.00 4139.00 "Игорь Лабутин" И, естественно, мы видим в нашем примере, что объект, который возвращается из массива, это, собственно, всегда массив. +4139.00 4141.00 "Игорь Лабутин" Из функции, которая возвращает массив, это, естественно, массив. +4141.00 4157.00 "Игорь Лабутин" А итератор, энумератор, который создается, он всегда типа setSZGenericArrayEnumerator от int, а это специальный внутренний энумератор, который, соответственно, для массивов возвращается. +4157.00 4189.00 "Игорь Лабутин" И, естественно, во всех местах после получения некоторой статистики jit добавляет следующую конструкцию. Допустим, вместо получения просто aEnumeratorE присвоить o.getEnumerator, он добавляет, что type = typeOfInt массивIntOf, то тогда мы в переменную присваиваем o скастованную к массиву intOf, и уже у этой переменной получаем энумератор. И тогда это не виртуальный вызов, это вызов вполне конкретный, он вернет структуру, и вот это все. +4189.00 4199.00 "Игорь Лабутин" И понятно, что такие штуки могут быть девиртуализированы, и даже заинлайнены, и jit будет более понятно, что вообще происходит в методе. +4199.00 4211.00 "Игорь Лабутин" Но в девятом дотнете, и вообще в более ранних дотнетах проблема состоит в том, что девиртуализация не так легко работает конкретно для массивов. +4211.00 4227.00 "Игорь Лабутин" И поэтому для получения вот этого первого вызова, то есть получения энумератора, на самом деле не работает девиртуализация для массивов, потому что массивы реализованы довольно специальным образом в дотнете. +4227.00 4235.00 "Игорь Лабутин" И поэтому первый вызов все равно анноцирует энумератор, если ничего специального не делать. +4235.00 4243.00 "Игорь Лабутин" И тут начинается описание в статье ряда челленджей, и всего их там по-моему порядка десятка перечисленных, я только по некоторым пробегусь. +4243.00 4249.00 "Игорь Лабутин" Первая штука - это, собственно, девиртуализация вызова через массивы. +4249.00 4271.00 "Игорь Лабутин" Надо заметить, что, как я говорил, в том коде, который джит видит в первый раз, когда он капеллирует метод, у нас есть 4-5 вызовов виртуальных методов. И мы по всем делаем профиляцию PGO, все дела, собираем какую-то статистику, но надо понимать, что вообще-то все эти вызовы скоррелированы. +4271.00 4291.00 "Игорь Лабутин" Если энумератор вернул, что у нас тип массива, в смысле типа возвращаемого коллекции - это int, то по статистике очевидно, в смысле по логике, очевидно, что вызов энумератора всегда вернется за array_enumerator, как он там называется, не может быть там ничего другого. +4291.00 4293.00 "Игорь Лабутин" Они скоррелированы. +4293.00 4297.00 "Игорь Лабутин" Эту информацию неплохо было бы как-то знать. +4297.00 4323.00 "Игорь Лабутин" В принципе, эту информацию джит мог бы получить из так называемого type propagation, то есть когда он понимает, что тут вернулся массив int, то тогда можно это дело пропагейтить дальше, но проблема в том, что анализис, он происходит с точки зрения фаз джита чуть-чуть раньше, чем заканчивается полный type propagation, поэтому не все так хорошо и легко доступно, именно поэтому пришлось добавить специальный атрибут. +4323.00 4325.00 "Игорь Лабутин" Называется он intrinsic. +4325.00 4331.00 "Игорь Лабутин" Если смотреть в код рантайма, там будет виден атрибут intrinsic, который говорит джиту буквально следующее. +4331.00 4347.00 "Игорь Лабутин" Если ты видишь виртуальный вызов через интерфейс на чем-то, что помечено атрибутом intrinsic, спроси, пожалуйста, у рантайма какой тип вернется тут в ответе. +4347.00 4359.00 "Игорь Лабутин" И таким образом, например, помечен гетто-нумератор на массивах и рантайм знает, что если вызывается гетто-нумератор на массиве, то там вернется generic array-нумератор, то есть и он джиту про это скажет. +4359.00 4369.00 "Игорь Лабутин" Это тем самым помогает джиту без вот этого type propagation понять вообще в каких местах что будет вызвано, и все-таки виртуализировать. +4369.00 4387.00 "Игорь Лабутин" Вторая проблема, которая специфична именно для массивов, состоит в том, что у массива массив настолько специальный тип, что реализация интерфейсов для массивов находится вообще в другом классе. +4387.00 4407.00 "Игорь Лабутин" То есть у нас есть специальный класс, называется czArrayHelper, и именно он реализует интерфейсы для массивов, всякие там гетто-нумератор, вот это все, и компилятор специально знает, что на самом деле, когда вызывается гетто-нумератор для массива, нужно вызывать компонент класса, а не какой-нибудь array. +4407.00 4419.00 "Игорь Лабутин" Поэтому за счет этого промежуточного класса получается, что для gta вроде как есть еще один вызов метода, через который нужно пробраться внутрь и понять, что же там внутри возвращается. +4419.00 4435.00 "Игорь Лабутин" Поэтому на этом czArrayHelper везде, почти на всех методах, стоит прессив инлайнинг, чтобы как раз таки JIT не видел этого хелперного класса, а видел непосредственно вызовы уже нормальных гетто-нумераторов, которые там внутри все нормально сделаны. +4435.00 4451.00 "Игорь Лабутин" Вот, это уже помогает, это помогает JIT понять, что же там будет возвращаться за иннумератор, но все еще не помогает дальнейшему промоушену, всяких там разбирания структур кинополя и так далее, это все следующие проблемы и конструкции. +4451.00 4455.00 "Игорь Лабутин" Внезапно возникает проблема с пустыми массивами. +4455.00 4525.00 "Игорь Лабутин" Почему? Потому что, как мы знаем, есть такой паттерн у нас, не надо каждый раз, когда мы хотим вернуть пустой массив, не надо возвращать newArray от нуля, нужно вернуть какой-нибудь array от int.empty, это специальное статическое поле, все хорошо, все замечательно, и этот статический объект прекрасно возвращает специальный, правильный immutable статический итератор, но тут возникает вопрос. С одной стороны, JIT хочется что-то там не аллоцировать, с другой стороны, мы тут имеем статический глобальный объект, и вот Escape Analysis прямо явно говорит, блин, ну если он статический, глобальный, тут явно с ним не надо его, так сказать, хранить в стэке, и нужно аллоцировать иннумератор нормально, другое дело, что он immutable, никогда не меняется, всегда возвращает ничего, и вот эту информацию, чтобы донести до JIT, там нужно прям довольно сильно постараться. Можно посчитать, кстати, как это сделано, то есть там есть правильные fallback'и на то, что в нужных местах все-таки надо аллоцировать, это на самом деле не страшно, потому что фактически там ничего аллоцироваться не будет. +4525.00 4541.00 "Игорь Лабутин" Дальше есть еще челленджи, связанные с trifinal, потому что trifinal тоже требует некоторых специальной обработки, дополнительного кода, и сильно усложняет эту самую обработку эскейпов. А дальше собственно сам эскейп анализис. +4541.00 4543.00 "Игорь Лабутин" Что же делается во время эскейп анализа? +4543.00 4553.00 "Игорь Лабутин" Надо же нам как-то понять, что вообще-то переменная так или иначе, точнее объект, который аллоцировали внутри функции, так или иначе ее не покидает. +4553.00 4677.00 "Игорь Лабутин" Тут используется довольно простой я бы сказал алгоритм практически в лоб, то есть каждая переменная, каждая аллокация внутри функции, даже если вы ее записываете в одну и ту же переменную, например, вы там, не знаю, три раза подряд пишите new и все их присваиваете в одну и ту же переменную, фактически внутри джета каждая аллокация записывается в некоторую свою виртуальную переменную, и если эта переменная точно где-то используется снаружи, то есть она записывается в какое-нибудь там статическое поле, еще куда-нибудь, на ней вызывается неизвестный метод, например, про который джет ничего не знает, и он не может сказать, запомнит, ну, будет ли захвачена эта переменная где-то внутри в какой-то внешний контекст, или не может, тогда это все считается все, что переменная эскейпит из этой функции, мы такую, этот объект мы не сможем зааллоцировать на стэке, и если вы копируете ссылку из одной переменной на другой, да, то есть присваиваете просто ссылку туда-сюда, то, соответственно, у вас строится некоторый граф связей, кто куда в кого скопировался, ну, и в конце просто делается транзитивное замыкание всего графа, и мы понимаем, что ну, соответственно, и по всем переменам, которые уже известны, что они эскейпятся из функции, дальше, согласно связям в графе, представляется по всем другим переменам, то есть все другие перемены тоже помечаются, что они эскейпятся, и только те, которые остались, что они не эскейпятся, ну, тогда их можно попытаться сложить на стэк. Но дальше возникает интересный другой вопрос. Напоминаю, что у нас в этом всем еще срабатывает профайл гайдед оптимизейшн, и что у нас, то, что вы в коде пишете что-то там, там, getToNumerator, да, то на самом деле после профайл гайдед там будет if что-то, то там a.prisvoid getToNumerator, else a.prisvoid a.getToNumerator. +4677.00 4695.00 "Игорь Лабутин" Фактически код один и тот же, просто в случае if тип a будет статически известен, а в случае else не будет известен. И это тоже надо рассмотреть с точки зрения эскейп-анализа. Мы же не знаем, как на самом деле пойдет исполнение функции, и вроде по статистике там 99% всегда было одно, а в 1% будет другое. +4695.00 4711.00 "Игорь Лабутин" Там для этого заводятся некоторые специальные виртуальные, так скажем, переменные, и дальше точно так же строится граф связей, только там чуть более сложно мапиться if-условия на else-условия, чтобы еще учесть те самые корреляции между разными if-ами. +4711.00 4721.00 "Игорь Лабутин" И если, опять же, хоть по какой-то ветке видно, что переменная может уйти наружу, то все, как бы, никакого стэка вам не видно. +4721.00 4723.00 "Игорь Лабутин" Это все было про массивы в основном. +4723.00 4761.00 "Игорь Лабутин" Дальше там рассматривается в статье несколько других типов, в частности listT, с которым все гораздо интереснее, потому что, во-первых, там энумератор делает не просто получить следующее значение из массива, а, во-первых, напомню, что list и другие коллекции проверяют некоторые внутренние свойства, называется version, из-за которого вам возникает collectionModifiedException, то есть вы не можете модифицировать коллекцию во время итерирования по ней. Это добавляет радости G2, потому что надо понимать еще и это условие учитывать во всяких этих при построении графа. +4761.00 4785.00 "Игорь Лабутин" А второе, что для G2 не так очевидно, что энумератор — это просто обращение к какому-то полю, потому что энумератор для листа он же не хранит ссылку на сам массив, он хранит ссылку на list, поэтому фактически для G2 это 3D-референс. Надо сначала из энумератора взять list, потом из него взять внутренний массив, потом из него взять элемент и только тогда вот этот вот элемент уже проверять на то, что там, куда, как. +4785.00 4787.00 "Игорь Лабутин" Escape, не escape и так далее. +4787.00 4791.00 "Игорь Лабутин" Можно ли его положить, например, на stack или еще что-то сделать. +4791.00 4803.00 "Игорь Лабутин" Поэтому в общем G2 гораздо сложнее, именно поэтому с листами пока тоже не все идеально и пока в основном делается все для массивов. +4803.00 4805.00 "Игорь Лабутин" Дальше. +4805.00 4811.00 "Игорь Лабутин" Все, что я рассказывал, в основном это касается локаций именно самого энумератора. +4811.00 4833.00 "Игорь Лабутин" Эта штука, конечно, довольно сильно улучшает ситуацию и, как я сказал в начале, скорее всего, это одна из самых, наверное, важных частей, где мы получим, наверное, максимальный профит от stack allocation, но у нас есть циклы. И в циклах, вот то, что я говорил раньше, если вы вызовете просто один и тот же метод 2 раза подряд, он нормально оптимизируется. +4833.00 4845.00 "Игорь Лабутин" Если вы вызовете его 2 раза из цикла подряд, несмотря на то, что вы никак не связываете итерации цикла между собой, они абсолютно независимы, сразу ничего не работает. Почему? +4845.00 4887.00 "Игорь Лабутин" Потому что вообще алгоритм сейчас основывается на идее, что для stack allocation мы заводим некоторое фиксированное число слотов, потому что если бы мы в цикле, допустим, лоцировали переменные n раз, складывали бы это все в какой-то временный массив в этой функции, в конце все, допустим, складывали результаты и выходили из функции, казалось бы, никто никуда не уходит из функции, все можно заалоцировать на стэке, но мы не знаем заранее количество итераций, особенно если оно тоже приходит каким-нибудь аргументом снаружи, и это значит, что стэк потенциально может расти, ну, если не бесконечно, то довольно далеко, и это не очень здорово. +4887.00 4967.00 "Игорь Лабутин" Поэтому скорее всего, как пишут в статье, будет первым рассматриваться вариант оптимизации, когда JIT будет доказывать сам себе, что то, что алоцировано внутри итерации цикла, не используется за пределами итерации цикла, и тогда можно переиспользовать одни и те же слоты в стэке для того, чтобы алоцировать переменные, в смысле, объекты между итерациями цикла, переиспользовать, в смысле. Как это будет работать с точки зрения какой-нибудь дебага и так далее, когда в дебаге, как я напоминаю, отключаются в основном всякие оптимизации, а в дебаге скорее всего в хипе просто будет и все. Да, тут я что-то тормозил, но в целом идеи с циклами, вот циклы пока самое главное, что портит такое ощущение, что всю эту историю с эскейп анализом, так что будем смотреть. А второй момент это несколько номерейшенов, то есть если у вас есть вложенные, например, for_each, то один из них будет обработан таким вот способом с точки зрения локации, а поскольку другой находится внутри в цикле, несмотря на то, что уж этот точно друг от друга не зависит, и итераторы для каждого внешней итерации будут внутри локироваться разные, и никак между собой не пересекающиеся, все равно два вложенных for_each уже не смогут быть оптимизированы таким вот эскейп анализом. +4967.00 5011.00 "Игорь Лабутин" Так что работы еще впереди много, проблем довольно сложных много, сделать это так, чтобы это работало стабильно и при этом приносило хороший benefit будет, конечно, прекрасно, но что-то я не уверен, что какие-то большие еще оптимизации мы увидим в десятке, потому что на LTS, на stable вряд ли там какие-то последние моменты будут выкатывать, разве что каким-нибудь экспериментальным флагом закроют, вот это может быть. А так то, что называется ждем с нетерпением, когда все это будет локироваться на стэке, объекты будут почти бесплатные, ну это все, ну и изменения собеседования, понятное дело, потому что объекты теперь могут быть не только в куче. +5011.00 5019.00 "Анатолий Кулаков" Ух, круто, отличные перипетии, практически интриги, расследования, перспективы, много интересных вопросов встает. +5019.00 5021.00 "Анатолий Кулаков" На будущее, как они будут это делать? +5021.00 5023.00 "Анатолий Кулаков" Замечательная темка. +5023.00 5043.00 "Игорь Лабутин" Ну, особенно учитывая, что делают это, я так понимаю, полтора человека, если не полчеловека, я не знаю, насколько большая команда там сидит, но кажется, что не очень много народу этим занимается сейчас, потому что, например, половину из, ну ладно, может быть не половину, но часть из таких оптимизаций, у меня такое ощущение, что чуть ли не комьюнити принесло со стороны. +5043.00 5053.00 "Игорь Лабутин" Ну, может быть именно в качестве идей, где-то я встречал обсуждение именно что комьюнити, но понятно, что это настолько корная часть, что тут основная команда должна скорее работать. +5053.00 5061.00 "Анатолий Кулаков" Ну да, наверное, комьюнити туда не пустят, так как идеи, наверное, да, это хорошо. Ну и кажется, что это должно хороший такой перформанс дать. +5061.00 5065.00 "Анатолий Кулаков" Почему этим занимается так мало полчеловека? Потому что там +5065.00 5075.00 "Игорь Лабутин" вся команда, я подозреваю, ну хорошо, два с половиной, не знаю, три. Сколько сейчас идут на этих человек, я не знаю, сколько занимаются основным ронтаймом. Кажется, что не очень много. +5075.00 5077.00 "Анатолий Кулаков" Да-да, наверное, так. +5077.00 5091.00 "Анатолий Кулаков" Ну ладно, тогда пожелаем этой половинке человека как бы больше усидчивости и нервов для того, чтобы довести дела до конца, потому что действительно там проблемы как бы на каждом шагу возникают. +5091.00 5097.00 "Игорь Лабутин" Ну, хорошо, давай посмотрим еще в одну такую полуархитектурную, мне кажется, тему. +5097.00 5115.00 "Анатолий Кулаков" Ну да, такую более верхнеуровневую, как раз для расслабончика нам с тобой напоследок хорошо должно зайти. А поговорим мы про наиболее частые ошибки, которые допускаются при проектировании публичного API. В частности, автор предложил собрать их в топ-5 именно для него. +5115.00 5125.00 "Анатолий Кулаков" А в общем, собраны они без какого-то определенного критерия, может быть, есть и лучше, может быть, есть и хуже, но ошибки довольно показательные, интересные, поэтому давайте вместе их обсудим. +5125.00 5145.00 "Анатолий Кулаков" Первая ошибка, которая допускает множество разработчиков по наблюдениям автора статьи заключается в том, что разработчики допускают слишком слабую валидацию на входе тех данных, которые к ним приходят. Они доверяют клиентам, которые присылают им данные и считают, что клиенты всегда присылают только валидные данные. +5145.00 5203.00 "Анатолий Кулаков" И это огромное-огромное заблуждение. Если вы вдруг не проверяете те данные, которые присылают вам ваши веб-клиенты, не важно, кто это, это могут быть C# клиенты, написанные вами, это могут быть какие-то клиенты из других языков, которые вам присылают, кто-то курлом заделался или ваш фронтендер через JavaScript шлет какие-то данные. Абсолютно все равно. Все внешние клиенты для нас, как для Backend-разработчиков, являются внешними. Так вот, если вы недостаточно хорошо проверяете этот ввод, который к вам присылается, то поздравляю, вы открыли огромный портал для уязвимостей, для багов, для того, чтобы ваше приложение зарушилось и вообще получило множество security рисков. Потому что это наиболее частый, наиболее распространенный вход для абсолютно всех багов, в том числе и security багов, security утечек, которые только существуют. +5203.00 5225.00 "Анатолий Кулаков" Ну, типичным примером является то, что если вдруг к вам прилетает какой-нибудь user.dto, ваш контроллер, то вы, не глядя абсолютно, делаете в базе данных запись, в эту запись сохраняете и name из этой DTO-шки, email из этой DTO-шки и все это пуляете в ваш Entity Framework и просите его сохранить. +5225.00 5255.00 "Анатолий Кулаков" И в результате возвращаете, что у вас все окей, все хорошо. Вот это самое глупое поведение, которое может быть. Что же вы могли бы сделать? Ну, во-первых, вы бы могли проверить на пустоту или нулябельность обязательных полей, например, такие как username или email. Вы могли бы проверить формат email, потому что к вам пришла строка, а внутри этой строки может запихнуто быть абсолютно все что угодно. Ну, хотя бы там каким-нибудь банальным regex-пиком email можно было бы смачить. +5255.00 5273.00 "Анатолий Кулаков" Вы могли бы проверить всякие бизнес-правила, потому что имя, например, которое не может быть несколько мегабайт по размеру, то есть каким-нибудь длину хотя бы ограничить стандартных полей. Там имен, может быть того же самого email, может быть еще чего-то возраста, который не может быть отрицательным. То есть стандартные бизнес-правила. +5273.00 5289.00 "Анатолий Кулаков" И это очень важный вообще момент, как раз не доверять внешним системам, а все перепроверять по 10 раз. Даже если вы точно уверены, что фронтендер, который все это вам прислал, ваш хороший знакомый никогда плохого ничего не присылал. +5289.00 5303.00 "Анатолий Кулаков" Потому что если вы вдруг пропустите этот шаг в вашем приложении, то вы скорее всего нарветесь на то, что у вас в базе данных будут валяться плохие данные, которые рано или поздно все равно выстрелят. +5303.00 5307.00 "Анатолий Кулаков" То есть дадут вам какую-нибудь ошибку, какую-нибудь наведенку, еще что-нибудь. +5307.00 5319.00 "Анатолий Кулаков" Также данный подход, когда вы не проверяете входные данные, он плох тем, что клиент всегда... То есть клиент невозможно диагностировать какие-то проблемы. +5319.00 5331.00 "Анатолий Кулаков" Например, он туда послал вам пустой юзернейм, этот юзернейм может в базу как сохраниться, так и не сохраниться, если вдруг у базы есть constraint, что простых юзернеймов она не допускает. +5331.00 5347.00 "Анатолий Кулаков" И вот эта диагностика для того клиента, который вам эти данные прислал, она будет довольно сложная. Потому что по сути, то, какое исключение там вылетит из этой базы данных, то, как оно сконвертится и то, как оно представится клиенту, абсолютно непредсказуемо и может меняться там от версии к версии. +5347.00 5351.00 "Анатолий Кулаков" В общем, поэтому усложняется дебаггинг. +5351.00 5363.00 "Анатолий Кулаков" Ну и если вы начнете все-таки проверять, вы убережете свой backend от всяких странных ошибок, которые я уже говорил, которые там отложены, когда вы сохраняете плохие данные, а потом эти плохие данные при... +5363.00 5375.00 "Анатолий Кулаков" при всяких операциях, при вычислении отчетов над ними, начинают срабатывать и бросать тоже непонятные исключения. Притом не в твоем месте, где они были записаны. +5375.00 5407.00 "Анатолий Кулаков" Другая, вторая ошибка, которая к нам приводит автор, как наиболее часто, это неверсионирование вашего API. То есть вы релизите ваш API и при этом не предусматриваете какую-то схему версионирования, какой-то способ, стратегию версионирования. И в реальности вы обычно хотите, чтобы ваш API менялся, и почему-то вы хотите, чтобы он менялся несовместимо со старой версией, и при этом, если вы так сделаете, то все ваши старые клиенты пострадают, они все умрут. +5407.00 5427.00 "Анатолий Кулаков" И у вас, если у вас нет никакого плана версионирования, то и вы при этом измените все ваши реквесты или респонсы несовместимо, то ваши клиенты поумирают. В общем, мне кажется, что версионирование это такой довольно... +5427.00 5429.00 "Анатолий Кулаков" довольно аргумент... +5429.00 5445.00 "Анатолий Кулаков" довольно такая тема, которая как-то слишком замусорена. То есть она не стоит вообще абсолютно того, сколько на нее тратят времени. Например, тот же самый пример, который приводит автор. Он говорит, что давайте представим парочку методов. +5445.00 5469.00 "Анатолий Кулаков" Как сделать плохо. Плохо сделать очень просто. Вы делаете контроллер, у которого обозначаете ресурс Products и возвращаете какие-то продукты. Как сделать хорошо? Тоже довольно просто. Делаете контроллер, у которого вы пишете V1 Products, возвращаете продукты и пишете контроллер, который называется V2 Products, возвращаете продукты и все. Этим способом вы как бы решили всю вашу проблему. +5469.00 5483.00 "Анатолий Кулаков" То есть вы подумали о стратегии версионирования и вы теперь можете деплоить ваши приложения даже с breaking changes. Если вы, соответственно, будете старый контракт оставлять старым, а breaking changes вносить в новый контракт. +5483.00 5487.00 "Анатолий Кулаков" И все ваши старые клиенты будут работать хорошо и надежно. +5487.00 5501.00 "Анатолий Кулаков" Ну, казалось бы, все правильно, все хорошо, другое дело. А давайте рассмотрим вот плохой вариант, который он предложил. Это когда мы просто делаем контроллер и делаем ресурс Products, на который возвращает какие-то продукты. +5501.00 5503.00 "Анатолий Кулаков" И пойдем по порядку. +5503.00 5509.00 "Анатолий Кулаков" Самая первая ошибка, которая здесь ментально есть, это в том, что автор говорит, если вы вдруг захотите сломать контракт. +5509.00 5521.00 "Анатолий Кулаков" По-хорошему вы не должны хотеть ломать контракт. То есть весь REST API проектировался таким образом, что никаких breaking changes в нем быть не должно. +5521.00 5533.00 "Анатолий Кулаков" И тот же самый Roy Fielding, который автор REST, он никаких версионирований не признает. Он говорит, что никакой версии в REST быть не должно. Вы должны поддерживать совместимость. +5533.00 5543.00 "Анатолий Кулаков" И вы должны расширять контракт, но не ломать его. И я на практике тоже больше с автором, с Roy придерживаюсь, потому что тут какой-то бред. +5543.00 5545.00 "Анатолий Кулаков" Дальше. +5545.00 5551.00 "Анатолий Кулаков" Вдруг почему-то вы все-таки захотели сломать контракт. Ну, представим, у вас там есть клиенты, которые там сто лет не используются. +5551.00 5569.00 "Анатолий Кулаков" И этот метод поддерживать очень трудно, очень сложно. Для него нужны какие-то страшные костыли, чтобы поддерживать. И вдруг вы хотите, например, сделать новый URL. И этот новый URL должен принимать новый реквест или возвращать какой-то респонс несовместимый со старым. +5569.00 5573.00 "Анатолий Кулаков" То так ли плохо вариант, который вы сделали? +5573.00 5575.00 "Анатолий Кулаков" То есть /products. +5575.00 5577.00 "Анатолий Кулаков" И в принципе нет. +5577.00 5581.00 "Анатолий Кулаков" Вы также точно можете рядом с этим /products добавить /v2products. +5581.00 5591.00 "Анатолий Кулаков" И продолжить с чистой душой работать дальше, при этом не имея в изначальном голове той самой стратегии версионирования, на которую повал автор. +5591.00 5593.00 "Анатолий Кулаков" То есть ничего страшного в принципе не произойдет. +5593.00 5597.00 "Анатолий Кулаков" Вот эту циферку v2products никто вам не мешает добавить и потом, и в конце. +5597.00 5621.00 "Анатолий Кулаков" А с учетом того, что если вы придерживаетесь правила, что в принципе breaking changes – это довольно редкая ситуация, и большинство сервисов не такие большие, не такие старые, не такие громоздкие, а они довольно-таки молодые, и API в них все-таки не так уж и много, то придерживаясь всех этих правил, скорее всего до v2products вы не дорастете никогда. +5621.00 5651.00 "Анатолий Кулаков" В 99% случаях никогда v2 у вас не появится. А у вас никогда не появится v2, какой смысл вымазывать ваши ресурсы вот этим дурацким v1, который будет практически всегда во всех урлах просто светиться и никакой пользы семантической нести не будет. В общем, поэтому вся эта чушь, как бы, с v2, v1, мне кажется, абсолютно перегрета и не нужна, если вы там пишете какой-нибудь огромный страшный сервис, у которого breaking changes случаются каждый месяц, и вам нужно поддерживать 100 миллионов клиентов, да, там, наверное, можно загнаться. +5651.00 5663.00 "Анатолий Кулаков" Если же мы говорим про какой-нибудь нормальный мобильный микросервис, то все эти v1, v2 - это те загоны, которые яйца выеденного не стоят, и при необходимости легко добавляются. +5663.00 5679.00 "Анатолий Кулаков" Поэтому сильно большие такие проблемы разработчиков я бы это не занес, а просто сказал бы, чтобы разработчики должны понимать, какие выходы у них есть из этой ситуации, и как их использовать, и все. Никаких особых проблем с этим нет. Ну, давайте пойдем дальше. +5679.00 5683.00 "Анатолий Кулаков" Все-таки у нас целых 5 проблем, которые допускают разработчики. +5683.00 5697.00 "Анатолий Кулаков" И третья проблема у нас - это неправильный статус-код. Потому что автор часто сталкивался с API, который возвращает все время 200 OK, и не важно, что у них произошло. +5697.00 5705.00 "Анатолий Кулаков" Случилась ли у них какая-то ошибка, нашли ли они какую-то сущность, или вдруг они словили какой-то exception, но их всегда 200 OK. +5705.00 5717.00 "Анатолий Кулаков" Отдельно стоит отметить прекрасный код, который возвращает 200 OK и в боди пишет error true, или error message и сообщает о каком-то месседже, который там произошел, но код у него все равно 200 OK. +5717.00 5721.00 "Анатолий Кулаков" В общем, тоже такие индивидуумы есть. +5721.00 5731.00 "Анатолий Кулаков" И плохо это как раз тем, что коды возврата, они были придуманы как раз для того, чтобы машины, вот эти автоматизированные клиенты, они с друг другом общались, и с сервером в том числе. +5731.00 5737.00 "Анатолий Кулаков" То есть это коды, которые помогают клиенту каким-то образом понять, что собственно происходит. +5739.00 5749.00 "Анатолий Кулаков" Потому что если клиент видит 200, то он не пойдет дальше каким-то образом обрабатывать ошибки, или показывать пользователю какие-то проблемы, или что-то делать. Он думает, что все хорошо. +5749.00 5755.00 "Анатолий Кулаков" Несмотря на то, что там внутри мог быть не найден пользователь, или случилось какое-то исключение, или еще что-то. +5755.00 5759.00 "Анатолий Кулаков" Что же нужно делать? А нужно использовать ошибки. +5759.00 5761.00 "Анатолий Кулаков" Использовать HTTP-эрроры. +5761.00 5769.00 "Анатолий Кулаков" Самые частные, которые есть, которые советуются, тот минимум набор, который советуется использовать, это 400 bad request. +5769.00 5777.00 "Анатолий Кулаков" Это в случае, если вдруг вам прислали какие-то невалидные данные. То есть в случае, если по ним пришла валидация, это прекрасный статус для того, чтобы сообщить клиенту об этом. +5777.00 5783.00 "Анатолий Кулаков" 401 unauthorized. Это если вы не залогинены, пользователь не залогинен в системе. +5783.00 5791.00 "Анатолий Кулаков" 403 forbidden. Это если вы залогинены в систему, но у вас не хватает каких-то прав, ролей, или еще чего-то для того, чтобы сделать эту операцию, или доступиться к ресурсам. +5791.00 5793.00 "Анатолий Кулаков" 404 not found. +5793.00 5795.00 "Анатолий Кулаков" Это если ресурс не найден. +5795.00 5811.00 "Анатолий Кулаков" 100 internal server error. Это если вдруг произошло какое-то непредвиденное исключение на серверной стороне. Об этом тоже лучше клиенту сообщить, чтобы он не долбился, не думал, что он сам как-то плохо написан, чтобы он понимал, что проблемы все находятся именно на стороне сервера. +5811.00 5833.00 "Анатолий Кулаков" И это очень важно, потому что таким образом клиенты могут понимать, что, собственно, происходит с их ответом, и каким-то образом попытаться исправить ситуацию. Например, можно сделать retry, можно сделать redirect, можно пользователю показать ошибку и попросить его исправить те данные, которые он ввел. То есть, каким-то образом продолжить интерактивное взаимодействие, каким-то образом принять какое-то решение. +5833.00 5835.00 "Анатолий Кулаков" Вот почему эти ошибки довольно важны. +5835.00 5853.00 "Анатолий Кулаков" Здесь можно добавить, что иногда разработчики вращаются в другую крайность. Вместо вот этих 5-6 ошибок стандартных, которые, в принципе, хватает на все случаи жизни, они начинают использовать абсолютно все коды, которые HTTP стандарт придумал. А их там просто сотни как бы. +5853.00 5861.00 "Анатолий Кулаков" И начинают выдумывать или выкапывать из спецификации такие глупости, которые потом ни один клиент не сможет нормально переварить. +5861.00 5877.00 "Анатолий Кулаков" Поэтому всегда, когда вы пытаетесь добавить какой-то странный код возврата, помните, что вы их добавляете не ради того, чтобы показать знания спецификации или какой-то новый код, который вы там недавно прочитали, а ради того, чтобы клиент каким-то образом мог их воспринять и обработать. +5877.00 5893.00 "Анатолий Кулаков" Поэтому, если вы вашему клиенту вернете какой-нибудь код "Я чайник" и клиент не будет знать, а что с этим чайником делать, то ничего хорошего вы не сделаете. Вы всего лишь на все запутаете ваших потребителей. Поэтому есть какие-то стандартные вещи, стандартных 5-6 кодов. +5893.00 5901.00 "Анатолий Кулаков" Их знают все. Клиенты их умеют обрабатывать, умеют показывать пользователям, умеют ретравиться. Вот ими и пользуйтесь, не выпендривайтесь. +5901.00 5907.00 "Анатолий Кулаков" Четвертая проблема, с которой столкнулся автор, это возврат слишком большой модели, полной модели. +5907.00 5921.00 "Анатолий Кулаков" То есть он говорит, что очень часто бывают такие ситуации, когда вы загружаете из базы данных какую-то сущность, у этой сущности сотня полей, и просто-напросто из контроллера ее возвращаете. +5921.00 5943.00 "Анатолий Кулаков" Довольно странная, редкая ситуация. Я такое встречал довольно редко, но, может быть, да, потому что может быть мало такого кода смотрел, где человеку придет в голову возвращать сущность, только что загруженную из базы данных, прямо из контроллера наружу. Ну, допустим, такие люди есть. +5943.00 5945.00 "Анатолий Кулаков" Что же у нас получается? +5945.00 5961.00 "Анатолий Кулаков" Обычно в реальности клиенту не нужны ваши огромные сущности. Ему нужны какая-то маленькая доля информации, относительно того, что у вас хранится маленькая, безусловно. Не надо возвращать ему целый снапшот из базы данных только потому, что вы можете. +5961.00 5967.00 "Анатолий Кулаков" С этим случается множество неприятных проблем. +5967.00 5975.00 "Анатолий Кулаков" Ну, например, самое первое, что бросается в глаза, это то, что вы полностью раскрываете структуру вашей базы данных. +5975.00 5991.00 "Анатолий Кулаков" То есть неизвестно, какие у этого объекта дополнительные какие-нибудь навигейшн-поля. Может быть, там какой-то пароль хранится в открытом виде, может какая-то security хэш-сумма важная, сертификат торчит какой-то, и вы раз и отдаете это все наружу. Это нехорошо. +5991.00 6007.00 "Анатолий Кулаков" Это показывает внутреннюю структуру базы данных, на которую завязывается клиент, и вы ее уже потом никогда не сможете изменить. Это влечет к тому, что вы можете раскрыть какие-нибудь чувствительные данные или персональные данные и повлечь какие-нибудь security проблемы. +6007.00 6021.00 "Анатолий Кулаков" И также, если вы возвращаете огромные объекты, в случае, если вы вернете весь объект из базы данных, он будет, скорее всего, огромным, это замедляет API, потому что больше нужно серилизовать, больше нужно передавать, и больше каким-то образом нужно разрабатывать. Что же делать? +6021.00 6025.00 "Анатолий Кулаков" Ну, очень просто. Нужно перемапливать большие объекты в какие-то понятные DTO-шки. +6025.00 6041.00 "Анатолий Кулаков" То есть определить, какой минимальный набор необходимых полей нужен клиенту, и обеспечить ему этот минимальный набор. Помните, что как бы DTO-шки всегда можно расширять. Расширение - это не breaking changes, поэтому, если к вам придет завтра и скажете добавить новое поле, вы всегда его добавите. +6041.00 6055.00 "Анатолий Кулаков" А вот урезать нельзя. Урезать - это уже breaking changes. Поэтому, если вы вылили всю модель из тысячи полей, а потом вы хотите оставить из них только 100, то здесь у вас уже будут проблемы. Вы этого сделать не можете, иначе вы нарушите публичный контракт. +6055.00 6077.00 "Анатолий Кулаков" И это довольно важная штука, потому что, опять же, вы должны контролировать вашу базу данных и те структуры, которые хранятся в вашей базе данных собственноручно. То есть вы не должны декларировать эту схему вовне, потому что вы не сможете поменять тогда базу данных, вы не сможете отрефакторить таблицы, вы не сможете переехать в какие-то новые типы данных. +6077.00 6083.00 "Анатолий Кулаков" Вот это нужно разделять. То есть то, что хранится в базе данных, то, что декларирует ваш публичный контракт, это должны быть всегда разные сущности. +6083.00 6087.00 "Анатолий Кулаков" Чем меньше ответы, тем быстрее они будут работать. +6087.00 6095.00 "Анатолий Кулаков" А чем быстрее они будут работать, тем счастливее будут ваши пользователи, а также будет лучше работать все оптимизация, поэтому будут также счастливы ваши монагеры. +6095.00 6107.00 "Анатолий Кулаков" Ну и, естественно, вы уменьшаете security risk, потому что не нарываетесь на случайное опубликование каких-то секретных полей, которые в вашей базе данных вполне могли бы храниться. +6107.00 6115.00 "Анатолий Кулаков" И последняя ошибка, которую приводит автор, это отсутствие центральной точки для обработки исключений. +6115.00 6129.00 "Анатолий Кулаков" Он часто встречал такую ситуацию, когда все методы внутри контроллера оборачиваются в try/catch блоки, а иногда забывают оборачиваться в try/catch блоки, и при этом вылетает необработанное исключение куда-то там далеко, и непонятно, что с ним будет дальше. +6129.00 6131.00 "Анатолий Кулаков" И это плохо. +6131.00 6143.00 "Анатолий Кулаков" Потому что все-таки нужно какое-то единственное место, которое контролирует все исключения, которые вылетают для того, чтобы обработать их как-то предсказуемо, стандартно и одновременно. +6143.00 6155.00 "Анатолий Кулаков" Представим себе код, где у вас есть контроллер, у него есть try/block, там вы пытаетесь что-то сделать с пользователем, как-то его поискать, и если все хорошо и вы не забыли, то поставили catch и там вернули результат с проблемой, допустим. +6155.00 6157.00 "Анатолий Кулаков" Что здесь плохого? +6157.00 6161.00 "Анатолий Кулаков" Ну, плохо то, что вам такой try/catch блок приходится ставить в каждом методе контроллера. +6161.00 6171.00 "Анатолий Кулаков" Также плохо то, что вы можете забыть поставить такой try/catch блок. Плохо то, что внутри catch вы можете каким-то разным образом вернуть результат. +6171.00 6177.00 "Анатолий Кулаков" Кто-то вернет problem details, кто-то bad request, кто-то еще что-то, какой-то другой тип ошибки. +6177.00 6183.00 "Анатолий Кулаков" Также плохо то, что у вас теряется какая-то понятная точка, единая точка для логирования и диагностики. +6183.00 6193.00 "Анатолий Кулаков" Для того, допустим, чтобы вашу какую-нибудь доску мониторинга послать эту ошибку и быстренько посмотреть, о чем, собственно, были проблемы. +6193.00 6197.00 "Анатолий Кулаков" Гораздо лучше, если вы будете использовать стандартные методы. +6197.00 6205.00 "Анатолий Кулаков" И для решения подобных ситуаций в последних ASP.NET'ах уже прикручено по дефолту problem details. +6205.00 6233.00 "Анатолий Кулаков" То есть problem details были всегда, но они не были в дефолтном middleware. Сейчас они по дефолту прикручены, то есть все исключения, которые вылетают, обрабатываются специальным problem details middleware. И их можно расширять, кастомизировать, как угодно, но в любом случае вы уже не попадете в какой-то просаг, потому что problem details - это кроссплатформенный RFC стандарт, который поддерживается, ну, по крайней мере, декларируется между разными языками и поддерживается очень многими инструментами. +6233.00 6235.00 "Анатолий Кулаков" В общем, и это прекрасно. +6235.00 6241.00 "Анатолий Кулаков" Если у вас не какой-то, не последний какой-то ASP, то problem details несложно прикрутить и к нему. +6241.00 6265.00 "Анатолий Кулаков" Единственное, что вам нужно, там нужно, наверное, скорее всего, будет написать какой-нибудь exception handler, exception filter для того, чтобы все-таки в одном месте это все обработать. И хорошо это потому, что ваш код становится чище, вы уже не обмазываете ваши контроллеры какими-то странными трекетчами, вы избавляетесь от тублирования кода, вы избавляетесь от различной обработки, все ваши обработки exception'ов становятся единообразными. +6265.00 6287.00 "Анатолий Кулаков" Также, если вы используете стандартный контракт типа problem details, то вы можете рассчитывать, что клиенты на других языках вас поймут, то есть тот контракт, который вы вернули, они вас поймут, там уже будет не просто какой-то call stack, там уже будет понятный JSON со строго задекларированными полями, в общем, там уже будет какая-то понятная схема, ее можно обработать. +6287.00 6307.00 "Анатолий Кулаков" И вы получаете единую точку, куда вы можете подключить там Serilog, OpenTelemetry, в общем, диагностику, отладку, в общем, все это тоже у вас в приложении как-то в одном месте будет красивенько настроено и уже легче вам будет отлаживать и смотреть, диагностировать все проблемы, которые у вас случаются. +6307.00 6323.00 "Анатолий Кулаков" Вот таких вот пять больших ошибок, с которыми сталкивался автор, наверное, многие из вас встречали их в своем коде или в коде коллег, и, может быть, теперь будут относиться к ним построже и будут знать, как их исправлять. +6323.00 6331.00 "Игорь Лабутин" Да, хорошие советы, полезные, хоть, наверное, и базовые, но на самом деле встречается код, который им не следует, и его тоже приходится рефакторить. +6331.00 6337.00 "Игорь Лабутин" Опять же, главное, вовремя остановиться, но этим советам точно хорошо бы следовать. +6337.00 6343.00 "Игорь Лабутин" Ну что, у нас на сегодня еще, наверное, есть чуть-чуть кратенько о разном. +6343.00 6345.00 "Анатолий Кулаков" Давай быстренько пробежимся. +6345.00 6347.00 "Анатолий Кулаков" Сейчас я вам парочку ссылок еще подброшу. +6347.00 6355.00 "Анатолий Кулаков" А, даже не я, наши слушатели присылают нам активно ссылки, поэтому вы тоже присылайте, если вдруг у вас есть какие-нибудь статьи, инструменты и чего-нибудь еще в этом духе. +6355.00 6361.00 "Анатолий Кулаков" Павел Воронов нам прислал прекрасный инструмент, который называется ReGix. +6361.00 6381.00 "Анатолий Кулаков" Это специальная библиотека, которая позволяет вам использовать регулярные выражения, даже не использовать, а строить шаблон для регулярных выражений во Fluent Syntax, потому что, наверное, многих смущает вот этот синтаксис регулярных выражений, который с непонятными заковырочками, скобочками, крючочками, и многим хотелось бы, наверное, во Fluent Syntax это все распределить. +6381.00 6391.00 "Анатолий Кулаков" В общем, библиотека это позволяет вам сделать прям хорошими английскими словами, вы описываете, где у вас должна стартовать проверка, что внутри нее, какие буковки и циферки должны быть, где должно закончиться. +6391.00 6409.00 "Анатолий Кулаков" И таким образом вы можете там через цепочку таких комбинаторов довольно сложные выражения строить. Посмотрите на примерчики, выглядит довольно интересно, хотя, скорее всего, через такой интерфейс у вас упадет аут, ну то есть аут это не поддержит, но, наверное, небольшая проблема. +6409.00 6423.00 "Анатолий Кулаков" Следующая ссылочка, которую я нашел, это статья на Хабре, которая называется "Functional Splitting и чистый код". Ребята из Contouran написали интересный пример, как красивость кода увеличивает производительность программы. +6423.00 6465.00 "Анатолий Кулаков" В общем, такое на уровне фана и реальности, потому что на практике, наверное, сложно вам применить такой подход, который улучшит вам перформанс, но в статье получился довольно классный пример, то есть у вас есть такая простыня из кода, который от рефакторов вынеси в разбивные методы, в общем, сделать таким чистеньким, красивым, с методами, с параметрами, и при этом код начинает работать быстрее, без изменения какой-то функциональности. И все это тоже объясняется, почему, как, как там все это оптимизируется, инлайнится, распределяется в памяти, с ассембленными вставками, бенчмарками, в общем, все как вы любите. Посмотрите, статья довольно забавная и интересная. +6465.00 6501.00 "Анатолий Кулаков" И также я хотел пользуясь случаем напомнить, что у нас проводятся оффлайн-митапы в Санкт-Петербурге и не только, и сейчас еще в Крыму, и на этих оффлайн-митапах мы записываем все лекции, которые читают авторы, и выкладываем их на наш YouTube-канал полностью открыто для каждого, поэтому, возможно, если вам не хватает просто слухового восприятия, которое мы вам предоставляем, может, вы больше визуал, вам необходимо что-то посмотреть, в общем, на YouTube прекрасная подборка свежего материала есть. +6501.00 6507.00 "Анатолий Кулаков" И в частности, я хотел бы вам назвать последние выпуски, что же у нас там накопилось. +6507.00 6519.00 "Анатолий Кулаков" Владимир Куропатко, логирование в .NET с помощью Serilog, оптимизация и отказоустойчивость, в общем, очень интересная опытка компании, как использовать Serilog. +6519.00 6523.00 "Анатолий Кулаков" Константин Финагин рассказывал нам про approval-тестирование. +6523.00 6539.00 "Анатолий Кулаков" Неожиданные тесты, в общем, мало кто, оказывается, знал у нас про approval-тестирование, там, по-моему, 3% всех посетителей или что-то в этом духе, возможно, вы тоже не знаете, что такое approval-тестирование, поэтому посмотрите доклад Константина, возможно, вам подойдут те подходы по тестированию, которые он рассказывал. +6539.00 6549.00 "Анатолий Кулаков" Евгений Масленков рассказывал про вайб-кодинг, то есть, как он использует пресловутый вайб-кодинг и искусственный интеллект в своей работе. +6549.00 6555.00 "Анатолий Кулаков" Алексей Андреев банально про архитектуру и микросервисы, опять же, вечные темы. +6555.00 6579.00 "Анатолий Кулаков" Дмитрий Нестерюк - разработка с использованием IE, обновленная версия доклада, это вторая уже версия вышла, рефреш весна 2025, у Дмитрия есть и первая часть, которая пользуется очень большей популярностью у нас на канале, поэтому обязательно посмотрите, если вы увлекаетесь IE, то находки, наработки и идеи Димы всегда интересны, всегда актуальны. +6579.00 6585.00 "Анатолий Кулаков" Виктор Япольский рассказал нам про оптимизацию и ускорение MongoDB сериализации. +6585.00 6601.00 "Анатолий Кулаков" Опять же, редкая для база данных, наверное, для дот-нет-разработчика, но все-таки встречается, встречается в нашей жизни, поэтому, если вас интересует перформанс сериализации в MongoDB и определенные хаки в определенных условиях, тоже очень интересные случаи были у команды Алексея. +6601.00 6607.00 "Анатолий Кулаков" И Егор Стрелов рассказывал про distributed tracing для поиска проблем, знаете, где? В Entity Framework. +6607.00 6613.00 "Анатолий Кулаков" В общем, как к Entity Framework прикрутить distributed tracing, зачем это нужно и какие проблемы, в свою очередь, искать. +6613.00 6623.00 "Анатолий Кулаков" Тоже прекрасный кейс, и вообще у ребят в компаниях творятся довольно интересные вещи, они их классно решают, и поэтому много интересных докладов выходит на нашем канале. +6623.00 6637.00 "Анатолий Кулаков" Если еще не подписаны, то присоединяйтесь к каналу dotnet.ru на YouTube, а также не только на YouTube, я еще перенес все видео в ВКонтакте, в ВК-видео, поэтому кому удобнее, можете посмотреть ВКонтакте. +6637.00 6639.00 "Анатолий Кулаков" Ну теперь, кажется, это точно все. +6639.00 6671.00 "Игорь Лабутин" Да, на этом мы сегодня будем заканчивать, мы посмотрели на новинки dotnet 10 preview 6, узнали, как потихонечку рефакторить анимичные модели в более тяжелые, но правильные behavior-driven models, посмотрели на немножечко внутряночку скейп-анализа, как dotnet это делает, подумали, разобрали 5 типичных ошибок, которые разработчики делают, когда строят свои API, ну и немножко полезных ссылок, кратко разно. +6671.00 6673.00 "Игорь Лабутин" На этом на сегодня все. +6673.00 6677.00 "Анатолий Кулаков" Всем до новых встреч, всем пока, шарии, пост лайки. +6677.00 6679.00 "Анатолий Кулаков" До новых встреч. +6679.00 6681.00 "Анатолий Кулаков" Пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-120.txt b/input/Radio/Transcriptions/RadioDotNet-120.txt new file mode 100644 index 0000000..3b3811c --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-120.txt @@ -0,0 +1,543 @@ +6.00 8.00 "Анатолий Кулаков" Здравствуйте, дорогие друзья! +8.00 11.00 "Анатолий Кулаков" В эфире Радио.нет выпуск номер 120. +11.00 13.00 "Анатолий Кулаков" В студии ее постоянный ведущий Анатолий Кулаков. +13.00 15.00 "Игорь Лабутин" И Игорь Лабутин. Всем привет! +15.00 20.00 "Анатолий Кулаков" А также мы выражаем огромную благодарность нашим великим помогаторам. +20.00 45.00 "Анатолий Кулаков" Среди них Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Посторнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Игорь Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин и Евгений Асташев. +45.00 47.00 "Анатолий Кулаков" Большое спасибо всем, что поддерживаете подкаст. +47.00 61.00 "Анатолий Кулаков" Если вы хотите тоже оказаться в числе поддерживающих подкаст, то заходите на наш сайт iqboost и посмотрите. У нас там много интересных еще есть эпизодов, лекций, комментариев, а также чат для наших помогаторов. +61.00 69.00 "Игорь Лабутин" И нас поддерживает компания Altenar, которая разрабатывает, масштабирует надежные решения для индустрии спортивных данных, которыми пользуются по всему миру. +69.00 80.00 "Игорь Лабутин" Разработка компании международная, пишутся высоконагруженные приложения, идеи команды не теряются в десятках согласований, все просто, быстро и хорошо и прекрасно для команды. +80.00 83.00 "Игорь Лабутин" Можно качать английский, можно использовать областиные платформы. +83.00 87.00 "Игорь Лабутин" Если вы вносите большой вклад, возможно продолжение карьеры в европейском офисе. +87.00 95.00 "Игорь Лабутин" А также ребята активно делятся опытом, проводят митапы, выступают с докладами и не только. Свидеть за новостями компании можно в их телеграм-канале. +95.00 98.00 "Анатолий Кулаков" Ну что ж, погнали далее к темам. +98.00 109.00 "Анатолий Кулаков" Наши слушатели очень часто нас корят, если мы упоминаем слишком мало Ispire выпуски, поэтому сейчас для вас прям большой сюрприз. У нас первая тема большая, массивная, про Ispire. +109.00 111.00 "Игорь Лабутин" Да, про Ispire. +111.00 124.00 "Игорь Лабутин" Ребята выложили большой пост, не пост, ну короче, ну наверное да, можно сказать пост в дискашенах своего github-репозитория, который называется Ispire roadmap 2025-2026. +124.00 150.00 "Игорь Лабутин" Правда в тексте написано, что это roadmap на ближайшие 6 месяцев, хотя глядя на его объем, я не уверен, что все это можно успеть за 6 месяцев, так что поглядим, что из этого реально успеется за полгода, но давайте разбираться по порядочку. Посмотрим, что же нас ожидает с точки зрения Ispire и какой прекрасный продукт мы в результате получим, когда все обещанные, так сказать, в roadmap фишки будут сделаны и готовы. +150.00 158.00 "Игорь Лабутин" Конечно же Ispire в первую очередь это про local development experience, то есть про локальное использование, а никак не в продакшене. +158.00 164.00 "Игорь Лабутин" И тут есть довольно большое количество всяких разных плюшек, обещанных нам. +164.00 166.00 "Игорь Лабутин" Во-первых, про сеть. +166.00 204.00 "Игорь Лабутин" Появится не просто обращение к сервисам друг к другу по имени тому, которое определено в вашем файле конфигурации, но и появится полноценная поддержка DNS для доменной зоны .localhost. То есть у вас будет каждый ресурс получать название, что-то типа redis.localhost, api.localhost, ну и все это будет работать. Зачем сделано, не знаю, в принципе, и по обычным просто названиям работает нормально, но, видимо, так лучше, плюс, вероятно, так проще отключать какие-то внутри еще дополнительные интеграции, не знаю. +204.00 208.00 "Анатолий Кулаков" Наверное, это, может быть, нужно не дотнетным процессором, а какими-нибудь экзешниками. +208.00 220.00 "Анатолий Кулаков" Представляешь, ты запускаешь какую-нибудь командную строку или ту же самую постгрю, и она не знает, как зарезолвить с помощью сервиса локатора какое-нибудь дотнетное приложение. А вот DNS все знают, +220.00 230.00 "Игорь Лабутин" и DNS все понимают. Ну да, и придется каким-то образом еще инжектироваться в систему, чтобы сторонние процессы знали, что такое localhost, но, в принципе, это во всех операционных системах более-менее понятно, как делать. +230.00 256.00 "Игорь Лабутин" Дальше, в продолжении DNS, также будет поддержан локальный HTTPS везде, то есть можно будет поднимать настоящие HTTPS-эндпойнты и использовать их нормально, а не HTTP. И это хорошо и правильно, потому что, когда вы работаете с HTTP либо с HTTPS-эндпойнтами, особенно из современных браузеров и веб-приложений, там существенно по-разному все работает, то есть там всякие куки по-другому немножко будут работать, ну и прочее все-таки. +256.00 260.00 "Игорь Лабутин" Современный веб заточен на HTTPS именно, поэтому это хорошо. +260.00 270.00 "Игорь Лабутин" И третья штука с сетью, это называется DevTunnels. Мы так или иначе касались всяких разных туннелей в S-коде, в Visual Studio, и вот это все. +270.00 274.00 "Игорь Лабутин" И здесь это примерно то же самое, да не совсем. +274.00 294.00 "Игорь Лабутин" Это смысл в том, чтобы, если вы хотите поделиться с коллегой, например, сервисом, который работает у вас на компьютере, вы поднимаете у себя на компьютере сервис, и Ispire сможет его выставить наружу для коллеги, например, которые в той же сетке находятся. Я не уверен прям совсем в весь интернет, но тем не менее. +294.00 302.00 "Игорь Лабутин" То есть помимо точки localhost нужно будет, видимо, как-то обращаться с соседних компов, так что Ispire будет понимать, где находится тот другой сервис. +302.00 304.00 "Игорь Лабутин" Ну, когда сделают, поглядим. +304.00 326.00 "Игорь Лабутин" Дальше, по workflow вообще в целом, по тому, как вы работаете с Ispire, и что вы можете с ним делать, появится несколько фич. Во-первых, можно будет поднимать только подмножество сервисов, которые вы хотите. То есть сейчас, когда вы говорите Ispire Run, то поднимается полная конфигурация, которая у вас указана. +326.00 338.00 "Игорь Лабутин" Технически для, допустим, воспроизведения какой-то проблемы, бага, не знаю, еще чего-то, вам нужно поднять только какое-то подмножество сервисов, которые у вас определено. Вот будет способ это сделать. +338.00 366.00 "Игорь Лабутин" Дальше можно будет внутри контейнеров, то есть, если у вас есть контейнеры, которые поднимаются в качестве сервисов, можно будет выполнять прямо команды внутри этих контейнеров. Понятно, что это можно сделать сейчас, какой-нибудь docker.exe, найти название контейнера, и все нормально будет, но будет такой нативный, удобный способ это сделать прямо через Ispire. Внутри контейнеров сейчас у нас не поддержана отладка .NET проектов, так вот это можно будет делать. +366.00 372.00 "Игорь Лабутин" Даже если вы завернете ваш .NET проект внутрь контейнера, его все равно можно будет нормально отлаживать, то есть, отладку каким-то образом прокинуть внутрь. +372.00 388.00 "Игорь Лабутин" Будет добавлена поддержка мультирепозиториев, то есть, сейчас у нас ну, скажем так, какой-то нативной поддержки кейса, когда у вас ваши сервисы разложены по разным репозиториям, а, например, апхост лежит еще в одном репозитории, в общем-то, нету. +388.00 400.00 "Игорь Лабутин" Понятно, что все сделать можно, можно, там, не знаю, каждое репозитория, приложение собирать в отдельный контейнер, а потом в хосте все это собирать, как будто это все сторонние контейнеры, но это все-таки не совсем нативный способ. +400.00 406.00 "Игорь Лабутин" Удобнее было бы, если можно было указать, что вот там .NET приложение, оно лежит в соседнем репозитории, бери оттуда. Ну, будет можно. +406.00 438.00 "Игорь Лабутин" И, более того, будет фича под названием Built-in Runtime Acquisition, то есть, если вы, например, в вашем Aspire приложении укажете, не знаю, там, какую-нибудь питоновскую зависимость, ну, питоновский сервис, или сервис на Node.js, или на Java, или на .NET, и у вас почему-то внезапно, ну, с .NET вряд ли это произойдет, но, тем не менее, на вашем компе нету рантайма для той технологии, которую вы указали в сервисе, то Aspire сам подтянет нужную. +438.00 456.00 "Игорь Лабутин" Тут, конечно, вопрос, какую нужную, ну, условно говоря, в .NET более-менее понятно, что она одна, плюс-минус, там, один рантайм нужной версии. Ну, с Node, наверное, плюс-минус тоже, а вот там, какую дистрибуцию Java, ну, вероятно, ту, которая от Microsoft, но, тем не менее. Короче, интересно, как это будет работать, ну, поглядим. +456.00 458.00 "Игорь Лабутин" Вот. Дальше. +458.00 462.00 "Игорь Лабутин" Естественно, разработка не обходится никогда без тестирования. +462.00 476.00 "Игорь Лабутин" В тестировании тоже будут улучшения. Во-первых, будет работать дашборд во время тестирования. То есть, пока у вас идут тесты, можно будет вживую на дашборде смотреть, что там происходит, ну, какие-нибудь там метрики смотреть, например, еще что-нибудь. +476.00 502.00 "Игорь Лабутин" В принципе, тоже нормально. Более того, например, поскольку у нас мы, напомню, внутрь Aspire начинаем встраивать всякие диплойменты, то, скорее всего, кусочки Aspire будут запускаться во время CI. Так вот, можно будет эти самые кусочки записывать и реплайить их после того, как они прошли на CI. Таким образом, упростится отладка того, что происходило на CI. +502.00 512.00 "Игорь Лабутин" Ну, соответственно, кусочек про то, что можно будет запускать только под множество приложений для тестов будет очень полезно. И это прям отдельной фичей написано. +512.00 534.00 "Игорь Лабутин" Дальше будет фича под названием "Request Redirection and Mocking". То есть, можно будет сказать, что, например, ради тестов нам, в принципе, не знаю, какой-нибудь Redis поднимать не надо, достаточно замокать тот факт, что он всегда отвечает, что ничего нет во мне, да, или там всегда отвечает, что там вот-вот без записи с кэша. +534.00 544.00 "Игорь Лабутин" То есть, можно будет что-то не поднимать, либо какие-нибудь внешние зависимости замокать и, таким образом, в тестах что-то ускорить или упростить. +544.00 546.00 "Игорь Лабутин" Ну и код-кавер, это одно считать. +546.00 550.00 "Игорь Лабутин" Так, сам дашборд. Дашборд тоже улучшится. +550.00 552.00 "Игорь Лабутин" В дашборде появится Storage Support. +552.00 570.00 "Игорь Лабутин" Можно будет сохранять состояние дашборда на какое-то время, в том числе и телеметрию, для того, чтобы после рестарта или после падения вся эта телеметрия у вас сохранилась. Сейчас напомню, мы запустили AppHost, он все это коллективит в In-Memory Storage, и когда вы завершаете выполнение приложения, все данные, в общем-то, теряются. +570.00 574.00 "Игорь Лабутин" Это все еще предназначено только для разработки и для тестирования. +574.00 594.00 "Игорь Лабутин" В основном, я так понимаю, что эта штука нужна для тестирования, чтобы после того, как у вас запустился тест-ворклоу, который контролируется самим Ispire, вы не потеряли все данные, да, логи, метрики и прочее. А они были сохранены, и вы могли бы на них посмотреть. Вот. Это все еще, конечно, не предназначено для продакшена или каких-то там высоконагруженных систем. +594.00 610.00 "Игорь Лабутин" Можно будет с графами, ну, в смысле, с этими, ну да, граф ресурсов немножко покрутить по-другому. Можно будет чуть лучше, хотя мне казалось, что сейчас это уже есть, связку трейсов, логов и метрик. +610.00 616.00 "Игорь Лабутин" Мне казалось, что какая-то минимальная сейчас есть, но, тем не менее, видимо, что улучшится. +616.00 618.00 "Игорь Лабутин" Потом, так, дипломин попозже. +618.00 626.00 "Игорь Лабутин" А, ну, поиск и фильтрация, понятное дело, искать лучше логи, трейсы, ресурсы, ивенты, короче, все, что хотите. +626.00 636.00 "Игорь Лабутин" И вот это, следующий пунктик, он такой, типа, вы в продакшен не ставьте, но мы обещаем вам поддержать reverse proxy support и настраиваемый бейс паф. +636.00 644.00 "Игорь Лабутин" Ну, как бы, я не знаю, зачем еще он может быть нужен, кроме как для диплоев. Какой-никакой прот, вроде, для тестов и прочего. +644.00 648.00 "Игорь Лабутин" Вряд ли вы будете поднимать централизованный дашборд на все ваши тесты. Ну, фиг знает, +648.00 650.00 "Анатолий Кулаков" может быть, вот. +650.00 654.00 "Анатолий Кулаков" Может, чтоб тестировать лучше то, что ты потом развернешь в продакшен? Ну, может быть, +654.00 662.00 "Игорь Лабутин" может быть, да. Поближе, поближе быть к продакшену. Не, ну, как это, фича хорошая, за reverse proxy можно захотеть поставить все, что угодно, поэтому пусть будет. +662.00 678.00 "Игорь Лабутин" Конечно же, не обошлось без AI. У нас, конечно же, будет специальная вьюшка для того, чтобы початиться с LLM-кой, с визуализацией, сколько токенов вы потратили, там будут стоять какие-то метрики специфичные для LLM. +678.00 682.00 "Игорь Лабутин" Ну, видимо, так сказать, KPI сами себя не сделают, приходится делать. +682.00 686.00 "Игорь Лабутин" Не знаю, насколько это будет полезно, но допустим. +686.00 698.00 "Игорь Лабутин" С тулингом. Значит, с тулингом ситуация следующая. У нас уже есть Aspire Cli, command-line interface, соответственно, он будет расширяться, ну, будет, соответственно, физически улучшаться и так далее. +698.00 728.00 "Игорь Лабутин" Добавятся инсталлеры, то есть, для винды и для касси, соответственно, Vinget и Homebrew. Это, наверное, Homebrew, понятно, на ланке самое популярное, что используется для инсталляции, ну, для винды, понятно, Vinget. Что же еще? Дальше хотят App-host сделать minimal, executable и single file, то есть, чтобы можно было запустить Aspire App без необходимости собирать этот самый App-host дополнительно. +728.00 742.00 "Игорь Лабутин" Сразу можно будет поставить App-host, который просто может прочитать, уметь вашу конфигурацию и все запустить. Ну и расширение для VS-кода, которое позволит запускать, отлаживать и всячески работать с Aspire-аппликациями на дотнете, джаваскрипте и питончике. +742.00 744.00 "Игорь Лабутин" И вот я уже... +744.00 746.00 "Анатолий Кулаков" Опять большие Visual Studio как-то молчат, +746.00 750.00 "Игорь Лабутин" обделают. Да, да, про большие Visual Studio вообще ни слова. +750.00 778.00 "Игорь Лабутин" При этом, как я уже сказал, не один раз упомянул джаваскрипт, упомянул питон, у них прям явно написано, отдельный раздел называется support. Они хотят сделать один, ну не одинаковый, то, что называется consistent на английском, интеграции. То есть хочется, чтобы были типизированные connection-строки, все правильно подтягивалось в конфиге, телеметрия работала одинаково для... Ну вот сейчас они это планируют для питончика и для NPM. +778.00 790.00 "Игорь Лабутин" Полностью хотят, соответственно, шаблончики и примеры тоже на C#, питоне и джаваскрипте сделать, чтобы было в документации готово для этих трех экосистем, так скажем. +790.00 806.00 "Игорь Лабутин" Ну и экспериментальная фича, интересная, но очень экспериментальная. Они смотрят на то, на вас, чтобы сделать поддержку нескольких runtime в одном процессе. +806.00 812.00 "Игорь Лабутин" Вот. То есть, чтобы вы могли, вероятно, внутри одного процесса запускать прям... +812.00 820.00 "Игорь Лабутин" Вообще, конечно, непонятно, зачем обхостить. Обхост уже у нас .NET, дофига туда тащить питон, но, может быть, зачем-то надо. Поглядим. +820.00 824.00 "Игорь Лабутин" Зачем это, может быть, надо и получится ли у них что-нибудь. Но мысль интересная. +824.00 844.00 "Игорь Лабутин" Так, AI, ну, понятно, опять AI, Aspire MCP Server, OpenAI Integration, вот это все. Значит, по хостингам, по тому, по интегрейшнам у нас, что будет с интегрейшнами? Это я напомню модули, которыми Aspire расширяется. +844.00 854.00 "Игорь Лабутин" С точки зрения аутентификации, конечно же, будет поддержка майкрософтовского EnterID, будет CakeLog, и будет EasyAuth. +854.00 866.00 "Игорь Лабутин" В Ажур, понятное дело, там куча всяких разных EventGrids, FrontDoor, API Management, Kusto добавит. Ажур Redis Enterprise, ну, в общем, дальше продолжат добавлять Ажуры. +866.00 868.00 "Игорь Лабутин" И диплойменты. Диплойменты - это прям интересно. +868.00 878.00 "Игорь Лабутин" Напомню, что исходно к философии Aspire была мыть и поток для локальной разработки. Ничего не делаем для диплоймента. Ну, мы можем сгенерить некоторый JSON-чик, описывающий ваше приложение. +878.00 880.00 "Игорь Лабутин" Дальше вы сами с ним что-нибудь делаете. +880.00 888.00 "Игорь Лабутин" Был проект Aspire 8, который из этого чего-нибудь генерировал, соответственно, куберовские конфиги. Ну, и нативная поддержка была еще для Ажура. +888.00 900.00 "Игорь Лабутин" В общем, это все поменялось, о чем мы рассказывали некоторое время назад, и у нас теперь хочется сделать полноценные диплойменты внутри Aspire. И для General Availability у них сейчас стоят таргеты. +900.00 914.00 "Игорь Лабутин" Ну, в основном, это, конечно, ажурные всякие разные. Ажур Container Apps, Azure Functions, Azure App Service, Azure Container Apps Jobs, Azure Kubernetes, Azure Functions, которые App Services, и Docker Compose и Kubernetes. +914.00 918.00 "Игорь Лабутин" Все они сейчас в той или иной степени прогресса. +918.00 924.00 "Игорь Лабутин" Какие-то, ну, там для меня самые интересные - Docker Compose и Kubernetes - они в процессе. +924.00 928.00 "Игорь Лабутин" Azure Container Apps уже готовы, остальные там что-то в процессе, что-то только запланировано. +928.00 930.00 "Игорь Лабутин" Вот. +930.00 934.00 "Анатолий Кулаков" Ну, то есть мы сможем из Aspire прямо в любой кубер катить нашу продакшн среду? +934.00 948.00 "Игорь Лабутин" Типа того, да. То есть ты скажешь какой-нибудь Aspire диплой и какой-нибудь там, не знаю, эндпоинт твоего кубера, ну, апишки куберовской, кубер хоста, и все, и дальше оно само там все создаст как надо, без всяких хелмов и прочего. +948.00 950.00 "Анатолий Кулаков" Вот. +950.00 952.00 "Анатолий Кулаков" То есть мы тут покусились уже на хелмы, на всякие. +952.00 962.00 "Игорь Лабутин" Да. Более того, ну, то есть да, вот это все они действительно хотят сделать не просто какую-то экспериментальную поддержку, а прямо general availability, полноценную нормальную поддержку. +962.00 970.00 "Игорь Лабутин" Более того, они хотят залезть в область CI/CD, как я уже сказал, они хотят, чтобы Aspire запускался в районе CI. +970.00 980.00 "Игорь Лабутин" Хочется сделать следующее. Во-первых, хочется уметь генерировать пайплайны для GitHub Actions, Azure DevOps и GitLab. +980.00 992.00 "Игорь Лабутин" Вот. И эти пайплайны должны уметь поддерживать конфигурацию через переменные окружения, нормальную поддержку секретов, вот это все. +992.00 994.00 "Игорь Лабутин" То есть в общем... +994.00 998.00 "Анатолий Кулаков" Это, кстати, не такая большая проблема, потому что, например, Nuke Build это давно уже умеет делать. +998.00 1000.00 "Анатолий Кулаков" Скорее всего, можно у него как обычно украсть +1000.00 1008.00 "Игорь Лабутин" и все. Ну да, но тем не менее, из простого тула для локальной разработки оно как-то уже рожается во что-то большое. +1008.00 1012.00 "Анатолий Кулаков" Тут больше интересно, а что собираются в пайплайне делать с помощью Aspire? +1012.00 1018.00 "Анатолий Кулаков" Ну, наверное, заменить им тест-контейнер, типа, чтобы подымалось там, или что-то еще планируется? +1018.00 1020.00 "Анатолий Кулаков" Зачем нам в пайплайне Aspire? +1020.00 1028.00 "Игорь Лабутин" Не понятно пока. Ну, видишь, нет, тесты прогонять им, наверное, прикольно, потому что тебе соберут всякие телеметрии, сразу и логи, и вот это все. Наверное, +1028.00 1030.00 "Анатолий Кулаков" тесты интересные, но только интеграционные. +1030.00 1032.00 "Анатолий Кулаков" В тестах мне что-то... +1032.00 1036.00 "Анатолий Кулаков" В тестах мне какая-то редко нужны телеметрия, логер, а вот, например, тест-контейнеры мне нужны часто. +1036.00 1050.00 "Анатолий Кулаков" То есть это чтобы различные сервисы собрать вместе, там, базу данных, ваше приложение, какой-нибудь между ними кэшик поставить, может быть, несколько сервисов своих собрать, вот, объединить их в сетку, и вот погонять там какие-то запросы. Ну, то есть так вот, чтобы ни один процесс участвовал во всем тестировании. +1050.00 1052.00 "Анатолий Кулаков" Вот это, наверное, может быть полезно. +1052.00 1054.00 "Анатолий Кулаков" То есть это прямой конкурент тест-контейнерам, как я вижу. +1054.00 1056.00 "Анатолий Кулаков" Что еще? Не очень понятно. +1056.00 1058.00 "Игорь Лабутин" Ну, пока да. Непонятно, не знаю. +1058.00 1070.00 "Игорь Лабутин" Далее будет или уже есть, по идее, официальный сайт, соответственно, aspire.dev, он, по идее, есть уже, там всякие доки, сэмплы, понятно, туториалы, вот это все, ютуб-канальчик. +1070.00 1084.00 "Игорь Лабутин" А также они планируют в 2026 году отдельную Aspire.conf. Ну, скорее всего, какой-нибудь community-онлайн-эвент такой, с докладиками, наверное, на денек, который, значит, покажет, как круто Aspire работает. +1084.00 1096.00 "Игорь Лабутин" Ну, в общем, какие-то такие дела, то есть планы, прямо скажем, наполеоновские, большие. Не знаю, насколько все это будет адаптиться, даже внутри дотнета. +1096.00 1098.00 "Игорь Лабутин" А что уж говорить про Python и JS? +1098.00 1102.00 "Игорь Лабутин" Они вообще в курсе, да, что они должны использовать Aspire? Не знаю. +1102.00 1106.00 "Игорь Лабутин" Ну, поглядим. Пока непонятно, но интересно. +1106.00 1116.00 "Анатолий Кулаков" Да, интересно бы статистику было собрать про другие языки. Наверняка у них там есть какая-нибудь анонимная телеметрия. Жалко, что они не публикуют, насколько там проникновение не в дотнет среде есть. +1116.00 1118.00 "Игорь Лабутин" Да даже в дотнет бы интересно. +1118.00 1128.00 "Игорь Лабутин" Потому что я вижу... Это тоже верно. Много кто, ну, там, в Твиттере или еще где-то, пишет, типа, ну, попробовал, не, прикольно, но как бы пока не понимаю, зачем там на работе, условно говоря. +1128.00 1130.00 "Игорь Лабутин" То есть... +1130.00 1142.00 "Анатолий Кулаков" У тебя, кстати, и после вот этого roadmap изменились какие-то представления, а куда оно движется и зачем оно надо? Потому что кажется, что здесь они уже более-менее на что-то претендуют. Кого-то заменяют, кто реально успешный, то есть реально успешной технологией. +1142.00 1148.00 "Игорь Лабутин" Слушай, ну, я так вот сходу не могу сказать. Ну, то есть понятно, что локальный development experience вроде... +1148.00 1152.00 "Игорь Лабутин" Ну, тут все понятно, да, как бы там локальные DNS объединить. +1152.00 1154.00 "Игорь Лабутин" Все, это как бы ладно, действительно. +1154.00 1158.00 "Игорь Лабутин" Это все можно было сделать и вручную, по большому счету, но, действительно, если tooling это будет делать сам, удобно. +1158.00 1168.00 "Игорь Лабутин" Но вот мне deployment, ну, непонятно. Я сомневаюсь, что кто-то будет деплоить просто через SPR deploy. +1168.00 1178.00 "Игорь Лабутин" Скорее всего, там все-таки некоторое количество всяких разных штук. Хотя, ну, не знаю, если какой-нибудь pet-проект для себя пишешь, то, в принципе, наверное, такой tool универсальный для всего, почему нет? +1178.00 1180.00 "Игорь Лабутин" Хотя, я бы предпочел все равно GitHub action какой-нибудь. +1180.00 1182.00 "Игорь Лабутин" Ну, вот его можно будет +1182.00 1188.00 "Анатолий Кулаков" теперь изгенерить. Допустим, тебе надо два контейнера развернуть и базу между ними, но ты ж не будешь ли это Helm'ы писать всякие? +1188.00 1190.00 "Анатолий Кулаков" А это, пожалуйста, одной командой в готовый кубер. +1190.00 1196.00 "Игорь Лабутин" Ну, скорее всего, да. То есть вот такие, как бы, небольшие проектики для pet-проектов вообще прекрасны. +1196.00 1202.00 "Игорь Лабутин" В Prod'е, ну, не знаю, я возьму соседний продукт такой же, Helm с него скопирую, название поменяю, и вот мне готовый Helm. +1202.00 1204.00 "Игорь Лабутин" Это ты умный, +1204.00 1208.00 "Анатолий Кулаков" ты знаешь Helm, а вот если не знаешь, .NET Deploy это все знают. +1208.00 1212.00 "Игорь Лабутин" Еще раз, даже если я не знаю, я его скопирую, название поменяю, и все. +1212.00 1218.00 "Игорь Лабутин" Мне, как бы, YAML с нуля писать не надо. Я не настолько знаю Helm, чтобы написать Helm'овый YAML'ик с нуля. +1218.00 1222.00 "Игорь Лабутин" Вот так вот, не выглядывая никуда. Я все копирую и изменяю. +1222.00 1228.00 "Анатолий Кулаков" Опять же, может, это все только начало, потом как бы мы Ansible какой-нибудь убьем, потом, глядишь, и до кубера +1228.00 1254.00 "Игорь Лабутин" дотянемся? Ну, поглядим, поглядим, да. Не знаю пока, но какая-то форма проглядывает, но непонятно, что из этого всего получится в плане, что будет сделано и насколько это будет, конечно, адаптиться, потому что сделать-то все можно. Фаулер может сколько угодно писать в Твиттере, что вау, какая красная штука, и вот это все, но вопрос, будет ли это использоваться. А это пока непонятно. +1254.00 1262.00 "Анатолий Кулаков" Ну, хорошо, хорошо, поживем, посмотрим, а мы обо всем будем докладывать, рассматривать и докладывать, поэтому не переключайтесь. +1262.00 1288.00 "Анатолий Кулаков" На следующую тему я хотел бы подробнее рассказать про новую толзу, которая называется DNX. Мы как раз в прошлый раз смотрели анонс превью шестого в .NET SDK, и там появилась новая команда, как раз которая нам рассказывала, каким образом мы можем запускать нугетные толзы, не устанавливая их. +1288.00 1312.00 "Анатолий Кулаков" Вот сегодня хотелось бы разобраться подробнее. Как я уже упомянул, эта команда называется DNX, и служит она как раз для того, для чего раньше мы использовали нугетные толзы. То есть мы их сначала устанавливали, а потом запускали, в общем. И эта команда позволяет их запускать, якобы не устанавливая, просто одной командой. +1312.00 1326.00 "Анатолий Кулаков" Очень удобно и очень интересно. Давайте же посмотрим подробнее, что она из себя представляет и как работает. Ну, если начинать с истории, то еще в Node.js, в далекие времена, появилась такая команда, которая называется npx. +1326.00 1328.00 "Анатолий Кулаков" Немножко что-то напоминает, да? +1328.00 1338.00 "Анатолий Кулаков" В общем, и вот эта команда npx, она как раз делала то же самое. Она брала пакеты Node.js, доставала из них какие-то инструменты и позволяла их запускать. +1338.00 1346.00 "Анатолий Кулаков" Как раз позволяла запускать, и это всем очень нравилось, да и в принципе сейчас нравится, и всем этим очень сильно пользуется. +1346.00 1356.00 "Анатолий Кулаков" И в .NET Core у нас почти была такая же возможность, то есть у нас уже были какие-то инструменты, которые мы могли скачать из Nuget пакетов и прекрасно их инсталлировать и прекрасно их запускать. +1356.00 1358.00 "Анатолий Кулаков" И вот теперь мы сделали там какой-то последний шаг. +1358.00 1364.00 "Анатолий Кулаков" Мы научились эти инструменты запускать без явной инсталляции. +1364.00 1368.00 "Анатолий Кулаков" И как я уже упомянул, эта поддержка появилась в превью 6 10 .NET. +1368.00 1374.00 "Анатолий Кулаков" Поэтому, чтобы все это вам попробовать, вам необходимо будет вот на этих версиях сосредоточиться. +1374.00 1378.00 "Анатолий Кулаков" И также у нас появилась команда dnx. +1378.00 1390.00 "Анатолий Кулаков" Тут стоит сказать, что у нас есть две сущности dnx. Во-первых, это отдельная команда, то есть отдельный запускабельный файл, который есть в вашей системе. +1390.00 1396.00 "Анатолий Кулаков" Вы можете сказать dnx, указать имя инструмента, и этот инструмент будет запущен. +1396.00 1402.00 "Анатолий Кулаков" И также вы можете сказать .NET dnx имя инструмента, то есть запустить то же самое через команду .NET, и он тоже будет запущен. +1402.00 1414.00 "Анатолий Кулаков" Поэтому можно и так и так пользоваться, но сокращённое dnx инструмента призвано вам упростить жизнь, поэтому, скорее всего, вы будете предпочитать именно её. +1414.00 1426.00 "Анатолий Кулаков" И что же эта штука делает? Как я уже упомянул, это небольшой аналог .NET Tool команды. И если мы посмотрим, например, на её возможности, на её команды, то они очень сильно пересекаются с .NET Tool. +1426.00 1428.00 "Анатолий Кулаков" Единственное отличие... +1428.00 1444.00 "Анатолий Кулаков" Да, .NET Tool команда - это как раз инструмент, который позволяет вам скачать например, какие-то другие приложения, которые уже распространяются через NuGet-пакеты, установить их локально и начать запускать. +1444.00 1446.00 "Анатолий Кулаков" Так вот, различие. +1446.00 1460.00 "Анатолий Кулаков" Различие заключается, на первый взгляд, в том, что во внешнем интерфейсе в том, что вы dnx можете указать ещё версию той команды, которую вы хотите скачать и запустить. +1460.00 1464.00 "Анатолий Кулаков" Версия указывается с помощью разделителя собаки. +1464.00 1466.00 "Анатолий Кулаков" То есть вы пишете имя пакета, собака и версия. +1466.00 1474.00 "Анатолий Кулаков" Мы уже не первый раз встречаем эту собаку, которая начала появляться в .NET 10 и проникает всё больше и больше в нашу систему. +1474.00 1482.00 "Анатолий Кулаков" И это прямое влияние Node.js, AGO и подобных экосистем, где такой синтаксис принят. +1482.00 1486.00 "Анатолий Кулаков" К сожалению, скорее всего, у нас он тоже начнёт быть скоро принят. +1486.00 1494.00 "Анатолий Кулаков" По дефолту, если вы запускаете команду dnx, она запускается в интерактивном режиме. +1494.00 1500.00 "Анатолий Кулаков" То есть она у вас спросит, хотите ли вы действительно скачать этот инструмент или не хотите. +1500.00 1508.00 "Анатолий Кулаков" Если вы предпочитаете неинтерактивный режим, то можно указать флажок --yes и она будет работать самостоятельно, без всяких дурацких вопросов. +1508.00 1516.00 "Анатолий Кулаков" Но даже с дурацкими вопросами она его задаст только первый раз. Следующие запуски команда уже вас спрашивать не будет. +1516.00 1518.00 "Анатолий Кулаков" Она уже запомнит ваш ответ. +1518.00 1526.00 "Анатолий Кулаков" Итак, давайте же разберёмся, в чём отличие dotnet tool от нашего dnx. +1526.00 1532.00 "Анатолий Кулаков" Как я уже говорил, dotnet tool install позволяет вам поставить какой-то инструмент у себя на компьютере. +1532.00 1544.00 "Анатолий Кулаков" У него есть два режима. Это инсталлировать инструмент глобально, чтобы он был доступен из всей вашей системы, и локально, чтобы он был доступен в рамках какого-то проекта, какого-то solution. +1544.00 1552.00 "Анатолий Кулаков" Когда эти инструменты начинают работать, dotnet tool install или dnx, они начинают оба одинаково. +1552.00 1556.00 "Анатолий Кулаков" Они скачивают nuget пакет, в котором запакован этот инструмент. +1556.00 1560.00 "Анатолий Кулаков" Скачивают они его обычно в папочку с nuget кэшом. +1560.00 1564.00 "Анатолий Кулаков" Это глобальный nuget кэш. +1564.00 1574.00 "Анатолий Кулаков" Кстати, если вы ни разу не видели, то nuget кэш можно найти с помощью команды dotnet nuget locals all --list. +1574.00 1578.00 "Анатолий Кулаков" То есть не саму эту папочку, а вы можете найти пути. +1578.00 1580.00 "Анатолий Кулаков" Все пути, которые использует nuget. +1580.00 1584.00 "Анатолий Кулаков" В частности, в одном из этих путей будет путь к папочке с кэшом. +1584.00 1590.00 "Анатолий Кулаков" У меня на компьютере это часто самая большая папка, которая есть на моем компьютере, поэтому иногда ее приходится даже ручками чистить. +1590.00 1596.00 "Анатолий Кулаков" Посмотрите, может вы тоже удивитесь ее размеру, потому что она умеет очень хорошо пухнуть. +1596.00 1610.00 "Анатолий Кулаков" И умеет очень плохо чиститься. Вернемся к нашей стратегии. Итак, после того, как мы скачали эти пакеты и заинсталировали инструмент в наш глобальный nuget кэш, что происходит дальше? +1610.00 1612.00 "Анатолий Кулаков" Дальше уже стратегии немножко расходятся. +1612.00 1620.00 "Анатолий Кулаков" SDK стандартный, то есть dotnet tool. Dotnet tool распаковывает вот этот пакет в специальную store папочку. +1620.00 1622.00 "Анатолий Кулаков" Папочку со store. +1622.00 1632.00 "Анатолий Кулаков" И создает такой специальный переходник, который располагается в папке .dotnet/tools. +1632.00 1636.00 "Анатолий Кулаков" И эта папка, она добавлена в общие пути нашей системы. +1636.00 1648.00 "Анатолий Кулаков" Поэтому, когда вы где угодно введете в командной строке название этого инструмента, он автоматически запускается. Как раз потому, что в tools создан так называемый... +1648.00 1650.00 "Анатолий Кулаков" Это почти ссылка, почти link. +1650.00 1652.00 "Анатолий Кулаков" Но немножко тоньше. +1652.00 1658.00 "Анатолий Кулаков" То есть практически создана ссылка на настоящий распакованный store инструмент. +1658.00 1662.00 "Анатолий Кулаков" Поэтому вы можете запустить его откуда угодно, из любого приложения, из любой командной строки. +1662.00 1664.00 "Анатолий Кулаков" Это так поступает SDK. +1664.00 1668.00 "Анатолий Кулаков" В отличие от него DNX поступает по-другому. +1668.00 1680.00 "Анатолий Кулаков" После скачивания пакета он точно так же инсталирует его в глобальный кэш всех пакетов, но при этом не происходит никакой инсталляции в директорию store. +1680.00 1686.00 "Анатолий Кулаков" И так же не создается никаких ссылок, никаких линков в .NET tools. +1686.00 1696.00 "Анатолий Кулаков" Вместо этого DNX просто-напросто напрямую запускает инструмент из кэша, из глобального кэша. +1696.00 1700.00 "Анатолий Кулаков" Таким образом происходит такой одноразовый запуск. +1700.00 1702.00 "Анатолий Кулаков" Не оставляет никаких следов в системе, не создает никаких ссылок. +1702.00 1706.00 "Анатолий Кулаков" Поэтому нигде больше вы его не видите и никак вы его не вызовете. +1706.00 1708.00 "Анатолий Кулаков" Но в кэше он лежит. +1708.00 1712.00 "Анатолий Кулаков" И поэтому в следующий раз, когда будет запущен DNX, он уже не будет ничего скачивать. +1712.00 1716.00 "Анатолий Кулаков" Он уже найдет в кэше и напрямую оттуда прямо все запустит. +1716.00 1722.00 "Анатолий Кулаков" И так, теперь давайте разберемся, а что же такое команда DNX? +1722.00 1724.00 "Анатолий Кулаков" И как она под капотом работает? +1724.00 1730.00 "Анатолий Кулаков" Прежде всего, можно выполнить команду get-command, если вы великий обладатель PowerShell. +1730.00 1752.00 "Анатолий Кулаков" get-command-dnx или where-dnx также будут работать на всяких Mac'ах и Linux'ах, которые покажут вам, что же такое DNX. И если вы посмотрите, то и то вы увидите, что DNX это на самом деле кмд файл, cmd файл, который лежит в c-program-files.net, то есть напрямую, рядышком-рядышком с нашей .NET командой. +1752.00 1756.00 "Анатолий Кулаков" И другое откровение в том, что это именно скриптовый cmd файл. +1756.00 1788.00 "Анатолий Кулаков" Если мы внутреннего посмотрим, то он состоит буквально из одной строчки. Это взять команду .NET.EXE, добавить к ней суффикс dnx и все остальные параметры передать, все остальные параметры, которые были переданы в эту команду, просто передать от этой .NET dnx. То есть на самом деле, вот эта автономная команда dnx, которая появилась в нашей системе, она не делает ничего, кроме того, что пересылает это все утилите .NET dnx со всеми аргументами. В принципе то, что в начале я и говорил, что они очень похожи. Не зря они похожи. +1788.00 1806.00 "Анатолий Кулаков" Практически то же самое сделано на Linux и macOS, только там вместо cmd файла там будет bash файл, но смысл тот же самый. Он просто пересылает все возможные аргументы .NET.EXE. Итак, если мы взглянем на верхний уровень работы этой команды, то она делает следующие вещи. +1806.00 1820.00 "Анатолий Кулаков" Если вы забыли задать, то есть специально не задали версию у пакета, у инструмента, который вы хотите запустить, то она пытается найти это в манифесте, в tools-манифест. +1820.00 1834.00 "Анатолий Кулаков" И если это удается, то берет оттуда. Если не удается, то она пытается найти правильную версию через nuget.org. То есть ищет правильный пакет и смотрит, что там у него есть, что там поддерживается, с какими платформами, с какими версиями. +1834.00 1846.00 "Анатолий Кулаков" И дальше, если она нашла правильную версию, которая ей нужна, то она проверяет nuget глобальный кэш. Если пакет уже скачен, то она его запускает. +1846.00 1854.00 "Анатолий Кулаков" Если пакет не скачен, то как раз в этот момент она спрашивает разрешение пользователя и скачивает его. И после скачивания уже запускает. +1854.00 1864.00 "Анатолий Кулаков" Поэтому, если вы запускаете инструмент второй раз, то никакого разрешения у вас больше спрашиваться не будет. Потому что разрешение спрашивается только при скачивании. +1864.00 1866.00 "Анатолий Кулаков" После первого скачивания уже все. +1866.00 1880.00 "Анатолий Кулаков" И после скачивания мы готовы к запуску и соответственно уже происходит директ запуск непосредственно из директории кэша, как мы рассмотрели выше. В принципе это все, что делает данный инструмент. +1880.00 1884.00 "Анатолий Кулаков" Это все, чем он отличается от .NET Tool, которым все мы пользуемся. +1884.00 1886.00 "Анатолий Кулаков" Который все наверняка из вас знают. +1886.00 1898.00 "Анатолий Кулаков" Поэтому никакой магии, никаких глобальных нововведений. Просто хорошо отформатированное, хорошо сложенное и хорошо настроенное все забытое старое. Поэтому пользуйтесь. +1898.00 1902.00 "Анатолий Кулаков" Если кому нужно, у нас появляется еще один интересный инструмент. Посмотрим. +1902.00 1908.00 "Анатолий Кулаков" В будущем наверняка появятся какие-то уже предсказуемые и практически полезные юзкейсы для него. +1908.00 1912.00 "Игорь Лабутин" Ну, один юзкейс мы уже обсуждали в прошлый раз. +1912.00 1914.00 "Игорь Лабутин" Это как раз таки запуск на CI. +1914.00 1928.00 "Игорь Лабутин" Можно конечно сказать .NET Tool install, но по большому счету это overkill, потому что все равно некому будет использовать. Особенно если это внутри контейнера происходит. Он скачает, один раз использует и выкинет в этот контейнер. +1928.00 1944.00 "Игорь Лабутин" Поэтому, скорее всего, это наверное вот разово такие штуки для CI, либо какие-то действительно суперразовые тулы, не знаю там, ну хотя не знаю, очистка Nuget, Cache. Наверное периодически делать надо. +1944.00 1948.00 "Игорь Лабутин" Что-то такое. Миграция может куда-нибудь один раз. +1948.00 1956.00 "Анатолий Кулаков" Наверное любые команды внутри контейнера, если мы говорим, что контейнер это в принципе такая одноразовая штука, любые команды там одноразовые. Все, что тебе один раз надо запустить +1956.00 1958.00 "Игорь Лабутин" в контейнере. Ну да, да. +1958.00 1964.00 "Игорь Лабутин" Наверное так. Ну, в общем, поглядим, опять же, насколько это все будет адаптиться. +1964.00 1968.00 "Игорь Лабутин" Дальше у нас статья Джона Скита. +1968.00 1980.00 "Игорь Лабутин" Джон Скит не так часто сейчас пишет про .NET, но он, я так понимаю, все еще работает над, скажем так, в свободное время над какими-то проектами на .NET. И поэтому периодически от него появляются статьи. +1980.00 1988.00 "Игорь Лабутин" В основном в случае, когда он находит какие-то странности или неожиданное поведение того или иного кусочка .NET. +1988.00 1990.00 "Игорь Лабутин" И вот такое же произошло в этот раз. +1990.00 1998.00 "Игорь Лабутин" В этот раз он разбирался про рекорды, которые он не ожидал, что работают именно так, как они работают. +1998.00 2002.00 "Игорь Лабутин" И спойлер, более того, то, как это документировано, что они работают. +2002.00 2004.00 "Игорь Лабутин" В общем, поведение не совсем очевидное. +2004.00 2008.00 "Игорь Лабутин" Хотя, если подумать, то вполне понятное. +2008.00 2010.00 "Анатолий Кулаков" Появляются новые вопросы на собеседование, я чувствую. +2010.00 2012.00 "Анатолий Кулаков" А как по версии Джона +2012.00 2020.00 "Игорь Лабутин" Скита работают рекорды? Ну, да, наверное. Скорее, не как по версии Джона Скита, а в чем неконсистентность того, что сделано. +2020.00 2022.00 "Игорь Лабутин" Сейчас давайте разберемся. +2022.00 2026.00 "Игорь Лабутин" Во-первых, напомним вообще, что такое рекорды и зачем они появились. +2026.00 2038.00 "Игорь Лабутин" То есть, рекорды сами по себе - это просто некоторая коллекция, грубо говоря, полей, которые вы объявляете прямо в виде, ну, типа как primary конструктор. +2038.00 2050.00 "Игорь Лабутин" Вы, в принципе, свободны дальше внутри рекорда, если хотите объявлять дополнительные пропертии, например, их как-то посчитать на основе тех полей, которые вы передали в primary конструктор. +2050.00 2058.00 "Игорь Лабутин" И дальше вы можете еще рекорды мутировать. Значит, что вы можете сделать? +2058.00 2062.00 "Игорь Лабутин" Вы для этого используете специальный оператор with. +2062.00 2078.00 "Игорь Лабутин" То есть, вы берете ваш какой-нибудь рекорд и пишете какой-то там рекорд под названием x и пишете x with, и дальше можете указать в фигурных клапанах, какие пропертии из этого рекорда нужно заменить на новые значения. Ну, и все прекрасно. +2078.00 2086.00 "Игорь Лабутин" Первый рекорд не меняется, а в результате создается новый, в котором заменены эти самые значения на те, которые вы указали. +2086.00 2090.00 "Игорь Лабутин" Создается новая, соответственно, сущность. +2090.00 2110.00 "Игорь Лабутин" И вот если мы вот эти самые пропертии, которые вы инициализируете через обычный инициализатор, то есть вы пишете внутри рекорда какой-нибудь там public int, не знаю, calculated property, ну, где-то, понятно, и дальше присвоение к какому-нибудь начальному значению. +2110.00 2156.00 "Игорь Лабутин" Оно все работает хорошо при создании, но оно не совсем хорошо работает с вот этим самым изменением через with, хотя ожидалось, что вполне будет. Почему так происходит? То есть происходит это потому, что вот этот самый инициализатор, который вы ожидаете, что будет вызван. Мы же создаем, по сути, новый объект. То есть мы, по сути, было бы логично, как вариант, сделать так, что когда вы пишете x with и дальше, ну, давайте не x, давайте будет какой-нибудь record point, у которого есть переменные x и y, вы создали новый point x, y, и, допустим, у вас есть property в нем distance от нуля, который там квадратный корень из суммы квадратов x и y. +2156.00 2166.00 "Игорь Лабутин" И потом вы создаете новый point, new point, присвоить point with и, не знаю, меняйте x на 0, например. +2166.00 2202.00 "Игорь Лабутин" Казалось бы, можно просто в этот момент создать новый point через этот самый primary конструктор, передать туда x, y и заново пересчитать вот это вот самое значение для дистанца, для вычислимого поля, но на деле все происходит не так. На деле, если вы такое сделаете, у вас будет x, y естественно новый, тот, который вы указали, но при этом вычислимое поле останется старым. Почему так происходит? Потому что на самом деле вызов внутри не вызывает вот этот самый primary конструктор. +2202.00 2214.00 "Игорь Лабутин" Для этого компилятор для рекорда генерирует специальный копирующий конструктор, работа которого заключается просто в том, что он копирует все поля. +2214.00 2226.00 "Игорь Лабутин" И после этого, то есть оператор with, он тупо вызывает конструктор, копирует все поля, и после этого ставит только те в новые значения, которые вы указали в блоке with. +2226.00 2242.00 "Игорь Лабутин" Ну и естественно, скопировав сначала все поля, а только потом проставив новые, никто заново уже инициализированное значение вычислять не будет, и никакого инициализатора не вызывается в этом случае. +2242.00 2258.00 "Игорь Лабутин" Ну или точнее, может быть, он даже и вызывается, если бы вы создали пустой, так сказать, объект, и он бы вызвался, но он все равно перезатирается тем значением, которое копирующий конструктор в генерированный это все переместил. +2258.00 2264.00 "Игорь Лабутин" Понятное дело, что есть простое решение. +2264.00 2268.00 "Игорь Лабутин" А, ну давайте вообще, John Skid предлагает в принципе несколько решений. +2268.00 2270.00 "Игорь Лабутин" Решение первое. +2270.00 2274.00 "Игорь Лабутин" Сказать, что ну как бы да и черт с ним. +2274.00 2278.00 "Игорь Лабутин" Будем знать об этом ограничении. +2278.00 2288.00 "Игорь Лабутин" Оно задокументировано, вполне себе, на сайте Майкрософт, ну просто что вокруг не написано никаких там мурнингов, вот это все, ай-яй-яй, у вас все может сломаться. +2288.00 2290.00 "Игорь Лабутин" Ну как бы нет, ничего не написано. +2290.00 2298.00 "Игорь Лабутин" Поэтому создав копию рекорда через with с вычислимым полем, вы получите старое значение неизмененного вычислимого поля. +2298.00 2318.00 "Игорь Лабутин" Если про это знать, ну в принципе можно писать код аккуратно и просто, допустим, не использовать with для таких рекордов, но это не очень классная стратегия, потому что понятно, что она может в любой момент сломаться о какого-нибудь новичка, который пришел в команду и не знает об этом. Не обязательно даже новичка, а именно человек, который просто об этом не задумывался и не встречался с этой частью T-Sharp. +2318.00 2320.00 "Игорь Лабутин" Вариант номер два. +2320.00 2328.00 "Игорь Лабутин" Можно использовать постоянно вычислимые рекорды, то есть не инстализатору рекорда написать, допустим, у GetOnlyProperty, в смысле. +2328.00 2342.00 "Игорь Лабутин" У GetOnlyProperty не инстализатор написать, а прямо проперти сделать, чтобы значение каждый раз вычислялось. Так сделать можно, оно естественно работать будет, но это не совсем оптимально с точки зрения производительности. +2342.00 2356.00 "Игорь Лабутин" Наверное, в большинстве мест сойдет, но если можно значение вычислить один раз и записать его, особенно если это вычисление какое-то довольно сложное, ну проще все-таки вычислить и записать, нежели простить вычислять каждый раз. +2356.00 2364.00 "Игорь Лабутин" В смысле, не просить, а заставлять CPU все это вычислить. Вполне решение, но надо смотреть, насколько это будет тормозить ваше приложение. +2364.00 2366.00 "Игорь Лабутин" Скорее всего сильно, конечно, не будет, но тем не менее. +2366.00 2370.00 "Игорь Лабутин" Следующий вариант - написать розлин аналайзер. +2370.00 2388.00 "Игорь Лабутин" Понятное дело, что мы можем сделать следующее, что у нас есть список параметров в рекорде, у нас есть список дополнительных пропертей в рекорде, и у нас есть список пропертей, которые вы используете в вашем коде с оператором with. +2388.00 2398.00 "Игорь Лабутин" И если вы внутри оператора with используете, например, только ваши дополнительные проперти, которых нет в прайме-реконструкторе, ну как бы все хорошо, вероятно. +2398.00 2406.00 "Игорь Лабутин" А вот если вы там используете что-то, что есть только в прайме-реконструкторе, а вычислимые поля зависят от них, в принципе это можно детектить. +2406.00 2410.00 "Игорь Лабутин" Задачка непростая, ну и поругаться, задачка непростая. +2410.00 2424.00 "Игорь Лабутин" Такого готового аналайзера Джон не нашел, может быть напишет свой, но что-то как-то он не очень нацелен, так скажем, на это решение, поэтому вряд ли это будет сделано. +2424.00 2434.00 "Игорь Лабутин" И, естественно, все это будет работать только для рекордов, которые в одном солюшене, то есть Roslyn аналайзер, он все-таки... +2434.00 2458.00 "Игорь Лабутин" В общем, если вы будете использовать в библиотеке, не факт, что так легко получится, потому что что там внутри библиотек происходит непонятно, но хотя нет, библиотеки тоже проанализируются. В общем, почему-то, что-то я сейчас не могу сообразить, почему это будет работать только внутри одного солюшена, по идее достучаться до рекорда из другой библиотеки мы тоже вполне можем, там же за ресторят уже все. +2458.00 2460.00 "Игорь Лабутин" В общем, поглядим. +2460.00 2462.00 "Игорь Лабутин" Надо подумать. +2462.00 2464.00 "Игорь Лабутин" Ладно. +2464.00 2478.00 "Игорь Лабутин" Следующая опция, она сродни немножко вот той самой вычислимой перевода проперти в вечно вычислимое состояние. Это промежуточный вариант. Давайте использовать pattern_lazy_at_t. +2478.00 2498.00 "Игорь Лабутин" То есть каждый раз, когда мы создаем копию этой самой структуры рекорду через Rails, у вас будет на самом деле копироваться некоторое внутреннее дополнительное приватное, приватный рекорд, на основе которого будет вычисляться лэйзи поля во внешнем рекорде. В общем, код там выглядит достаточно ужасно. +2498.00 2500.00 "Игорь Лабутин" Надо не забывать это все аккуратно делать. +2500.00 2506.00 "Игорь Лабутин" Добавляет расход памяти, потому что по факту у вас два получается рекорда, внутренний и внешний. +2506.00 2510.00 "Игорь Лабутин" Ну и нужно это аккуратно помнить. В общем, это сродни решение номер один. +2510.00 2514.00 "Игорь Лабутин" Типа в некоторых рекордах это нужно, в некоторых не нужно. Короче, так себе решение. +2514.00 2524.00 "Игорь Лабутин" Ну и последнее решение, оно самое простое. Называется request_a_language_change. А давайте поменяем C#. Ну, скорее всего понятное дело, что вряд ли это произойдет. +2524.00 2532.00 "Игорь Лабутин" Скорее всего, команда C# знает об этом, раз про это прямо написано в документации и думала можно ли это исправить или нельзя. +2532.00 2540.00 "Игорь Лабутин" Единственное, о чем может быть удастся договориться, делать это никаким нерослым аналайзером, а в общем компилятором. +2540.00 2548.00 "Игорь Лабутин" Компилятор прекрасно понимает, что он перезаписывает какое-то вычислимое поле, потому что весь этот код генерится, в общем-то, в момент компиляции. +2548.00 2556.00 "Игорь Лабутин" И поэтому, возможно, какой-нибудь warning в компиляторе добавить на эту тему, чтобы width стал более безопасным. +2556.00 2560.00 "Игорь Лабутин" Ну, в общем, такая вот история. +2560.00 2562.00 "Игорь Лабутин" Казалось бы, простая штука. +2562.00 2564.00 "Игорь Лабутин" Рекорд объявил, через width поменял. +2564.00 2566.00 "Игорь Лабутин" Красиво, всё здорово, имьютабилити. +2566.00 2586.00 "Игорь Лабутин" Вот это всё. Но можно наступить на такой, наверное, довольно редкий, что ли, такой уголочек C#, где он ведёт себя не совсем, ну не то, что ожидаемо, может быть, сказать, не совсем консистентно тому, что ожидает, наверное, разработчик. +2586.00 2602.00 "Игорь Лабутин" Такая вот история. Поэтому, используя всякие разные фичи, убеждайтесь, что в вашем коде, если он, этот самый код, хоть немножко отходит от совсем простейших примеров, что фича на самом деле работает так, как ожидалось. +2602.00 2606.00 "Игорь Лабутин" Напишите каких-нибудь простеньких тестов и проверьте. +2606.00 2608.00 "Анатолий Кулаков" Такая вот история. +2608.00 2614.00 "Анатолий Кулаков" Да, как всегда у скита весьма поучительно, когда он на простых примерах ломает всем голову. +2614.00 2616.00 "Анатолий Кулаков" В принципе, за это мы его любим. +2616.00 2618.00 "Анатолий Кулаков" Ага. +2618.00 2624.00 "Анатолий Кулаков" Пойдём дальше. Я тут решил посмотреть, каким образом у нас .NET может взаимодействовать с Python. +2624.00 2628.00 "Анатолий Кулаков" Вот почему-то мне внезапно сильно захотелось. +2628.00 2632.00 "Анатолий Кулаков" Вспоминаю там прошлое IronPython и так далее. +2632.00 2640.00 "Анатолий Кулаков" И набрёл на интересную штуку, называется PCSnake. Это инструмент, который позволяет вам встраивать Python-овский код прямо в ваш .NET проект. +2640.00 2646.00 "Анатолий Кулаков" Ну, казалось бы, да, зачем это может быть нужно. Но если на самом деле задуматься, то применение масса. +2646.00 2650.00 "Анатолий Кулаков" Python - это довольно популярный язык, как ни странно. +2650.00 2656.00 "Анатолий Кулаков" Его очень много используют для всякого исследования, для дата процессинга, для машин ленд-лёрнинга, тот же самый. +2656.00 2672.00 "Анатолий Кулаков" И никуда без Python сейчас не летит. Поэтому вполне вероятно, что вы почему-то, по какой-то причине, захотите переиспользовать библиотеки, которые уже написаны на Python, уже отлажены, уже используются в индустрии, захотите переиспользовать их в .NET. +2672.00 2698.00 "Анатолий Кулаков" И при этом каким-то образом не хотите мараться на чистом Python, а может быть хотите каким-то образом внутри вашего процесса .NET все эти знания получить и заюзать. Конечно, вы всегда можете поднять Python в каком-нибудь Docker-контейнере, выставить оттуда какие-нибудь поинты и ходить через HTTP, дергать питоновские вызовы, получать данные и по процессу этих в .NET. +2698.00 2700.00 "Анатолий Кулаков" Но кажется, что это какой-то оверкил. +2700.00 2706.00 "Анатолий Кулаков" Возможно, для каких-то больших серверов это правильное взаимодействие, там микросервисы и все такое. +2706.00 2716.00 "Анатолий Кулаков" Но если вам нужно что-нибудь поменьше, что-нибудь покомпактнее, то вам в голову вполне может прийти такая дикая мысль, а встроить Python в свое приложение. +2716.00 2728.00 "Анатолий Кулаков" И вот сейчас мы с вами посмотрим, какими стандартными современными инструментами это можно сделать, где находится у нас сейчас как раз уровень развития .NET. +2728.00 2730.00 "Анатолий Кулаков" Опять же, могут быть пользовательские скрипты. +2730.00 2740.00 "Анатолий Кулаков" Раньше было популярно, когда мы в UIT писали, что пользователь может налобать любой скрипт на каком-нибудь произвольном скриптовом языке, а вы должны его сделать. +2740.00 2744.00 "Анатолий Кулаков" Вот здесь может быть точно такой же какой-то use case, когда вы хотите пользовательские скрипты поддержать. +2744.00 2750.00 "Анатолий Кулаков" В общем, Python можно встраивать в свое приложение, и много для этого use case есть. +2750.00 2752.00 "Анатолий Кулаков" Давайте посмотрим, как. +2752.00 2756.00 "Анатолий Кулаков" Итак, SysNake. SysNake - это инструмент, который состоит из двух частей. +2756.00 2760.00 "Анатолий Кулаков" Во-первых, это .NET Source Генератор, и во-вторых, это Runtime - специальный. +2760.00 2774.00 "Анатолий Кулаков" И с помощью него вы можете встраивать Python-овский код и библиотеки, уже готовые, не только код напрямую, в ваш .NET Solution. Поддерживаются .NET 8 и 9, и Python 3.9.3.13. +2774.00 2788.00 "Анатолий Кулаков" Итак, как же это все работает изнутри? SysNake использует специальный CPython C API, то есть API для вызова C-шных библиотек, для C-шных вызовов библиотек. Давайте так. +2788.00 2800.00 "Анатолий Кулаков" То есть это нормальный, хороший Python, обычный, никакой не микрософтовский, не специально скомпилированный по .NET, это движок настоящего Python, у которого наружу выставлен C API. +2800.00 2812.00 "Анатолий Кулаков" И .NET процесс может напрямую дергать этот C API, передавать какие-то данные внутрь вот этого Python-овского движка, получать данные обратно в виде результата и как-то их обрабатывать. +2812.00 2818.00 "Анатолий Кулаков" Подобное взаимодействие довольно низкоуровневое, что дает ему очень большой перформанс. +2818.00 2824.00 "Анатолий Кулаков" Естественно, это не перформанс, когда вы вызываете .NET-ный код из .NET-ного кода, но вполне приемлемый. +2824.00 2828.00 "Анатолий Кулаков" То есть это перформанс сравним с вызовом обычных C-шных байдингов. +2830.00 2862.00 "Анатолий Кулаков" Имеется совместимость и с любыми Python-овскими расширениями, то есть если не только с нативными Python-овскими, но если расширение на Python-е для Python-а написано на C, такое часто встречается, например, для увеличения производительности математики, поэтому если у вас есть расширение на C для Python-а, то оно тоже прекрасно встроится и прекрасно будет использоваться. Поддерживается куча Python-овских фреймворков, библиотек, технологий, например, Virtual Environments, инсталлятор PIP, работа с NumPy-ами и прочие-прочие такие вещи. +2862.00 2864.00 "Анатолий Кулаков" То есть никаких ограничений практически нет. +2864.00 2874.00 "Анатолий Кулаков" Все, что вы можете запустить, захостить, заделать, заинсталлировать в настоящем Python-е, здесь тоже возможно. Теперь разобрались. +2874.00 2878.00 "Анатолий Кулаков" Python-овский движок у нас полноценный, хороший, взаимодействие с ним понятно какое. +2878.00 2884.00 "Анатолий Кулаков" Теперь как же узнать нам, каким образом, какой Python-овский код через какой .NET-ный метод дергать. +2884.00 2894.00 "Анатолий Кулаков" Здесь тоже авторы подошли довольно современно и модно. Они используют Python-овские хинты для типов. +2894.00 2910.00 "Анатолий Кулаков" Для тех, кто не в курсе тренда, напоминаю, что раньше у нас были динамические языки программирования с динамической типизацией, или как можно было услышать, без типизации вовсе, такие как JavaScript, Python и так далее, которые кричали на каждом углу, что типы им не нужны. +2910.00 2924.00 "Анатолий Кулаков" Типы только для интерпрайса. Да кому нужны вообще эти ваши типы? Так вот, в современном мире JavaScript в виде TypeScript перешел на типы, и Python активно тоже переходит на типы. +2924.00 2928.00 "Анатолий Кулаков" Но это не полноценные типы, как у нормальных языков программирования. +2928.00 2936.00 "Анатолий Кулаков" Это сбоку костыль, чуть ли не комментариями, сделанные так называемые Type Hinting. +2936.00 2942.00 "Анатолий Кулаков" У Python тоже есть теперь возможность указать, какие типы у нас ходят между параметрами, какие результаты возвращаются. +2942.00 2946.00 "Анатолий Кулаков" Поэтому он тоже приближается более-менее по синтаксису к нормальным языкам. +2946.00 2950.00 "Анатолий Кулаков" Естественно, все это поддерживается не всеми инструментами, не всеми компиляторами. +2950.00 2958.00 "Анатолий Кулаков" Питонисты все еще кусают кактус, но при этом сопротивляются. Но в целом технология вполне рабочая. +2958.00 2976.00 "Анатолий Кулаков" Так вот, если у вас задан Type Hinting для сигнатур функций, то вот этот библиотекам с помощью Source-генератора просканирует вам питоновские сигнатуры, и по этим питоновским сигнатурам сгенерит инвокеры для C#. +2976.00 2988.00 "Анатолий Кулаков" Она сгенерит соответствующие методы, соответствующие классы C#, которые будут просто-напросто инвоковать по уже договоренным правильным интеропам питоновский код. И это довольно элегантное и хорошее, красивое решение. +2988.00 2998.00 "Анатолий Кулаков" Весь питон вам не нужно Type Hinting обмазывать, только те сигнатуры, которые вы хотите, чтобы были доступны из внешних библиотек, допустим. +2998.00 3022.00 "Анатолий Кулаков" И вот подобный подход как раз с помощью генератора, который смотрит на Type Hinting и генерирует обертки на C#, и рантайма, который способен поднять настоящий питон и сделать между ними интероп, с помощью вот подобного подхода и формируется то самое заветное .NET-приложение, которое выполняет питон в том же самом процессе. +3022.00 3026.00 "Анатолий Кулаков" То есть процесс у нас один, никаких рядышков, ничего не запускается. +3026.00 3030.00 "Анатолий Кулаков" Весь интерпроцесс Communication, что весьма быстро, оптимально и красиво. +3030.00 3034.00 "Анатолий Кулаков" Естественно, продерживаются все платформы, это Windows, Mac и Linux. +3034.00 3036.00 "Анатолий Кулаков" С этим проблем нет никаких. +3036.00 3038.00 "Анатолий Кулаков" Как же это можно штук попробовать? +3038.00 3044.00 "Анатолий Кулаков" Ну, во-первых, стандартно для всего .NET, это .NET New SysName Templates. +3044.00 3048.00 "Анатолий Кулаков" Вы можете установить себе темплейты и при этом сразу же создать новое приложение. +3048.00 3056.00 "Анатолий Кулаков" Прям первое же приложение Hello World вам покажет на консоли приветствие от питона, то есть из питона. +3056.00 3058.00 "Анатолий Кулаков" Которое было вызвано кодом на C#. +3058.00 3062.00 "Анатолий Кулаков" Буквально вот в одну строчку вы можете посмотреть, как это работает. +3062.00 3070.00 "Анатолий Кулаков" Распространяется это все в виде одного единственного .NET-пакета, который называется cs_sysnx_runtime. +3070.00 3076.00 "Анатолий Кулаков" И этот пакет внутри себя уже содержит и SourceGenerator и все необходимые Runtime в библиотеке. +3076.00 3080.00 "Анатолий Кулаков" SourceGenerator это в принципе рекомендуемая штука. +3080.00 3082.00 "Анатолий Кулаков" Так как я уже выше сказал. +3082.00 3084.00 "Анатолий Кулаков" Очень интересный, хорошие бандинги делает. +3084.00 3098.00 "Анатолий Кулаков" И как бы это бест практисом считается. Но если вдруг вы почему-то хотите взаимодействовать с Runtime напрямую, с питоновским, какой-то сложный кейс у вас допустим, почему-то он не смог типы перемапить. Или не знаю зачем еще, но вы можете это сделать. +3098.00 3104.00 "Анатолий Кулаков" Вы можете в C# напрямую ходить в Python, динамически поддерживать его типы, передавать какие-то аргументы. +3104.00 3108.00 "Анатолий Кулаков" В принципе общаться с ним напрямую. +3108.00 3114.00 "Анатолий Кулаков" Если же вы ничего не хотите этого делать, то пожалуйста SourceGenerator сделает вам все необходимые обертки. +3114.00 3122.00 "Анатолий Кулаков" Для того, чтобы с этим работать в EDM, вам необходимо добавить питоновские файлы, в которых вы напишите необходимые для вас функции. +3122.00 3132.00 "Анатолий Кулаков" И выставить специальный в проекте сделать питоновские файлы пометить как Additional Files. +3132.00 3134.00 "Анатолий Кулаков" И выставить им специальный Build Action. +3134.00 3146.00 "Анатолий Кулаков" Который называется C# Analyzer Additional Files. Это позволяет как раз таки запустить тот самый аналайзер. Тут еще нужно сказать, что анализатор, он же SourceGenerator, он довольно таки умный. +3146.00 3152.00 "Анатолий Кулаков" Например, у питона существуют договоренности об именовании не такие, как в C#. +3152.00 3156.00 "Анатолий Кулаков" У питона именуются методы в виде SnakeCase. +3156.00 3160.00 "Анатолий Кулаков" А у C# методы обычно в PascalCase. +3160.00 3166.00 "Анатолий Кулаков" Так вот, этот генератор-трансформатор он как раз преобразует все к EDM-атическому коду. +3166.00 3168.00 "Анатолий Кулаков" Все питоновские классы, методы. +3168.00 3172.00 "Анатолий Кулаков" И преобразует их именно в PascalCase, с большой буковки, как положено. +3172.00 3174.00 "Анатолий Кулаков" Все, как мы любим в C#. +3174.00 3178.00 "Анатолий Кулаков" При этом у него есть очень богатая поддержка маппинга. +3178.00 3186.00 "Анатолий Кулаков" И поддерживаются не только стандартные типы для маппинга C# и Python, но также типы специфичных библиотек, таких как NumPy. +3186.00 3196.00 "Анатолий Кулаков" Там всякие матрицы, различные вектора и вот эти вот прочие глупости тоже вполне перемапливаются в C# как вы и ожидали это увидеть. +3196.00 3214.00 "Анатолий Кулаков" В примере мы можем не только какие-то простые скрипты использовать, но у нас еще также есть вполне солидные инструментации для хостинга. Например, представим, что у нас есть какой-то файлик demo.py на Python. +3214.00 3216.00 "Анатолий Кулаков" Да, у этого файлика всего две строчки. +3216.00 3220.00 "Анатолий Кулаков" def.helloworld, который по качеству аргумента принимает функцию это имя. +3220.00 3228.00 "Анатолий Кулаков" И все, что оно делает, это возвращает просто строку "hello" вместе с именем, тем аргументом, тем параметром, который принимали в качестве имени. +3228.00 3230.00 "Анатолий Кулаков" Вот такой простенький скриптик. +3230.00 3232.00 "Анатолий Кулаков" Как же нам его заисполнить? +3232.00 3244.00 "Анатолий Кулаков" Ну, прежде всего, можно создать стандартный хост, Application Builder, то есть все, как мы любим, нормальный хост поднимаем, у которого как же сразу регистрируются контейнеры, у которого берутся переменные окружения, все, вот это вот. +3244.00 3254.00 "Анатолий Кулаков" Дальше мы можем указать, наверное, все-таки должны указать, это базовый путь к питоновскому модулю, в котором лежат все питоновские файлы, все питоновские модули, которые мы будем использовать. +3254.00 3270.00 "Анатолий Кулаков" В сервисах мы настраиваем сам Python, сам SysNeq с помощью weavPython метода. Указываем его домашнюю директорию, в которой он будет искать все необходимые питоновские скрипты. +3270.00 3274.00 "Анатолий Кулаков" Указываем, каким образом мы будем доставать Python. +3274.00 3278.00 "Анатолий Кулаков" То есть он сам, вот этот хост, он умеет скачивать Python правильной версией. +3278.00 3284.00 "Анатолий Кулаков" Ему также можно подключить, допустим, поддержку PipInstall, то есть это типа Nuget'а питоновского. +3284.00 3296.00 "Анатолий Кулаков" И он сам сможет инсталлировать необходимые пакеты, которые нужны в рантайме ваш хост, то есть, по сути, в вашу систему. В общем, это тоже сделано все довольно-таки удобно. +3296.00 3312.00 "Анатолий Кулаков" Дальше мы строим хост и после того, как мы сделали BuilderBuild, у нас получился аппликейшн, и у этого аппликейшна у нас уже есть зарегистрированные сервисы. И, например, нам один из самых интересных сервисов, который нас интересует, это IPythonEnvironment. +3312.00 3342.00 "Анатолий Кулаков" У этого IPythonEnvironment мы можем уже через него взаимодействовать с питоновским кодом. Например, мы можем запросить модуль demo, и у этого модуля demo магическим source-генераторским способом появляется метод helloWorld, который мы объявили в питоновском файле, который о чудо принимает строку, уже C# красивую, и возвращает в результате тоже строку, которую мы можем уже в C# консоль, например, вывести. +3342.00 3356.00 "Анатолий Кулаков" Таким интеропом, глядя на C# код, вообще никаким образом не видно, что это какие-то питоновские типы, питоновские взаимодействия, какие-то питоновские интеропы, до тех пор, конечно, пока мы в Type не посмотрим, которые там нам нагенерили. +3356.00 3394.00 "Анатолий Кулаков" А так код довольно гематичный, прекрасно выглядит, прекрасное именование, тут все на месте, все хорошо. Поэтому интероп получается довольно бесшовный, красивый и хороший. Нужно признать, что библиотека довольно функциональная, в ней поддерживается очень много разных фишек, например, какие-то экспериментальные питоновские F3D, которые пытаются отказаться от использования GIL, там тоже уже есть. Есть, безусловно, AsyncSupport, асинхронные методы, даже не методы, а вот этот подход с асинкавэйтом, если C# переночевал во множество других языков, в том числе и в Python. +3394.00 3412.00 "Анатолий Кулаков" Поэтому в Python есть тоже асинк-функции, и генератор настолько прекрасен, что он понимает, что это асинхронные функции, и с таких функций он возвращает нам в C#-обвертки task.at, и вполне из C# можно await-ить питоновские асинхронные функции, что вообще прекрасно. +3412.00 3418.00 "Анатолий Кулаков" Нельзя не упомянуть, что у него есть поддержка Ispire, казалось бы, где Python, а где Ispire. +3418.00 3420.00 "Анатолий Кулаков" Что это технически обозначает? +3420.00 3436.00 "Анатолий Кулаков" Ну, это обозначает в том, что вы можете завязать вот этот питоновский хост, питоновский модуль в виде ispire-овского референса, достаточно вам сделать project reference на тот проект, в котором вы настроили вот эту интеграцию с питоном вместе с Asysnake. +3436.00 3460.00 "Анатолий Кулаков" Дальше, прямо из питона вы можете с помощью переменных среды окружения, например, доставать connection-строки, допустим, если у вас там есть какой-то Postgres вы подключили в Ispire и другим проектом подключили уже питоновскую какую-то lib. Ну так вот, питоновская lib вполне может обратиться к этому Postgres, потому что Ispire пробрасывает все connection-строки к базам данных в переменные окружения. +3460.00 3462.00 "Анатолий Кулаков" Из переменных окружений можно их достать. +3462.00 3478.00 "Анатолий Кулаков" Также Python вполне нормально поддерживает OpenTelemetry и логи, и трейсы, и метрики, поэтому если вы подключите такой проект к Ispire, то в принципе в Ispire-дэшборде вы увидите все метрики, логи, трейсы из питона. +3478.00 3494.00 "Анатолий Кулаков" И вы вполне можете проследить вот эти самые вызовы между сервисами, не только когда сервис обращается к C#-ному сервису, но и когда C#-ный сервис потом пошел к питоновскому сервису. Короче, выглядит как хорошая поддержка Ispire, при этом ничего чисто для Ispire делать не пришлось. +3494.00 3504.00 "Анатолий Кулаков" Пришлось просто использовать переменные окружения и пришлось поддержать стандартные OpenTelemetry, которые в принципе и та технология в принципе в питоне так и с коробки доступна. +3504.00 3510.00 "Анатолий Кулаков" Вот такая поддержка Ispire, но с другой стороны довольно интересный сампл получается. +3510.00 3512.00 "Анатолий Кулаков" Итак, посмотрим же на конкурентов. +3512.00 3514.00 "Анатолий Кулаков" Я уже сегодня упомянул IronPython. +3514.00 3520.00 "Анатолий Кулаков" IronPython - это первая, наверное, такая массовая реализация Python-а по .NET была. +3520.00 3524.00 "Анатолий Кулаков" Выпущена она была Microsoft-ом и базировалась на технологии Dynamic. +3524.00 3536.00 "Анатолий Кулаков" Если ключевое слово Dynamic, которое вы могли увидеть в C#, еще вам чем-то знакомо, то, скорее всего, вы знаете про IronPython. Если не знакомо, то, наверное, даже не имеет смысла больше знакомиться. +3536.00 3540.00 "Анатолий Кулаков" Так вот, IronPython, наверное, можно сказать, что он давно уже мертв. +3540.00 3546.00 "Анатолий Кулаков" Я сам лично наблюдал где-то 3 или 4 реинкарнации и как-то ни одна из них не летит. +3546.00 3548.00 "Анатолий Кулаков" Поэтому довольно мертв. +3548.00 3550.00 "Анатолий Кулаков" Но разница не в том. +3550.00 3552.00 "Анатолий Кулаков" Давайте посмотрим, чем же он отличается. +3552.00 3556.00 "Анатолий Кулаков" Отличается он прежде всего технологиями, которые были использованы. +3556.00 3574.00 "Анатолий Кулаков" В IronPython был немножко другой подход. Там люди сделали свою имплементацию Python-а. То есть они взяли стандартный синтакс из Python, стандартную спеку, сами написали для них парсер, лексер, транслятор и пытались его поддерживать в актуальном состоянии. +3574.00 3578.00 "Анатолий Кулаков" Что получалось довольно плохо, потому что не успевали поддерживать. +3578.00 3582.00 "Анатолий Кулаков" Но преимущество было в том, что он работал чисто в .NET. +3582.00 3586.00 "Анатолий Кулаков" То есть это был Python, который полностью запускался на .NET Runtime. +3586.00 3592.00 "Анатолий Кулаков" Ну, не нужны были ни свои процессы, ни свои слои, какие-то абстракции, никакой интероп, потому что он чисто .NET-овский был. +3592.00 3598.00 "Анатолий Кулаков" То есть это своя имплементация Python-движка от Microsoft. +3598.00 3610.00 "Анатолий Кулаков" Отличается он тем, что там была своя реализация, которая не успевала за стандартной, а у SysNake мы берем стандартный Python и лишь дергаем его через C API. +3610.00 3616.00 "Анатолий Кулаков" И отличается оно тем, что IronPython мертв, а SysNake в принципе жив, цветет и пахнет. +3616.00 3620.00 "Анатолий Кулаков" Есть еще такая библиотека, которая называется Python.NET. +3620.00 3630.00 "Анатолий Кулаков" Вот на Python.NET SysNake он уже более-менее похож. То есть Python.NET точно так же делает обертку вокруг Python C API. +3630.00 3640.00 "Анатолий Кулаков" Это дает ему как раз то самое преимущество, что ему не надо пытаться угнаться за стандартным движком Python, а можно просто брать мейнстримный пакет и все, и радоваться жизни. +3640.00 3648.00 "Анатолий Кулаков" Но у SysNake есть Source Generator, который позволяет сделать красивый интероп и автоматически настроить вот этот вот слой абстракции. +3648.00 3656.00 "Анатолий Кулаков" Поэтому вот SysNake отличается от Python.NET именно как раз вот этим. +3656.00 3664.00 "Анатолий Кулаков" Ну что ж, вот такая вот интересная тулза, мне кажется, вполне жива, вполне интересна, много всего умеет и, надеюсь, найдет своего пользователя. +3664.00 3670.00 "Анатолий Кулаков" И мы получим какие-нибудь еще интересные интеграции, интересные инструменты, которые можно вытаскивать в этот нет. +3670.00 3676.00 "Игорь Лабутин" Это действительно звучит интересно, и если действительно работает прям так бесшовно и прикольно, то классно, классно. +3676.00 3688.00 "Игорь Лабутин" Посмотрим, как это все действительно синтегрируется, может быть, это будет еще одним кусочком, который позволит чуть поближе сдвинуть два разных экосистемы, я бы даже сказал. +3688.00 3690.00 "Игорь Лабутин" Два рантайма. +3690.00 3698.00 "Игорь Лабутин" Как я уже говорил, Espire тоже целится в Python.JS и .NET, так что, может быть, что-то интересное и будет. +3698.00 3700.00 "Анатолий Кулаков" Да, побольше таких интеропов. +3700.00 3702.00 "Игорь Лабутин" Да. +3702.00 3710.00 "Игорь Лабутин" На сегодня, наверное, надо потихонечку заканчивать, у нас есть еще чуть-чуть коротеньких новостей, про которые мы сейчас расскажем. +3710.00 3736.00 "Игорь Лабутин" Автомапер и медиатор, мы говорили, что переходят в режим двойной лицензии, то есть, если вы некоммерческая организация или небольшая организация с доходом меньше, по-моему, 5 миллионов долларов в год, если я правильно помню, или оборотом точнее, то вы можете использовать все еще бесплатную версию, бесплатную лицензию автомапера или медиатора, если вы больше, то нужно платить. +3736.00 3740.00 "Игорь Лабутин" Джимми Богор наконец-таки определился с тем, сколько это все будет стоить. +3740.00 3764.00 "Игорь Лабутин" Соответственно, будет три вида лицензии, стандартная, профессиональная и энтерпрайзная, в зависимости от размера команды. Соответственно, стоит 50-150 и в энтерпрайз-варианте 400 долларов. Получаете вы за это приоритетную поддержку, получаете поддержку всяких разных старых рантаймов, я так понимаю, что без лицензии вы типа на каком-нибудь старом .NET фреймворке запускать уже не сможете, ну или не сможете по лицензионному соглашению. +3764.00 3768.00 "Игорь Лабутин" Так-то вас никто не запретит. +3768.00 3800.00 "Игорь Лабутин" Вот, в ближайшие версии, в которые будут уже под этой новой лицензией, это автомапер 15 и медиатор 13, старый код, который был раньше, прошлые версии, они оставлены, репозитории переименованы в .archive, ну там, автомапер .archive и медиатор .archive, но не удалены, по крайней мере, как это было с Identity-сервером, а наставлены на GitHub, пожалуйста, форкайте и делайте с ними что хотите. Вот, новое, соответственно, это все живет под брендом и новые репозитории живут под брендом Lucky Penny Software. +3800.00 3802.00 "Игорь Лабутин" Вот такие дела. Интересно, +3802.00 3804.00 "Анатолий Кулаков" насколько это продержится? +3804.00 3808.00 "Анатолий Кулаков" Реально ли это будет коммерчески успешный продукт? Чего-то я сильно сомневаюсь. +3808.00 3810.00 "Анатолий Кулаков" Или все-таки он сдастся и бросит +3810.00 3834.00 "Игорь Лабутин" это дело? А, непонятно. Ну, смотри, допустим, его продолжат все использовать бесплатно. Ну, предположим, да? То есть, не то, чтобы он, как это, до этого все и так было бесплатно, да? То есть, не то, чтобы он как-то сильно разорится от того, что ему не будут платить, да? То есть, это же как бы не что-то, где что, как бы ты вложился в эту компанию и теперь живешь только на доход от этой компании, нет? +3834.00 3836.00 "Игорь Лабутин" Я так понимаю, будет приносить топ-деньги? +3836.00 3844.00 "Игорь Лабутин" Ну, хорошо. Подпишется какой-нибудь 2-3, не знаю, крупных заказчика по 400 долларов. +3844.00 3846.00 "Игорь Лабутин" Вот тебе уже 1200 в месяц. +3846.00 3848.00 "Игорь Лабутин" Приятно. +3848.00 3860.00 "Анатолий Кулаков" Ну, насколько мы обсуждали его мотивацию, то у него основная мотивация была в том, что я силы вкладываю, типа, а денег за это не получаю. Ну, да. Вот. И если все будут пользоваться бесплатными инструментами, то ситуация останется та же самая. +3860.00 3872.00 "Анатолий Кулаков" Он силы будет вкладывать, а денег не получит. То есть, скорее всего, он перестанет вкладывать силы и вообще не будет развивать продукты, в том числе и коммерческие. Ну, если, конечно, как ты говоришь, хотя бы пару компаний купят, наверное, у него какая-то мотивация будет. +3872.00 3874.00 "Анатолий Кулаков" Ну, только зачем? +3874.00 3880.00 "Игорь Лабутин" Ну, да. С другой стороны, ну, я, честно говоря, ни автомапером, ни медиатором уже давно не пользуюсь. +3880.00 3886.00 "Игорь Лабутин" Не очень понятно, что там развивать. Ну, кроме как перехода на всякие новые версии Дотнета. +3886.00 3888.00 "Игорь Лабутин" Не знаю. Ну, да, новые версии +3888.00 3890.00 "Анатолий Кулаков" Дотнета. Как минимум, да. +3890.00 3894.00 "Анатолий Кулаков" Да, думаю, это всегда можно то же самое и прикрутить. О, да. +3894.00 3898.00 "Игорь Лабутин" Как автомапер без ИИ работает, я не представляю. +3898.00 3900.00 "Анатолий Кулаков" Он и так глючит иногда. +3900.00 3902.00 "Анатолий Кулаков" Представляешь, так еще будет рандомно менять +3902.00 3904.00 "Игорь Лабутин" пропертии местами. Действительно. +3904.00 3906.00 "Игорь Лабутин" Потом говорит, да, я ошибся. +3906.00 3910.00 "Игорь Лабутин" Надо по-другому. Перезапустите запрос, я там точно правильно сделаю. +3910.00 3916.00 "Анатолий Кулаков" Да, да. Ну, в этом месяце у меня токены кончились, поэтому следующий релиз мы вам можем собрать только в следующем месяце. Типа того. +3916.00 3918.00 "Игорь Лабутин" Ну, такие дела, в общем. Поглядим, посмотрим. +3918.00 3920.00 "Анатолий Кулаков" У меня тоже есть пару ссылочек. +3920.00 3924.00 "Анатолий Кулаков" Во-первых, хотел бы вам рассказать про сервис Scan Source Generator. +3924.00 3926.00 "Анатолий Кулаков" Это инструмент, который прислал наш слушатель. +3926.00 3934.00 "Анатолий Кулаков" И я напомню, что у нас есть почта, и с радостью мы принимаем ваши линки на любые статьи, там инструменты, присылайте всегда. +3934.00 3936.00 "Анатолий Кулаков" Обязательно посмотрим. +3936.00 3938.00 "Анатолий Кулаков" Так вот, прикольная штука. +3938.00 3944.00 "Анатолий Кулаков" Смысл в чем? Когда вы, например, регистрируете в вашем сервис-контейнере, вы регистрируете зависимости. +3944.00 3948.00 "Анатолий Кулаков" И обычно у вас процесс регистрации состоит из таких двух виртуальных частей. +3948.00 3952.00 "Анатолий Кулаков" Во-первых, вы ищете все зависимости, которые вы хотите зарегистрировать. +3952.00 3958.00 "Анатолий Кулаков" А во-вторых, уже регистрируете их в сервис-коллекции. Добавляете там Singleton, Transient и прочее. +3958.00 3962.00 "Анатолий Кулаков" Так вот, хочется остановиться подробнее на первом этапе поиска. +3962.00 3972.00 "Анатолий Кулаков" Вы можете ручками это все глазками искать по всему вашему проекту и каждую строчку убережно добавлять. Но есть такая инструмента, как Скутер. +3972.00 3974.00 "Анатолий Кулаков" Скутер направленно не читается. +3974.00 3984.00 "Анатолий Кулаков" Скутер это такой как раз инструмент, который позволяет вам просканировать в Ocean все ваши библиотечки или какое-то подмножество. Найти те типы, которые вы хотите зарегистрировать. +3984.00 3988.00 "Анатолий Кулаков" Допустим, по интерфейсу, по атрибуту, по имени, неважно как. +3988.00 3990.00 "Анатолий Кулаков" И автоматически их зарегистрировать. +3990.00 3992.00 "Анатолий Кулаков" Удобно? Удобно. +3992.00 4000.00 "Анатолий Кулаков" Во-первых, ты никогда не забудешь то, что у тебя появился какой-то новый тип в твоей сборке и ты забыл его зарегистрировать. +4000.00 4006.00 "Анатолий Кулаков" Скутер это все отсканирует и всегда будет поддерживать актуальность ваших регистраций в самом лучшем виде. +4006.00 4010.00 "Анатолий Кулаков" Но у этого процесса есть накладные расходы. +4010.00 4018.00 "Анатолий Кулаков" Потому что как только приложение поднимается, в ран тайме оно вынуждено проходить, сканировать все сборки и искать там какие-то типы. +4018.00 4020.00 "Анатолий Кулаков" Казалось бы, абсолютно бесполезное действие. +4020.00 4026.00 "Анатолий Кулаков" Зачем это делать в ран тайме, когда мы о всех наших типах знаем во время компиляции, в compile time. +4026.00 4036.00 "Анатолий Кулаков" И плюс у нас есть source-генераторы, с которыми все становится лучше. Ну так вот эта библиотека и эксплуатирует вот эту недоделанную как бы возможность. +4036.00 4060.00 "Анатолий Кулаков" Она позволяет отказаться от использования поиска в ран тайме и использования рефлексии и переложить это на compile time, на source-генерацию. То есть source-генератор вам при компиляции просмотрит всю вашу сборку, найдет все интерфейсы, которые вам нужны, атрибуты, которые вам нужны, и сгенерирует уже для вас регистрации в сервис коллекшене. +4060.00 4066.00 "Анатолий Кулаков" И это прекрасно, потому что мы как всегда при переходе на source-генератор получаем out-compatible. +4066.00 4070.00 "Анатолий Кулаков" То есть теперь наш код полностью совместим с out. +4070.00 4078.00 "Анатолий Кулаков" И плюс еще мы устраняем вот этот шаг performance penalty, когда на старте мы вынуждены сканировать наши сборки. +4078.00 4100.00 "Анатолий Кулаков" Теперь на старте performance идеален, потому что ничего сканировать не нужно. Нужно просто вызвать уже готовый сервис коллекшен с готовыми как бы регистрациями и все. Интерфейс довольно приятен. Атрибуты довольно мощные, то есть с помощью атрибутов вы можете настраивать, а что искать и каким образом регистрировать. +4100.00 4104.00 "Анатолий Кулаков" Естественно, вы можете зарегистрировать instance по интерфейсу. +4104.00 4116.00 "Анатолий Кулаков" Дальше вы можете регистрировать, например, minimal API endpoints, также поддерживаются options типы, также можно evcore entity type configuration регистрировать, сканируя по всем сборкам. +4116.00 4124.00 "Анатолий Кулаков" В общем, довольно все типы, которые обычно я, например, использую в пакетах для регистрации, там поддерживаются. +4124.00 4136.00 "Анатолий Кулаков" Поэтому инструмент довольно мощный, довольно интересный и довольно логичная замена вот этом скрутером, который позволяет это в рантайме нас нагружать какими-то ненужными операциями. +4136.00 4152.00 "Анатолий Кулаков" И еще одна статейка от Эндрилока, которую хотел вам рассказать, но она слишком узкая была, поэтому в основной выпуск нам не попало, но кратко упомянуть ее стоит. Это еще одно введение .NET 10 в секции source-генераторов. +4152.00 4174.00 "Анатолий Кулаков" У source-генераторов до .NET 10 была такая проблема, что очень часто для того, чтобы сделать какую-то генерацию кода, вам необходимо предоставить, как автору генератора, вам необходимо предоставить некий атрибут, который вы навесите над своим классом, и уже тогда source-генератор будет знать, что раз этот атрибут навесили, значит сейчас я чего-нибудь нагенерю. +4174.00 4190.00 "Анатолий Кулаков" Ну вот, например, как в нашем примере, для того, чтобы вот этому сервис-скану нагенерировать необходимые регистрации, нужно повесить сначала атрибутик, который расскажет, а с какими интерфейсами, с какими типами эти регистрации нужно поискать. +4190.00 4220.00 "Анатолий Кулаков" Вот, и это довольно частый use-case, то есть практически большинство source-генераторов так работает. Ну так вот, и у этого подхода, у этой стратегии, по которой работают большинство source-генераторов, есть большая-большая проблема, была большая проблема, это каким образом предоставить вот этот самый атрибут, который все остальные будут использовать, для того, чтобы потом запустить на основании его source-генератор. Эта проблема немножко решилась уже со следующих версий source-генераторов, которые там выходили, предыдущие дотнеты. +4220.00 4228.00 "Анатолий Кулаков" Там у source-генераторов появился специальный хук, который позволяет сделать такой... +4228.00 4232.00 "Анатолий Кулаков" сгенерировать в определенное время атрибут, не анализируя исходники. +4232.00 4244.00 "Анатолий Кулаков" То есть специальный атрибут генерирует и все, и дальше вы можете его использовать. А потом уже запускаются Roslin аналайзеры, передается все дерево, начинают генерироваться исходники, то есть это уже потом происходит. +4244.00 4248.00 "Анатолий Кулаков" Но с этим сгенерированным атрибутом тоже есть небольшие проблемы. +4248.00 4256.00 "Анатолий Кулаков" Обычно его генерируют как internal с определенным namespace, с четко заданным namespace, и складывают его в сборочку. +4256.00 4280.00 "Анатолий Кулаков" Для того, чтобы включать генератор к другой сборочке, там тоже был такой же точно атрибут, но так как он internal, проблем с этим вроде никаких нет, они не пересекаются. Но иногда бывают люди, которые ставят internal-visible-tool для таких сборочек, и тогда уже начинаются конфликты, когда у нас два атрибута, оба internal, оба в одном и том же namespace, но в разных сборках. Получаются конфликты, начинается все конфликтовать. +4280.00 4282.00 "Анатолий Кулаков" Ну так вот, к чему это? +4282.00 4296.00 "Анатолий Кулаков" Так вот, вот эту проблему наконец-таки попытались решить в дотнете 10, не без проблем, но все-таки как-то приблизились довольно мощно к решению такой проблемы с помощью еще одного атрибута, который называется Embedded attribute. +4296.00 4306.00 "Анатолий Кулаков" В общем, тема, как я уже сказал, довольно узкая, не всем она, наверное, интересна, но если вы пишете source-генератор, то Embedded attribute наверняка вам позволит сделать что-то еще более немножко красивым. +4306.00 4308.00 "Анатолий Кулаков" Посмотрите на него. +4308.00 4310.00 "Игорь Лабутин" Да, прикольно. +4310.00 4334.00 "Игорь Лабутин" Ну, а на этом мы на сегодня будем заканчивать. Мы сегодня быстренько посмотрели на Aspire Roadmap на ближайшие как минимум полгодика, погрузились в детали того, как реализован .NET Tool DNx для такого одноразового запуска .NET Tools, выяснили, чем John Skid не то что недоволен, а удивлен в поведении рекордов, и глянули, как можно вызывать бетонный код из .NET. +4334.00 4338.00 "Игорь Лабутин" И на этом, наверное, на сегодня мы будем заканчивать. +4338.00 4350.00 "Анатолий Кулаков" Да, точно будем. В принципе, летние выпуски вам тоже хорошо отдохнуть, хорошо загореть, хорошо набраться новых сил для того, чтобы приступить к работе уже на новых версиях .NET. +4350.00 4354.00 "Анатолий Кулаков" Уже практически ждем, да, скоро-скоро, уже осенью обещают выпуститься. +4354.00 4360.00 "Анатолий Кулаков" А также напоминаем, что нас можно будет найти на .NEXT, и .NEXT состоится в сентябре. +4360.00 4368.00 "Анатолий Кулаков" Проходить он будет долгожданно, наконец, в Питере. Поэтому, если кто хочет пообщаться, увидеться, милости просим на .NEXT. +4368.00 4370.00 "Анатолий Кулаков" Там встретимся. +4370.00 4376.00 "Игорь Лабутин" Все так, слушайте, подписывайтесь, распространяйте, лайкайте и все такое прочее. +4376.00 4378.00 "Игорь Лабутин" Пишите письма, пишите комментарии. +4378.00 4380.00 "Анатолий Кулаков" А на этом все. Всем пока. +4380.00 4382.00 "Анатолий Кулаков" До новых встреч. diff --git a/input/Radio/Transcriptions/RadioDotNet-121.txt b/input/Radio/Transcriptions/RadioDotNet-121.txt new file mode 100644 index 0000000..16ce717 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-121.txt @@ -0,0 +1,392 @@ +0.00 15.08 "Анатолий Кулаков" Здравствуйте дорогие друзья, в эфире Радио Дотнеты выпуск номер 121, в студии постоянный ведущий Анатолий Кулаков. +15.08 18.28 "Игорь Лабутин" И Игорь Лабутин, всем привет. +18.28 41.52 "Анатолий Кулаков" Благодарим за помощь наших прекрасных помогаторов - Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев. +41.52 44.76 "Анатолий Кулаков" Большое спасибо друзья, всем кто нас поддерживает. +44.76 51.32 "Игорь Лабутин" А нас продолжает поддерживать компания Altenar, которая разрабатывает масштабируемые и надежные решения для индустрии спортивных данных. +51.32 59.04 "Игорь Лабутин" В основе большинства продуктов, Dotnet и C#, инженеры работают с высоко нагруженным риел таймом, а их идеи не теряются в десятках согласований. +59.04 64.84 "Игорь Лабутин" Разработка компании международная, можно использовать удобные DE-шки, английские и всё такое прочее. +64.84 71.36 "Игорь Лабутин" Также ребята активно делятся опытом, проводят митапы, выступают с докладами и за их новостями можно следить в телеграм-канале. +71.36 101.00 "Анатолий Кулаков" Я еще хочу напомнить, что скоро грядет знаменательное событие, состоится конференция Dotnext и если вы хотите увидеться то нас можно поймать там, а еще для всех наших бустеров, независимо от уровня, если вы хоть когда-то нас поддерживали, у нас для вас есть подарочки, поэтому если вы придете на конференцию и еще подписаны на нас на бусте, то требуйте свой подарок, вас ждет небольшой сюрприз, но я думаю вам очень понравится. +101.00 109.20 "Игорь Лабутин" Ну, пойдемте теперь к выпуску, у нас есть новости, Майкрософт выпустил превью седьмой для десятого дотнета, мы +109.20 115.20 "Анатолий Кулаков" потихонечку… Майкрософт как-то не перестает, да, вот оно вошло в какие-то стабильные превью и каждый выпуск нам готовят пирожочки. +115.20 132.04 "Игорь Лабутин" Ну, они не такие большие, но регулярность тоже неплохая, насколько я помню, обычно бывает семь или восемь штук превью, потом начинается релиз кандидата где-то в сентябре, уже в октябре, поэтому поглядим, как пойдет, сколько еще превью будет, но давайте как обычно пробежимся по всем разделам, как мы это делаем. +132.04 167.56 "Игорь Лабутин" Начнем с библиотек, в библиотеках совершенно разноплавные изменения, во-первых, поменялась API для процесса StartInfo, там теперь есть метод CreateNewProcessGroup, который позволяет запустить процессы в отдельной процесс-группе, это не просто так сделано, да, все это на винте только, это позволяет посылать сигналы только дочерним процессам, то есть послать Control+C в вот такую процесс-группу и все дочерние процессы в этой процесс-группе его получат, как я понимаю, с гарантией, что не получат родительские, то есть родительские случайно не помрят. +167.56 174.08 "Игорь Лабутин" Ну, наверное, удобно для каких-то, видимо, нишевых сценариев, так скажем, было сделано. +174.08 205.72 "Игорь Лабутин" Дальше, для постквантовой криптографии, про которую мы в прошлый раз рассказывали, появилось некоторое количество улучшений и изменений, для MLDSA подвезли более удобную API, ей стало более удобно пользоваться, легко, появился поддержка HashMLDSA, ну и добавилась штука под названием CompositeMLDSA, это нечто в сторону RSA уже направленное, но пока еще не до конца, как я понимаю, там какие-то пока примитивы завезли. +205.72 222.92 "Игорь Лабутин" JSON Serializer обрел поддержку PipeReader, раньше нужно было, если у вас было PipeReader, с которым нужно было десериализовать что-то в JSON через JSON Serializer, нужно было сначала PipeReader запихнуть в Stream, и только потом в JSON Serializer, теперь можно сразу PipeReader туда запихнуть. +222.92 245.92 "Игорь Лабутин" В нетворкинге, если вы работали с веб-сокетами, то вы наверняка знаете, что нужно было, там всякий буферинг, сборку сообщений из байтового потока, декодирование-раскодирование, всякие кастомные врапперы, все это писать нужно было, для того чтобы интегрироваться со стримами, каналами и прочими более удобными абстракциями. +245.92 257.52 "Игорь Лабутин" Теперь есть штука под названием WebSocketStream, которая как раз таки все это дело делает за вас, и вы просто можете работать с веб-сокетным байтовым потоком, как со стримами, подключать его в нужное место. +257.52 279.24 "Игорь Лабутин" А также, если вы используете в нетворкинге .NET на MacOS, то клиентскую его часть, т.е. HTTP Client и прочие такие штуки, то теперь вам доступен TLS 1.3, потому что они теперь используют нативную Apple-овскую реализацию штуки под названием Network Framework в SSL-стриме и в HTTP-клиенте. +279.24 296.76 "Игорь Лабутин" Ну, соответственно, у вас теперь будут самые последние новинки от Apple в плане TLS, но эта штука подключается, ее нужно явно включить, потому что это довольно серьезное изменение Networking Stack и не факт, что у вас все хорошо заработает. +296.76 310.48 "Игорь Лабутин" Тем более, нет гарантии, что на последних версиях Apple все еще работает TLS 1.1, если вы случайно в вашем продукте или не случайно, а осознательно используете TLS 1.1, но просто так переключаться не стоит, у вас все отвалится. +310.48 311.48 "Игорь Лабутин" Дальше. +311.48 312.48 "Игорь Лабутин" S/P/NOT-Core. +312.48 318.96 "Игорь Лабутин" С S/P/NOT-Core тоже довольно-таки не очень большие точечные изменения. +318.96 327.16 "Игорь Лабутин" Во-первых, можно теперь передать свой делегат в новую опцию под названием ExceptionHandlerOptions.surpriseDiagnosticsCallback. +327.16 342.04 "Игорь Лабутин" Это callback, который будет вызываться, когда middleware получает необработанное исключение, exception handler, и если этот callback вернет true, то это значит, что этот исключение не надо логировать. +342.04 351.40 "Игорь Лабутин" Это нужно, если у вас есть собственная middleware, которая логирует все и вся, то есть вы, например, можете сказать, что такие исключения больше не надо логировать, и так далее. +351.40 360.56 "Игорь Лабутин" И второй момент, что по дефолту вот этот ExceptionHandlerMiddleware, который поставляется во фреймворке, теперь по-другому работает. +360.56 369.08 "Игорь Лабутин" Если исключение было обработано iExceptionHandler, то тогда оно логироваться не будет дополнительно, считается, что вы все и так залогировали, если надо, в ExceptionHandler. +369.08 377.00 "Игорь Лабутин" Для того, чтобы вернуться к прошлому поведению, нужно передать туда callback, который всегда возвращает false, ну и, соответственно, тогда будет старое поведение. +377.00 378.00 "Игорь Лабутин" Дальше. +378.00 411.60 "Игорь Лабутин" Если вы используете авторизацию в S/PanelCore, вот эту стандартную штуку с логинами и всем добром, то раньше, если, например, вы обращались к endpoint, и там в запросе не было нормальных кредов, то тогда вместо того, чтобы возвращать что-то по коду 401 или 403, фреймворк пытался редиректнуться, например, на login, на endpoint/login, чтобы показать пользователю окошечко, что, типа, дорогой залогин. +411.60 426.52 "Игорь Лабутин" Это работает неплохо, если у вас это backend к фронтенду, но если это API, которая дергается к какой-то другой API, каким-то другим backend-сервисом, то, в общем-то, бесполезно редиректоваться на login, потому что там никого не требуется, то есть в стране там тоже сервер. +426.52 445.00 "Игорь Лабутин" И теперь поменяли поведение, если у вас есть API-endpoint, то в этом случае, и к вам пришли без аутентификации, без куки нужной, то тогда будет просто 401, 403, в обычном что-то по респонсии, но, видимо, с проблем-детейлзом, скорее всего. +445.00 447.88 "Игорь Лабутин" А как же определяется, что такое API-endpoint? +447.88 448.88 "Игорь Лабутин" Тут все просто. +448.88 455.48 "Игорь Лабутин" Есть новый интерфейс, называется IAPI-endpoint metadata, и именно по нему определяется, что это именно API-endpoint. +455.48 469.60 "Игорь Лабутин" Для того, чтобы в обычном коде приложения это определить, нужно либо использовать атрибут API-controller, не просто контроллер, а именно API-controller, либо использовать minimal-API, тут все просто minimal-API. +469.60 488.60 "Игорь Лабутин" Если они используют JSON-request-body или пишут JSON в респонсии, считается, что это просто API, а не какой-нибудь там Razor-endpoint или еще что-нибудь, если вы возвращаете typed-result из вашего API-метода, либо если это SignalR. +488.60 494.72 "Игорь Лабутин" Во всех таких случаях больше не будет редиректа на /login, а будет нормальный 401, 403. +494.72 508.48 "Игорь Лабутин" При этом вы можете поменять это поведение, можно запихать свои коллбеки в ивенты под названием redirect-login и redirect-access-denied, и сделать там что хотите. +508.48 514.36 "Игорь Лабутин" Хотите редирект, хотите слогировать, хотите вернуть код ошибки, как угодно, в общем. +514.36 520.20 "Игорь Лабутин" Дальше у нас есть поддержка по scale-authentication, но у нас про это есть отдельная статья, я не буду сейчас задаваться в подробности. +520.20 523.88 "Игорь Лабутин" Дальше поддержка localhost-top-level-domain. +523.88 534.64 "Игорь Лабутин" Согласно RFC 2606, а также RFC 6761, у нас есть специальный домен .localhost-top-level-domain, который по стандарту должен резовываться всегда в localhost, то есть в RFC 27001. +534.64 537.48 "Игорь Лабутин" В принципе, современные браузеры более-менее это делают уже. +537.48 540.28 "Игорь Лабутин" Ну вот, соответственно, Aspire.net Core теперь тоже это делает. +540.28 551.28 "Игорь Лабутин" Сделано это, я подозреваю, ради Aspire, потому что именно в Aspire, по-моему, в прошлый раз или позапрошлый я в новостях каких-то рассказывал, что можно теперь через .localhost обращаться к сервисам. +551.28 556.48 "Игорь Лабутин" Ну вот, видимо, для того, чтобы это можно было сделать, пришлось это сделать в Aspire.net Core, в .net. +556.48 558.84 "Игорь Лабутин" Вот, да, такое работает. +558.84 577.48 "Игорь Лабутин" И дальше тот самый pipereader, который, я сказал, что поддержан теперь для декодинга, в принципе, это все должно работать абсолютно прозрачно, оно все внутри фреймворка это сделано. +577.48 584.80 "Игорь Лабутин" И в обычном коде вы это не должны видеть, и прямо из pipereader, там, кестрилов какого-нибудь, это все будет автоматически декодиться в ваши объекты. +584.80 599.52 "Игорь Лабутин" Но там есть проблема, если вы используете кастомный JSON-конвертор, то он может сломаться на как раз таких вот чтений пайпов, когда он там встречает какую-нибудь коллекцию или массив. +599.52 610.52 "Игорь Лабутин" Там есть workaround, но можно поставить, во-первых, апконтекстовый флажок под названием Microsoft Aspire.net Core Use Stream-Based JSON Parsing, ну и тогда он перестанет pipereader использовать. +610.52 616.80 "Игорь Лабутин" Либо там есть более изощренные способы именно как пофиксить сам конвертор, ну и более правильные на самом деле. +616.80 619.52 "Игорь Лабутин" В статье посмотрите, если вы вдруг такое используете. +619.52 625.80 "Игорь Лабутин" Но и с pipereader понятно, что это должно работать быстрее, потому что не надо оборачивать в лишний промежуточный стрим. +625.80 635.36 "Игорь Лабутин" Для классов рекордов теперь можно использовать совершенно нормальную валидацию, которая тоже использует код генерации и вот это все. +635.36 638.86 "Игорь Лабутин" То есть, в общем, классы рекорд эти работают абсолютно одинаково. +638.86 646.24 "Игорь Лабутин" Пачка импрувментов в Blazor, довольно точечных не буду касаться. +646.24 657.80 "Игорь Лабутин" Обновилась зависимость на OpenAPI.net, это стандартная библиотека от OpenAPI, которая теперь использует версию 2.0. +657.80 664.12 "Игорь Лабутин" Ну и все, Aspire.net Core больше нет ничего такого. +664.12 678.56 "Игорь Лабутин" В EF Core тоже всего лишь один импрувмент, который удостоился включения в релизную статью, это более правильная обработка коллекции, когда вы передаете ее в параметре. +678.56 690.92 "Игорь Лабутин" По сути, у вас есть два способа это сделать, либо вы можете передать массив и в SQL-запросе проверять на вхождение в массив, либо вы можете каждый параметр коллекции передать отдельным параметром в SQL-запрос. +690.92 700.36 "Игорь Лабутин" Вот сейчас дефолтное поведение EF Core будет передавать каждый элемент коллекции отдельным параметром в SQL-запросе, а не большим массивом. +700.36 703.24 "Игорь Лабутин" То есть почему сделано непонятно, но вот теперь такое. +703.24 736.92 "Игорь Лабутин" В MAUI появляется не только performance improvements и bug fixing, но в XAML завезли source-генераторы, т.е. можно включить явно поддержку обработки XAML-и source-генераторами, так что вы будете видеть, что же там получается на самом деле именно на этапе компиляции, а не на этапе какого-то магического шага уже дальше от внутри после компиляции обычных CSS-файлов, и в Media Picker какие-то фичи завезли про EXIF, а дальше все остальное, это performance improvements и все такое прочее. +736.92 767.00 "Игорь Лабутин" В WinForms DarkMod улучшился, давно, кстати, не было ничего про WinForms, но вот над DarkMod'ом они работают, ну и в контейнерах тот самый .dnx-тул, про который мы много рассказывали в прошлый раз, это штука, которая позволяет вам запускать .dnx-тулы, она теперь по дефолту в контейнерах с SDK доступна в пути, т.е. вы можете внутри SDK контейнера запускать .dnx без необходимости прописывать какие-либо пути дополнительные. +767.00 774.68 "Игорь Лабутин" Вот такие у нас новости в седьмом превью, не то, что прям много, не то, что прям супер что-то важное, но есть. +774.68 783.80 "Анатолий Кулаков" Не, ну я бы сказал, что они не то, что важные, но довольно много, в принципе, относительно превью, часто выходящего. +783.80 795.80 "Анатолий Кулаков" В общем, молодцы, что-то стараются, единственное, что хотелось бы, каких-то более глобальных штучек, но, видимо, нас их кормили, нам им больше не дадут, скорее всего, мы будем радоваться экстеншн-мемберами. +795.80 808.84 "Игорь Лабутин" Не, ну, это ты про C# имеешь в виду, про C#, кстати, вообще нет ничего, даже не то, что там, типа, ничего нового, а его даже в релиз-ноутсах нет ни в каком виде. +808.84 815.72 "Анатолий Кулаков" Ну, да-да, ты прав, что для C# там вообще даже ничего пока не завозят в превью, но фреймворк постепенно шлифуют. +815.72 828.64 "Анатолий Кулаков" Ну, хорошо, пойдем к инструментам, немножко еще коснемся, тут тоже интересный анонс, вышел в очередном превью, анонсировали MCP-сервер для Nuget'а, вот, хотелось бы разобраться, что это такое. +828.64 841.60 "Анатолий Кулаков" Мы, к сожалению, так и не добрались с тобой до карточки, которая с MCP-серверами нашими, у нас там есть огромный набор статей про то, что такое MCP-сервер, как его едят, с чем его готовить и распространять и так далее. +841.60 842.60 "Анатолий Кулаков" Ну, там. +842.60 843.60 "Игорь Лабутин" Я надеюсь, что мы когда-нибудь дойдем. +843.60 860.20 "Игорь Лабутин" Я могу сказать, что там не только про MCP, там, в принципе, про то, как там AI, тутнет и вот это все, там, по-моему, более широкая тема у меня с утоги была заявлена в той карточке, но она настолько стала большой, что мы ее пока, да, не можем к ней подступиться нормально, надо будет ее, может, попилить на более мелкие части и таки рассказать. +860.20 862.64 "Анатолий Кулаков" Да, попилить и делегировать еще. +862.64 869.72 "Анатолий Кулаков" Вот, ну, вкратце, для того, чтобы обсудить немножко эту тему, я открою завису тайны, для тех, кто не знает. +869.72 890.08 "Анатолий Кулаков" MCP - это модель-контекст протоколу, и это специальный стандарт, который был разработан для ИИ-агентов, позволяющий безопасно соединять различные внешние дата-сорцы, внешние по отношению к ИИ, дата-сорцы, инструменты, ну, то есть давать ему доступ к каким-то другим источникам информации и инструментам. +890.08 899.88 "Анатолий Кулаков" В общем, протокол довольно примитивный, простой, ничего в нем такого нет, но в общем случае, может быть, именно поэтому он пользуется такой большой популярностью. +899.88 909.64 "Анатолий Кулаков" И позволяет вам подключать различные какие-то провайдеры данных или какие-то возможности, которыми ИИ сам по себе обладать не может. +909.64 923.64 "Анатолий Кулаков" Ну, например, вы можете подключить к нему доступ к вашей базе данных, и он тогда сможет там чего-то делать, искать определенные данные, выполнять запросы, ну и если вы дерзкий, то может даже обновлять какие-то данные в вашей базе. +923.64 934.12 "Анатолий Кулаков" Вы можете дать ему подключение к своему API или доступ к файловой системе, или вообще написать там какую-то кастомную логику, по которой вы хотите, чтобы он работал. +934.12 941.84 "Анатолий Кулаков" В общем, вот такие вот типа плагины для ИИ можно делать с помощью вот этого протокола. +941.84 951.36 "Анатолий Кулаков" Интересная новость состоит в том, что в принципе MCPC-серверы начали поддерживаться как First Class Citizens в Nuget.org-сервере. +951.36 953.04 "Анатолий Кулаков" Что это значит? +953.04 959.56 "Анатолий Кулаков" Это значит, что теперь вы через Nuget.org можете искать все возможные MCPC-сервера, которые только есть. +959.56 980.56 "Анатолий Кулаков" Ну, естественно, вы туда их можете паблишить, после этого их можете искать, и автоматически, так как это все поддерживает стандарт нашего Nuget.org, у них появляется понятное, хорошее версионирование, семантическое версионирование, у них появляются зависимости, у зависимости появляется понятное тоже версионирование и результат конфликтов. +980.56 986.96 "Анатолий Кулаков" И также точно весь наш инструментарий, все наши IDE понимают, каким образом их устанавливать. +986.96 995.88 "Анатолий Кулаков" То есть Visual Studio Code, Visual Studio вполне понимает, как себе оставить MCPC-сервер, настроить его и заставить работать. +995.88 1016.32 "Анатолий Кулаков" Для того, чтобы сделать, например, свой MCPC-сервер вообще не составляет никакого труда, потому что, как всегда, у нас тоже подсвятилось темплейтами, вы создаете темплейт, добавляете какой-то проект, опять же есть инструмент для тестирования удобного MCPC-сервера, паблишите в Nuget и все, и он там готов для того, чтобы распространяться, устанавливаться и работать. +1016.32 1038.68 "Анатолий Кулаков" Вот, все это прилюдия к тому, что вышла главная новость, это первый такой MCPC-сервер от Microsoft, более-менее публичный и полезный, это MCPC Nuget, давайте же как раз на примере вот этого Nuget MCPC-сервера и посмотрим, что это за такое, зачем оно нужно и как может быть использоваться. +1038.68 1063.14 "Анатолий Кулаков" Итак, Nuget MCPC-сервер позволяет вам интегрировать в реальном времени информацию о ваших пакетах, которые установлены в вашем солюшене, а также управлять ими, и это можно делать напрямую в рантайме, допустим, в ваших ие-агентах, которых вы просите помочь развивать конфликты, обновить версии и что-то еще вы там с ними делаете. +1063.14 1085.60 "Анатолий Кулаков" Таким образом, этот сервер, он предоставляет информацию о новых пакетах, нам надо понимать, что в принципе, если мы спросим обычного какого-нибудь чат-бота в интернете, типа какие последние версии, например, того же самого Aspire вы мне поставите, и он вам сообщит ту версию, на которой он обучался, которая была доступна на тот момент, когда он обучался. +1085.60 1103.28 "Анатолий Кулаков" И вот MCP-серверы, это еще один из способов как бы сделать доступ к свежим данным для нашего ие-агента, то есть, чтобы он отвечал вам не теми версиями, которые были доступны, когда он обучался, а текущими, настоящими. +1103.28 1106.56 "Анатолий Кулаков" И вот наш Nuget MCP-сервер как раз и позволяет это сделать. +1106.56 1112.72 "Анатолий Кулаков" Он может сказать, какие на данную секунду прям настоящие актуальные версии, и это в принципе дорогого стоит. +1112.72 1122.40 "Анатолий Кулаков" Также он может рассказать вам про приватные фиды, потому что, опять же, обучался и агент только на публичных фидах. +1122.40 1130.96 "Анатолий Кулаков" А здесь обычно, если, например, в корпоративном рынке вы сидите, то у вас в компании есть приватный фид, в который складываются все ваши пакеты со всеми вашими версиями. +1130.96 1138.68 "Анатолий Кулаков" И вот Nuget-сервер может рассказать, что вот у нас в приватных корпоративных интерпрайс-фидах живут такие-то пакеты с такими-то версиями. +1138.68 1141.20 "Анатолий Кулаков" И это очень хорошо. +1141.20 1150.36 "Анатолий Кулаков" При этом Nuget MCP-сервер позволяет, использует алгоритм Nuget Solving, про который мы рассказывали в одном из наших предыдущих выпусках. +1150.36 1154.16 "Анатолий Кулаков" Это алгоритм, который упрощает автоматический резолв конфликтов. +1154.16 1162.00 "Анатолий Кулаков" Он был разработан в содружестве с Microsoft Research, и у него там есть куча-куча всяких крутых эвристик. +1162.00 1164.24 "Анатолий Кулаков" Если кто пропустил выпуск, обязательно послушайте. +1164.24 1165.84 "Анатолий Кулаков" Интересная была темка. +1165.84 1175.88 "Анатолий Кулаков" Ну так вот, MCP-сервер позволяет вашему агенту правильно очень красиво, четко и быстро резолвить всякие конфликты и зависимости. +1175.88 1192.08 "Анатолий Кулаков" Надо признать, что, наверное, это одна из самых больших проблем, тем более, если мы говорим про новичков и про большие проекты, которые бросают, самая большая проблема - это вот понять, почему какая-то библиотека находится или не находится, или почему версии конфликтуют или какие-нибудь панинг и директы не туда ссылаются. +1192.08 1197.96 "Анатолий Кулаков" То есть это довольно сложная тема, особенно с непривычки, если вы еще на этом собаку не съели. +1197.96 1204.00 "Анатолий Кулаков" Вот этот сервер вместе с агентами, возможно, сделает задачу проще и легче. +1204.00 1215.68 "Анатолий Кулаков" Итак, если мы говорим про текущие возможности, то есть что уже этот MCP-сервер позволяет сделать с агентом вместе. +1215.68 1226.22 "Анатолий Кулаков" Ну, во-первых, он может вам рассказать про то, какие последние версии есть, посоветовать вам установить их в ваш Solution и также разрезолвить конфликты. +1226.22 1229.12 "Анатолий Кулаков" Конфликты на основании тех стратегий, которые я писал выше. +1229.12 1233.48 "Анатолий Кулаков" Но это, в принципе, вы могли сделать и с обычной дотнет-тулзой. +1233.48 1235.56 "Анатолий Кулаков" Просто апдейт и все. +1235.56 1236.92 "Анатолий Кулаков" Дальше немножко интереснее. +1236.92 1243.24 "Анатолий Кулаков" Он умеет находить секьюрити-уязвимости и при этом эти секьюрити-уязвимости закрывать. +1243.24 1256.36 "Анатолий Кулаков" И закрывает он их не просто так, он умеет патчить эти уязвимости таким образом, чтобы пакет, на который вы обновляетесь, содержал минимальную версию, в которой эта уязвимость закрыта. +1256.36 1260.20 "Анатолий Кулаков" Вот это довольно интересная и полезная стратегия. +1260.20 1267.16 "Анатолий Кулаков" То есть он вам не, по сути, не привносит какие-то новые уязвимости, пытаясь скачать самый последний пакет. +1267.16 1274.30 "Анатолий Кулаков" А при этом он понимает, что его главная цель - это закрыть секьюрити-уязвимость и поэтому ставит ближайший пакет, где эта секьюрити-уязвимость закрыта. +1274.30 1278.20 "Анатолий Кулаков" При этом же опять все проверяет на совместимость. +1278.20 1282.40 "Анатолий Кулаков" Следующая стратегия - это стратегия просто обновления версии. +1282.40 1284.64 "Анатолий Кулаков" И здесь стратегия полностью наоборот. +1284.64 1292.84 "Анатолий Кулаков" Она состоит в том, что он обновляет версии пакетов самой максимально совместимой версией, которую найдет в пакетах. +1292.84 1301.48 "Анатолий Кулаков" То есть когда пакеты обновляются, его главная задача - принести больше фич, принести больше возможностей и фиксов в ваше приложение. +1301.48 1305.36 "Анатолий Кулаков" Поэтому он обновляет на максимально возможную пакет. +1305.36 1319.20 "Анатолий Кулаков" И при этом одно из нововведений, которое подчеркивается - он учитывает именно таргет-фреймворк того проекта, для которого он делает, потому что раньше на таргет-фреймворк очень многие инструменты просто забивали. +1319.20 1326.20 "Анатолий Кулаков" Они брали последнюю версию пакетов, вставили ее и не смотрели о том, что ваш таргет-фреймворк в этой версии уже давно не поддерживается. +1326.20 1328.12 "Анатолий Кулаков" С этим тоже было множество конфликтов. +1328.12 1332.60 "Анатолий Кулаков" Интеграция этого MCP-сервера довольно прозрачная. +1332.60 1338.40 "Анатолий Кулаков" Она легко настраивается в Visual Studio, Visual Studio Code и более того в GitHub Coding Agent. +1338.40 1345.84 "Анатолий Кулаков" Никогда мне не приходилось пользоваться GitHub Coding Agent, но это в принципе тоже редактор, наверняка кому-то будет полезно. +1345.84 1349.08 "Анатолий Кулаков" Там тоже это все есть. +1349.08 1351.92 "Анатолий Кулаков" Подключается все довольно прозрачно, настраивается легко. +1351.92 1355.16 "Анатолий Кулаков" Если вам интересно, можете посмотреть статейки. +1355.16 1370.52 "Анатолий Кулаков" Такое интересное проникновение нашего Nuget в IE-сервисы способного помочь вам не только резолвить конфликты, но и более успешно секьюрити патчи накатывать. +1370.52 1389.24 "Анатолий Кулаков" Это должно быть одно из его самых главных преимуществ, потому что секьюрити-дыры находятся очень часто и многие компании чисто сердечно забивают на то, чтобы патчиться вовремя, потому что это требует очень много телодвижений различных. +1389.24 1396.76 "Анатолий Кулаков" Посмотреть на совместимости, подтянуть какие-то зависимости, может быть даже обновить какие-то контракты публичные, которые поломались. +1396.76 1400.08 "Анатолий Кулаков" Все это такие мелкие действия, до которых очень часто не доходят руки. +1400.08 1402.08 "Анатолий Кулаков" На самом деле это очень важный аспект. +1402.08 1416.96 "Анатолий Кулаков" И кажется, что подобная связка и агента и настоящего думающего Nuget MCP сервера, который понимает, как все эти зависимости работают, как с друг другом соотносятся, вот эта связка должна сделать наши продукты немножко более секьюрными. +1416.96 1424.16 "Игорь Лабутин" Да, звучит интересно, хотя, ну, поглядим, сколько туда будут кто что выкладывать. +1424.16 1427.92 "Игорь Лабутин" Опять же, я так понимаю, что есть здесь же два момента. +1427.92 1438.28 "Игорь Лабутин" С одной стороны, это MCP сервер, который позволяет смотреть в Nuget, с другой стороны, это Nuget, который позволяет хостить MCP плагины, или как это сказать, MCP-агенты. +1438.28 1441.24 "Анатолий Кулаков" Ну, MCP сервера, по-моему. +1441.24 1442.24 "Анатолий Кулаков" Да, сервера. +1442.24 1443.24 "Игорь Лабутин" Разные. +1443.24 1444.24 "Игорь Лабутин" Правильно. +1444.24 1449.80 "Игорь Лабутин" То есть, короче, с одной и с другой стороны посмотрим, какая из сторон выстрелит быстрее, раньше, интереснее. +1449.80 1451.16 "Анатолий Кулаков" В общем, поглядим. +1451.16 1464.28 "Анатолий Кулаков" Я сейчас смотрел Nuget, опять же, чем хороша интеграция тем, что у нас теперь появилась Nuget-серчи на темные поиски по всем MCP-серверам, их там буквально штук 40, и большая часть из них это мусор. +1464.28 1471.36 "Анатолий Кулаков" Ну, то есть, пока люди упражняются, самплы пушат и все такое, вообще полезного там мало, но перспективы большие. +1471.36 1475.68 "Игорь Лабутин" Ну, вопрос, насколько удобно именно на Дотнете писать именно сервера. +1475.68 1484.00 "Игорь Лабутин" То есть, туториалов мы видели много, а вот насколько в продакшене это будет, и почему нужно выбирать именно Дотнет, ну, поглядим. +1484.00 1491.36 "Игорь Лабутин" Так, пойдем дальше, дальше у нас Дотнет Эспайр, куда же без него. +1491.36 1513.28 "Игорь Лабутин" В Эспайре вышла версия 9.4, я так понимаю, что мы не дождемся 10-й версии Эспайра, пока не выйдет Дотнет 10-й, чтобы версии были синхронизированы, но тем не менее, 9.4 продолжает традицию, ну, довольно-таки регулярных релизов, и в нем есть некоторое количество интересных вещей. +1513.28 1542.80 "Игорь Лабутин" Первое, наконец-таки, Эспайр Command Line Interface, про который мы говорили в прошлый раз, по-моему, и даже позапрошлый раз, он теперь официально General Available, то есть его можно использовать, при этом там очень забавно, 4 базовых команды, они типа в GA статусе, то есть .NET Espyre, Espyre New, Espyre Add, это, соответственно, создать проект, добавить туда какие-то зависимости, Run, запустить, ну и Config, это проставить какие-то опции, они типа в GA статусе. +1542.80 1558.40 "Игорь Лабутин" Дальше есть Publish команда, которая позволяет запублишить проект куда-нибудь, она в Preview статусе, и еще есть две команды Exec и Deploy, они в Beta статусе, вот, то есть как бы Command Line в целом GA, но часть команд в разных статусах. +1558.40 1568.96 "Игорь Лабутин" Вот, штука эта, это Command Line Tools, написано на Дотнете, скомпилированная в Ahead of Time варианте, то есть она там ни от чего не зависит, сразу бинарно и все такое прочее. +1568.96 1577.04 "Анатолий Кулаков" Наверное, скоро мы дойдем до варианта, когда у каждой подкоманды будет своя версия, несовместимая с предыдущей версией подкоманды и все такое. +1577.04 1597.88 "Игорь Лабутин" Ну вот, да, да, и при запуске одного она будет говорить ай-яй-яй, а, причем хитро, там типа чтобы можно было использовать Exec и Deploy, нужно сначала через Espyre Config Set разрешить использовать бета-команды, то есть сначала GA команды ставишь опцию, что типа можно использовать бета-команды, после чего можно использовать бета-команды, в общем, прекрасная конструкция. +1597.88 1598.88 "Игорь Лабутин" Круто, круто, да. +1598.88 1599.88 "Игорь Лабутин" Нормально. +1599.88 1601.24 "Игорь Лабутин" Значит, это про CLI. +1601.24 1602.24 "Игорь Лабутин" Дальше. +1602.24 1603.24 "Игорь Лабутин" Дэшборд. +1603.24 1616.32 "Игорь Лабутин" В дэшборде все продолжает развиваться, уже сейчас можно на самом деле делать кастомные ресурсы, кастомные команды внутри ресурсов, ну типа там, не знаю, забросить кэши, например, да, мы рассказывали про это. +1616.32 1651.68 "Игорь Лабутин" Можно какие-то именованные урлы, которые будут видимо в дэшборде выглядеть как-то, не знаю, кнопка или урла, на которую можно нажать и вы это, пошлете какой-то либо сигнал в ваш сервис, и даже можно цепляться к ивентам, которые срабатывают на жительном цикле ваших компонентов внутри приложения, но теперь есть 9.4, более лучшая, как там написано, измененная и вообще все переделанная, новый подход, называется интеракшн сервисы. +1651.68 1703.04 "Игорь Лабутин" Они позволяют создать вообще кастомный даже UX для того, чтобы получать ввод от пользователя, и во время разработки, и во время исполнения программы, то есть показывать какие-то уведомления, спрашивать подтверждения, причем UX, когда мы говорим UX, то есть там есть встроенный, там возможность показать список, всякие булевские флажки, чекбоксики насколько я понимаю, ну в смысле булевские то есть, чекбоксики, текстовые инпуты, числовые инпуты, то есть все теперь можно делать очень суперинтерактивно, причем настолько интерактивно, что оно работает и с командлайн интерфейсом, то есть если он понимает, что ему для запуска какой-либо команды нужны какие-то настройки и вы это через интеракшн сервис определили, то при запуске через командлайн у вас тоже это будет все показано, но уже в командлайн режиме. +1703.04 1714.48 "Анатолий Кулаков" То есть весь этот UX, он ни на каком-то визуальном языке, ни на HTML, ни на JavaScript написан, на каком-то декларативном, который интерпретируется каждой оболочкой по-своему. +1714.48 1720.84 "Игорь Лабутин" Да, дашборд показывает UI, а командлайн показывает видимо командлайновые эти самые промпты. +1720.84 1721.84 "Игорь Лабутин" Прикольно. +1721.84 1728.08 "Игорь Лабутин" И на основе этой штуки построена следующая ветча, которая называется built-in prompting for parameters. +1728.08 1729.08 "Игорь Лабутин" Смысл в чем? +1729.08 1736.32 "Игорь Лабутин" То есть если у вас есть продукт, который например для того, чтобы запустить вам нужно туда передать ряд параметров. +1736.32 1746.20 "Игорь Лабутин" Ну не знаю там, внешний урлык каким-нибудь внешним сервисом или там не знаю connection string какой-нибудь очень специфичной базе данных, которые нет в вашем продукте. +1746.20 1749.76 "Игорь Лабутин" Ну в общем что-нибудь внешнее, ну и просто какие-то параметры запуска. +1749.76 1763.80 "Игорь Лабутин" А раньше как это делалось, вы должны были либо тащить в репозитории какой-нибудь там example upsettings.json, либо что-нибудь такое, да, либо какие-то разумные дефолты туда, чтобы поведение продукта было склонируй и просто запусти. +1763.80 1770.80 "Игорь Лабутин" Но иногда это сделать невозможно, иногда вы не можете сделать разумные дефолты и каждый разработчик у себя так и должен что-то прописать свое собственное. +1770.80 1803.64 "Игорь Лабутин" И в этом случае вот теперь вы можете в Aspire продукте, в Aspire окружении задать параметры для ваших сервисов и если вы склонируете и скажете Aspire run, то он использует interaction service и поймет, что ага, вот этому компоненту не хватает такого параметра, такого параметра, все это позволит вам задать и более того позволит сохранить все через user secret в вашем локальном так сказать хранилище, так чтобы это не закоммитилось в репозитории, но при этом эти настройки сохранились, он их будет подтягивать дальше при следующих запусках и все будет работать. +1803.64 1826.88 "Игорь Лабутин" То есть это такое, ну улучшение в каком-то смысле девелоперского экспириенса, когда вы берете какой-нибудь репозиторий из гитхаба, ну из гитлаба, ну чего угодно, короче где вы храните исходники, клонируете к себе, запускаете и он вам говорит, а теперь веди мне url туда, вот url сюда, там не знаю, ты там веди свое имя, там не знаю, кастомизируй как будет называться файлик и вот теперь у тебя продукт запущен. +1826.88 1837.88 "Игорь Лабутин" То есть прям можно, если правильно задать параметры у продукта, он тебя, продукт сам спросит разработчика ввести все нужные параметры, не надо угадывать где они должны быть в конфигурации. +1837.88 1840.44 "Игорь Лабутин" Звучит удобно, сколько будет пользоваться, ну непонятно. +1840.44 1861.88 "Игорь Лабутин" Так, ну естественно куда же без AI, в 9.4 появились две новых интеграции, это GitHub Models и Azure AI Foundry, которые позволяют соответственно использовать всяческие AI модельки, удобно и бесшовно там, типа 10 строчек кода и вы можете уже что-то использовать. +1861.88 1885.32 "Игорь Лабутин" Ну и в Aspire добавили еще одну интеграцию, точнее обновили интеграцию с YARP, ну непонятно насколько там прям именно YARP как таковой, но смысл в том, что вы теперь можете взять любой внешний URL и сказать, что этот URL это тоже External Service и добавить его в, так сказать, модели вашего приложения. +1885.32 1936.12 "Игорь Лабутин" То есть это будет не просто некая строковка там, приходящая из некоих параметров, это прям будет полноценный сервис, который, ну не то чтобы полноценный, Aspire не можете его, естественно, запустить или остановить, потому что это какая-то внешняя сущность, но например вы можете там, не знаю, сказать "Add External Service" и назвать там OpenAI что-нибудь, допустим, забить туда обычный OpenAI URL и, например, потом какому-нибудь вашему backend-приложению сказать, что он With Reference, то есть он зависит от вот этого внешнего URL, и для вот такого внешнего сервиса можно дополнительно там с помощью доп-методов определить там его Health Check и так далее, то есть Aspire будет понимать в каком состоянии ваш внешний URL, ну как бы всего лишь зная URL, ну и возможно какие-то дополнительные информации вокруг него. +1936.12 1941.80 "Игорь Лабутин" В принципе, все, больше в 9.4 ничего нового нет. +1941.80 1945.36 "Анатолий Кулаков" А мажорный 10-го мы, наверное, ждем вместе с дотнетом, +1945.36 1946.36 "Игорь Лабутин" да? +1946.36 1947.36 "Игорь Лабутин" Я думаю, что да. +1947.36 1949.56 "Игорь Лабутин" Ну что-то мне подсказывает, что они выпустят их одновременно. +1949.56 1957.60 "Анатолий Кулаков" Ну, кстати, анонсы dotnet.conf уже есть, даты уже есть, там, по-моему, 11-12 ноября, в общем, в ноябре ждем десяточку. +1957.60 1962.68 "Игорь Лабутин" Да, осталось еще 3 месяца подождать, через 3 месяца все будет. +1962.68 1965.72 "Анатолий Кулаков" Ну да, ну да. +1965.72 1966.72 "Анатолий Кулаков" Погнали дальше. +1966.72 1987.64 "Анатолий Кулаков" Так, сегодня ты уже упомянул POSKEY SUPPORT, в общем, давай с этим разберемся, очень интересная тема, новая, более-менее для дотнота, да и вообще для пользователей как таковых, пользователей интернета и интерактивных приложений не слишком часто, поэтому, я думаю, нам интересно на нее будет посмотреть и как программистам и как пользователям. +1987.64 1990.28 "Анатолий Кулаков" Что же это за чудо такое? +1990.28 2005.56 "Анатолий Кулаков" Это, прежде всего, это стандарт, это стандарт специальный, который нам дает возможность безопасного, беспарольного доступа к аутентификации на веб-сайтах и в ваших приложениях. +2005.56 2013.16 "Анатолий Кулаков" И это очень важная штука, потому что пароли - это самая большая проблема современной безопасности. +2013.16 2026.02 "Анатолий Кулаков" Пароли утекают, пароли ломаются, пароли компрометируются и с ними очень много всего страшного происходит, потому что самая большая дыра при использовании паролей - это человек. +2026.02 2035.52 "Анатолий Кулаков" Человек очень плохо приспособлен к тому, чтобы запоминать рандомные знаки и символы, выдавать их с очень большой точностью и, может быть, иногда даже ротировать. +2035.52 2047.96 "Анатолий Кулаков" В общем, пароли как моральное средство секьюрити уже давно устарело, поэтому человечество бьется уже многие годы в том, как бы их заменить и некоторые подвижки в этом есть. +2047.96 2056.96 "Анатолий Кулаков" Например, если вы возьмете свой телефон или лаптоп с отпечатком пальцев, то очень часто бывает так, что пароли там практически не нужны. +2056.96 2062.44 "Анатолий Кулаков" К телефону вы можете приложить отпечаток, к какому-нибудь своему макбуку вы тоже можете приложить отпечаток пальцев. +2062.44 2071.36 "Анатолий Кулаков" Иногда он вас, конечно, может попросить вспомнить какой-то доменный пароль, просто для того, чтобы вы его не забыли, а телефончик нарисовать какой-нибудь смешной рисуночек на нем. +2071.36 2075.44 "Анатолий Кулаков" В общем, и все это, если вы не замечали, не вводя пароли. +2075.44 2081.40 "Анатолий Кулаков" В большинстве случаев, не вводя пароли, но этих случаев довольно много и это довольно удобно. +2081.40 2085.16 "Анатолий Кулаков" Когда вы берете телефон, он вам разблокируется по вашему отпечатку пальцев. +2085.16 2086.16 "Анатолий Кулаков" Это очень удобно. +2086.16 2090.80 "Анатолий Кулаков" Вот, хотелось бы, чтобы таких моментов в нашей жизни было больше. +2090.80 2104.36 "Анатолий Кулаков" Чтобы не только ваш телефон разблокировался, но и вы на сайт, зашли бы на сайт почитать почту, вот почему вы должны вводить какой-то пароль, почему в этой почте не хватает вашего отпечатка пальцев или там зашли на какой-нибудь форум. +2104.36 2110.64 "Анатолий Кулаков" Опять же, отпечаток пальцев - это все, что нужно, для того, чтобы вас заинтересовать, почему какой-то сторонний форум этого не понимает. +2110.64 2127.56 "Анатолий Кулаков" Ну, так вот, как раз этот стандарт, он и призван научить всех, кто захочет научиться, научить логиниться с помощью вот таких вот различных биометрических или хардварных устройств, которые не содержат в себе никакого пароля. +2127.56 2133.32 "Анатолий Кулаков" Соответственно, если нет пароля, у вас ничего не потеряется, ничего не взломается, ничего не закомпрометируется. +2133.32 2135.60 "Анатолий Кулаков" И вам не надо будет ничего помнить. +2135.60 2137.88 "Анатолий Кулаков" В общем, отсутствие пароля - это хорошо. +2137.88 2142.04 "Анатолий Кулаков" И этот способ считается более безопасным, чем способ с паролями. +2142.04 2156.20 "Анатолий Кулаков" В нашей статье, в принципе, вы могли бы подобную технику, подобный протокол, способ слышать еще под именами Web Authentication или FIDO, или, вон же, PASKY. +2156.20 2162.16 "Анатолий Кулаков" Все это абсолютно разные вещи, но на том уровне, на котором рассматриваем мы, можно считать это одно и то же. +2162.16 2164.12 "Анатолий Кулаков" То есть, это вот этот протокол, это вот эта техника. +2164.12 2177.24 "Анатолий Кулаков" Итак, новость состоит как раз в том, что возможность сделать PASKY была добавлена в SPNadCore Identity и в .NET 10 Preview 6. +2177.24 2190.24 "Анатолий Кулаков" На данный момент, вот мы сейчас рассмотрим, как она реализована, что там интересного есть, но надо понимать, что, как уже было сказано выше, там у нас все осталось еще 3 месяца до официального релиза и, естественно, все может поменяться. +2190.24 2208.32 "Анатолий Кулаков" Мы об этом не раз убеждались, не то, что фичи менялись, а в том, что они даже отменялись или переносились, поэтому сейчас мы сделаем большими мазками такой обзор, чтобы все понимали, что это, но в общем случае смотрите, что будет к релизу, все может еще измениться. +2208.32 2212.72 "Анатолий Кулаков" Ну, естественно, мы в наших выпусках об этом обязательно скажем, если это произойдет. +2212.72 2232.00 "Анатолий Кулаков" Итак, текущая версия, которая у нас есть сейчас в Preview, она не заменяет полностью пароли, она все еще требует, чтобы пользователь завел пароль при первой регистрации, но после того, как он зарегистрировался, он сможет добавить паски и паролем больше никогда не пользоваться. +2232.00 2261.44 "Анатолий Кулаков" Скорее всего, пароль подразумевается, что нужен для того, чтобы аварийно как-то восстановить доступ к своей системе, потому что паски непосредственно привязаны к устройству, которое предоставило ту или иную биометрическую или криптографическую информацию, поэтому пароль как такое, средство бэкапа пока все еще сохраняется, но в общем случае философия паски заключается в том, что никаких паролей никогда существовать не должно и постепенно индустрия к этому движется, но, наверное, пока еще недостаточно быстро, недостаточно додвигалась. +2261.44 2269.76 "Анатолий Кулаков" Так вот, здесь еще нужно сказать о реализации. +2269.76 2331.28 "Анатолий Кулаков" Данная реализация, которая у нас есть на текущий момент, она не предоставляет какой-то отдельной библиотеки или пространства имен для универсального способа веб-аутентификации или FIDO, или PASKIA, нет, это напрямую прям сильно-сильно вшитое в ASP.NET Core Identity штуковина, которую вряд ли вам получится просто так переиспользовать вне процесса аутентификации, но если вы хотите вдруг настоящую библиотеку с полноценными фичами, которые реализуют веб-аутентификацию, то существует на GitHub библиотека, она называется FIDO2.NET LIBRARY и поддерживает .NET начиная с восьмой версии и выше, и она полноценная фича библиотека с всеми алгоритмами, проверками, фичами, которые там только есть. +2331.28 2339.04 "Анатолий Кулаков" В общем, очень мощная штука, поэтому если вдруг она вам нужна просто так, оторвана для своих собственных алгоритмов, для своих собственных входов, есть отдельная библиотека. +2339.04 2344.08 "Анатолий Кулаков" В общем, а мы сейчас обсуждаем то, что Microsoft пытается встроить в свой Core Identity. +2344.08 2349.04 "Анатолий Кулаков" Итак, чтобы попробовать, у нас есть Blazor Template. +2349.04 2358.56 "Анатолий Кулаков" Пока это такая возможность есть только для Blazor Template, но мы побольше с вами разберемся, как она работает и поймем, что в принципе прикрутить ее несложно для любой UI. +2358.56 2371.48 "Анатолий Кулаков" В общем, но для начала можно сделать Blazor приложение из .NET утилиты, здесь важно указать в параметрах создания шаблона индивидуальную идентификацию так называемую. +2371.48 2384.08 "Анатолий Кулаков" Дальше приложение готово к запуску, вы можете его запустить, зарегистрировать пользователя, как обычно, и после регистрации необходимо пройти на страницу настройки аккаунта. +2384.08 2401.24 "Анатолий Кулаков" И в настройке аккаунта там появилась уже новая секция, которая называется как раз таки "Паски", а если вы щелкните на кнопочки "добавить новые паски", то начинает происходить наше чудо, наше создание самого паския. +2401.24 2402.64 "Анатолий Кулаков" Что же это такое? +2402.64 2405.96 "Анатолий Кулаков" Прежде всего каждый пользователь должен сначала создать паски. +2405.96 2411.92 "Анатолий Кулаков" Как только вы нажимаете на кнопочку "создать паски", у вас открывается нативное диалоговое окно в браузере. +2411.92 2416.24 "Анатолий Кулаков" Оно полностью зависит от того девайса, на котором вы сейчас упражняетесь. +2416.24 2435.44 "Анатолий Кулаков" Например, для Windows это может открыться стандартное Windows Hello диалоговое окно, которое позволит вам, например, с помощью видеокамеры на вашем ноутбуке снять ваше лицо и с помощью Face Recognition сгенерить некий слепок, или может быть даже ввести пин-код. +2435.44 2443.60 "Анатолий Кулаков" Если вы будете на мобильном устройстве, там у вас будет стандартный отпечаток пальца, или точно такой же Face Recognition, или такой же пин-код. +2443.60 2449.52 "Анатолий Кулаков" В общем, полностью зависит от вашего устройства, что в этот момент произойдет. +2449.52 2465.64 "Анатолий Кулаков" То есть откроется какое-то окошко, в котором вы должны доказать, что вы - это вы, и задача подтверждения вас как личности, то есть по сути аутентификации, она полностью ложится на операционную систему и на то устройство, которым вы сейчас пользуетесь. +2465.64 2470.76 "Анатолий Кулаков" В принципе уже хорошо, но есть дополнительный бонус. +2470.76 2480.36 "Анатолий Кулаков" Допустим, у вас есть компьютер, но на нем нет камеры, или допустим вы хотите воспользоваться отпечатком пальца, для того чтобы залогиниться на какой-то сайт. +2480.36 2484.36 "Анатолий Кулаков" Здесь в дело вступает Cross-Device Sign. +2484.36 2495.96 "Анатолий Кулаков" Это специальный протокол, который позволяет вам использовать другие устройства для подтверждения вашей личности, а не то устройство, на котором происходит непосредственно вход в систему. +2495.96 2512.64 "Анатолий Кулаков" То есть если вы на ноутбуке и хотите воспользоваться отпечатком пальца, вы вполне можете взять телефон, который лежит рядом и у которого есть специальные сенсоры для снятия биометрии отпечатка пальца, там прислонить палец и вас залогинит на компьютере, что очень-очень удобно. +2512.64 2523.48 "Анатолий Кулаков" Таким же устройством может выступать не только телефон, но и допустим какой-то крипто токен, который там у вас валяется, или внешний отпечаток пальца, или внешний 3D сканер лица, или может быть еще что-то там. +2523.48 2531.16 "Анатолий Кулаков" Все что угодно, любой внешний девайс, который у вас каким-то образом подключен к вашему компьютеру, связан с вашим компьютером. +2531.16 2535.80 "Анатолий Кулаков" Так вот, после того, как вы создали паски, что происходит дальше? +2535.80 2541.04 "Анатолий Кулаков" Дальше ваше приложение берет этот паски и сохраняет его на вашем устройстве. +2541.04 2548.80 "Анатолий Кулаков" Блейзер-приложение, то, которое мы создали на дотнете, в этот момент спросит вас о том, а как вы хотите назвать ваш паски. +2548.80 2557.76 "Анатолий Кулаков" В общем, назвать вы можете как угодно, это чисто такое описательное название для пользователя, чтобы он не запутывался, потому что у него может быть несколько паски. +2557.76 2579.16 "Анатолий Кулаков" Вы можете добавить несколько паски, потому что на один и тот же сайт, допустим, вы можете логиниться разными способами, когда-нибудь по отпечатку пальцев, когда-нибудь допустим по пин-коду, когда-нибудь по секьюрити токену, поэтому вы можете добавить несколько паски, более того, вы их можете переименовать, то есть дать им различные описания, или можете удалять, управлять им полностью какими-то независимыми ключами. +2579.16 2585.24 "Анатолий Кулаков" Вот, это процесс, который как раз создает вам вот эти ключи. +2585.24 2589.72 "Анатолий Кулаков" Как же у нас теперь происходит вход в пользователя? +2589.72 2590.72 "Анатолий Кулаков" Логин. +2590.72 2605.80 "Анатолий Кулаков" Ну, для того, чтобы это проверить, вам нужно сначала разлогиниться, далее заходим на страничку с логином, но при этом не вводим ни юзернейм, ни пасворт, а нам необходимо кликнуть на маленькую ссылочку, которая внизу, которая называется "Логин в паски". +2605.80 2611.32 "Анатолий Кулаков" Как только мы на эту ссылочку кликаем, то браузер снова запускает нам нативное окно. +2611.32 2617.64 "Анатолий Кулаков" И в этом нативном окне мы должны выбрать, какой ключ мы будем использовать для того, чтобы залогиниться. +2617.64 2625.20 "Анатолий Кулаков" И снова, в зависимости от вашего девайса, у вас возникнет окно, которое попросит вас подтвердить, что вы - это вы. +2625.20 2630.44 "Анатолий Кулаков" Ну, например, в Windows Hello это Face Recognition, в телефоне это отпечаток пальца и так далее. +2630.44 2642.20 "Анатолий Кулаков" И как только вы подтвердите вашу идентичность, то вы будете немедленно залогинены на сайт, не вводя никаких юзернеймов, паролей, ничего вот этого больше вводиться не должно. +2642.20 2666.96 "Анатолий Кулаков" В общем, и вот такая немудренная схема, она в принципе может быть реализована не только сайтами, но абсолютно любыми приложениями, там, десктопными приложениями, мобильными приложениями, ну, наверное, в приложениях мы давно могли такое сделать, потому что там есть нативная интеграция со всеми железками, которые мы обладаем, со всей биометрией, а вот веб-сайты были более-менее лишены такой возможности. +2666.96 2682.28 "Анатолий Кулаков" И самая главная заслуга, наверное, этого протокола это в том, что они дают очень хороший, понятный протокол на уровне браузера, на уровне библиотек вокруг, для того, чтобы синтегрировать веб-сайты со способом входа без парольным. +2682.28 2687.46 "Анатолий Кулаков" Поэтому любые веб-сайты, которые желают, которые вы делаете, могут воспользоваться такой штукой. +2687.46 2691.76 "Анатолий Кулаков" Давайте же теперь посмотрим, а что с точки зрения разработчиков происходит под капотом. +2691.76 2696.52 "Анатолий Кулаков" Итак, для разработчиков у нас есть те же самые два процесса. +2696.52 2700.40 "Анатолий Кулаков" Это создание ключа и логин с помощью этого ключа. +2700.40 2701.40 "Анатолий Кулаков" Как происходит создание? +2701.40 2712.88 "Анатолий Кулаков" Для того, чтобы создать ключ, UI'ка, в нашем случае это был браузер, должна сначала запросить некие опции у бэкэнда, опции, с которыми она будет создавать этот ключ. +2712.88 2721.46 "Анатолий Кулаков" Опции довольно простые, а это, например, они могут включать в себя юзер-айди, юзер-нейм, юзер-дисплей-нейм. +2721.46 2726.44 "Анатолий Кулаков" В общем, опции немножко похожи на состав JVT-токена, если вы видели. +2726.44 2732.84 "Анатолий Кулаков" В принципе, вот такой, с тряпами JVT-токен, то есть куча каких-то атрибутов, которые могут быть нам полезны в последующем. +2732.84 2738.68 "Анатолий Кулаков" В общем, дальше у нас есть под это все стандартные классы, естественно, завезли. +2738.68 2758.36 "Анатолий Кулаков" И самый главный класс, наверное, самый главный метод, который у нас появился, это в Seegan Manager стандартном, метод, который называется MakePathKeyCreationOptions, то есть вы ему передаете вот это аргументы, и он вам создает те самые опции, которые необходимы для создания вот этого ключа. +2758.36 2768.88 "Анатолий Кулаков" Эти опции возвращаются к UIKey, UIKey в это время просит браузер создать, создать креденшалы с вот этими опциями. +2768.88 2778.06 "Анатолий Кулаков" UIKey запускает вот этот диалог нативный со всякими face recognition и после этого возвращает нам уже непосредственно креденшалы. +2778.06 2786.78 "Анатолий Кулаков" После того, как креденшалы были Blazor-ом приняты, мы их отправляем снова на сервер, и на сервере они сохраняются. +2786.78 2793.32 "Анатолий Кулаков" Для того, чтобы сервер их сохранил, у Seegan Manager есть несколько вспомогательных методов. +2793.32 2805.84 "Анатолий Кулаков" Один из самых интересных это PerformPathKeyAtStation, то есть это метод, который запускается для того, чтобы проверить, что те креденшалы, которые были созданы, они валидны и вообще могут быть сохранены, и соответствовать тем опциям, которые мы просили вообще. +2805.84 2822.04 "Анатолий Кулаков" В общем, если они валидны и все хорошо, то у UserManager есть специальный метод SetPathKey, который принимает именно тот PathKey, который нам прислала UI-ка, и пользователя, и он связывает данного пользователя с вот этим ключом. +2822.04 2825.00 "Анатолий Кулаков" Связывает - это значит записывает в базу данных в этот момент. +2825.00 2836.02 "Анатолий Кулаков" У нас в базе данных появляется новая табличка, которая называется ISPNetUserPathKeys, она довольно простая, там записывается связка пользователей, как раз тот PathKey, который нам передали. +2836.02 2848.08 "Анатолий Кулаков" И в нашем случае, после того, как мы записали уже PathKey в базу, мы редиректируем непосредственно пользователя на страничку переименования, то есть, чтобы он задал правильное имя для этого ключа, который мы только что сохранили. +2848.08 2851.80 "Анатолий Кулаков" Как вы видите, здесь нет никакой специфики Blazor. +2851.80 2861.16 "Анатолий Кулаков" Все вот эти методы, они полностью доступны на бэкэнде, и их может вызвать абсолютно любой WebAPI с абсолютно любой UI-ки. +2861.16 2868.92 "Анатолий Кулаков" Поэтому Blazor здесь был приведен просто, наверное, потому что легче всего и быстрее всего было к нему все эти функциональности добавить. +2868.92 2873.36 "Анатолий Кулаков" Процедура логина выглядит еще проще. +2873.36 2879.88 "Анатолий Кулаков" Для того, чтобы UI-ка смогла залогинить пользователя, она точно так же должна сначала запросить опции, с которыми она будет логинить. +2879.88 2890.00 "Анатолий Кулаков" Дальше у бэкэнда есть в Second Manager конфигура по SkiRequestOptions метод, который эти самые опции как раз и генерирует и создает. +2890.00 2894.60 "Анатолий Кулаков" UI-ка просит браузер залогинить данного пользователя с этими опциями. +2894.60 2903.84 "Анатолий Кулаков" Браузер, если успешно залогинил пользователя, возвращает UI-ки креденшалы и эти креденшалы успешно отправляются на бэкэнд. +2903.84 2908.72 "Анатолий Кулаков" В результате этой отправки пользователь становится залогиненным в системе. +2908.72 2911.36 "Анатолий Кулаков" В принципе, процесс довольно простой. +2911.36 2918.16 "Анатолий Кулаков" То есть создание какой-то связки креденшалов, какого-то паскея и потом его последующее использование. +2918.16 2927.24 "Анатолий Кулаков" В общем, всю основную работу, то есть биометрию, связывание с пользователем, проверку самого пользователя берет на себя операционная система. +2927.24 2930.52 "Анатолий Кулаков" И, в принципе, во всех современных операционных системах это уже есть. +2930.52 2931.52 "Анатолий Кулаков" Это уже встроено. +2931.52 2941.80 "Анатолий Кулаков" Осталось просто дать доступ к этой встроенной и отложенной системе всем веб-сайтам, что, собственно, и делает паски, Web Authentication и фида. +2941.80 2946.32 "Анатолий Кулаков" В общем, вот у нас появляется такой интересный новый инструмент. +2946.32 2949.84 "Анатолий Кулаков" Не только как у разработчиков, но, в принципе, как и у пользователей тоже. +2949.84 2956.72 "Анатолий Кулаков" Потому что я пока не знаю ни одного веб-сайта, который бы это использовал, но, надеюсь, в будущем их будет появляться больше и больше. +2956.72 2963.96 "Анатолий Кулаков" Поэтому будем ждать, будем смотреть, а для того, чтобы они появлялись, нам как разработчикам необходимо немножко поразрабатывать. +2963.96 2971.04 "Анатолий Кулаков" Поэтому пробуйте, применяйте в своих приложениях, заносите в свои сервер-сервисы, тестируйте на проде, ну и рассказывайте, насколько все летит. +2971.04 2978.52 "Игорь Лабутин" Мне, кстати, кажется, что мне то ли GitHub, то ли кто-то из вот таких вот сервисов предлагал уже. +2978.52 2983.56 "Игорь Лабутин" А давай, говорят, паскей заявить им, что ты тут логинишься странными способами. +2983.56 2985.04 "Игорь Лабутин" Но я пока отказывался. +2985.04 2987.84 "Игорь Лабутин" Короче, у меня 2 или 3 сайта какие-то предлагали паскей. +2987.84 2989.48 "Игорь Лабутин" Надо будет попробовать. +2989.48 3000.40 "Анатолий Кулаков" Да, мне тоже кажется, что GitHub предлагал, но тоже я как-то это игнорировал чудо, потому что не было еще понимания, как эти паски передаются между устройствами. +3000.40 3006.00 "Анатолий Кулаков" То есть, если я на одном телефоне ввел свои отпечаток пальцев, как мне потом с ноутбука зайти на тот же самый GitHub? +3006.00 3007.00 "Игорь Лабутин" Ну, телефоном. +3007.00 3013.56 "Анатолий Кулаков" Ну, наверное, да, но если у меня ноутбук не подключен к телефону, а нет там разных фильмов, допустим. +3013.56 3014.56 "Анатолий Кулаков" Так нет. +3014.56 3029.60 "Игорь Лабутин" Я так понимаю, что это как-то делает, ну, то есть, в общем, вот эту механику я пока не очень понимаю, но надо разобраться будет, кто кому еще раз передает, потому что ты, конечно, рассказал, но мне кажется, что там на слух это так сложно понять. +3029.60 3036.24 "Игорь Лабутин" То есть, я вот, ну, я не пытался еще разобраться, надо будет понять и посмотреть. +3036.24 3040.56 "Анатолий Кулаков" Ну, в общем, да, будем пробовать, будем смотреть, набивать шишки. +3040.56 3044.64 "Анатолий Кулаков" Я думаю, что технология довольно перспективная, потому что пароли реально уже задолбали везде. +3044.64 3049.68 "Игорь Лабутин" Ну, парольный менеджер спасет, мне кажется. +3049.68 3051.32 "Игорь Лабутин" Ладно, давай пойдем дальше. +3051.32 3056.88 "Игорь Лабутин" Дальше у нас есть статья Джона Скита, продолжение истории про рекорды. +3056.88 3076.24 "Игорь Лабутин" Напомню, что в прошлый раз мы рассказывали про его статью, где он пытался модифицировать рекорды с помощью ключевого условия WIT и удивлялся, что у него не пересчитываются некоторые свойства, которые инициализировались из, ну, параметров рекордов, грубо говоря, то есть он менял параметры через WIT, а свойства не модифицировались. +3076.24 3095.88 "Игорь Лабутин" Ну и его, значит, вот этот пост как-то пообсуждали и на Reddit, и еще где-то, и, в общем, пришел Эрик Либерт, который, я так понимаю, один из, ну, не то что тех, кто дизайнил эту фичу, он, по-моему, уже особо не относился к дизайну тут на это никак, в момент, когда дизайнили рекорды и WIT. +3095.88 3105.12 "Игорь Лабутин" Тем не менее, он сказал, что в его понимании WIT делает полную копию рекорда, изменяя только те значения, которые ты явно указал. +3105.12 3114.40 "Игорь Лабутин" Ну, как бы, и поэтому поведение, которое описывал Джон Скит, вроде как, ожидаемое, что свойство, которое ты не указал, оно не меняется. +3114.40 3125.76 "Игорь Лабутин" Но, с другой стороны, Джон Скит говорил, что, ну, я понимал так, что мы не меняем свойства, а мы создаем новый рекорд с измененными параметрами. +3125.76 3127.76 "Игорь Лабутин" И типа тогда свойство должно пересчитаться. +3127.76 3137.00 "Игорь Лабутин" Как бы, и то, и то версия, ну, так скажем, верна, но оказалась вернее та, которая всё-таки Эрика Липперта, но и она же в майкрософтской документации описана. +3137.00 3152.56 "Игорь Лабутин" И в целом, как бы, ну и окей, как написал в прошлой статье Скит, как бы, ладно, надо считать внимательно документацию, возникает вопрос, а как можно не попасться в это дело ещё разок, и он написал такие, просто аналайзеры. +3152.56 3156.72 "Игорь Лабутин" Я говорил тогда, что непонятно, будет он писать или нет, но он их написал. +3156.72 3169.32 "Игорь Лабутин" Сначала он попробовал обойтись одним, он прекрасно работал, но проблема с одним аналайзером в том, что он работает только в, когда у вас и рекорд, и код, который его пытается модифицировать через Viz, находится в одном проекте. +3169.32 3180.32 "Игорь Лабутин" Если же одним из разных проектов уже не работает, потому что нужной метаданных нету при анализе, поэтому пришлось писать два анализатора. +3180.32 3210.88 "Игорь Лабутин" В итоге они уфубликованы в Nugeti.johnskit.roslynanalyzers, пока их только два этих, возможно, будет ещё, но для начала, значит, что нужно сделать, не то, что сделать, если вы объявляете рекорд, напомню, что там объявлялся рекорд number, у которого был параметр value, ну да, параметр по сути параметра реконструктора, и внутри определялось свойство even, которое считалось один раз при ничётной или нечётной value. +3210.88 3222.88 "Игорь Лабутин" И на такой рекорд аналайзер выдаёт warning про то, что вообще-то вы параметры используете внутри вычисления какой-то инициализации какого-то другого свойства. +3222.88 3228.88 "Игорь Лабутин" Это типа так нельзя, нужно, чтобы вы value анонсировали специальным атрибутом dangerous target. +3228.88 3281.68 "Игорь Лабутин" Ну, хорошо, определяем такой атрибут, он может быть где угодно, в каком угодно namespace, аннотируем параметр, первый анализатор успокаивается, зато если мы теперь хоть где-нибудь напишем вот этот вот instance этого рекорда with и дальше value присвоить какое-то другое значение, то есть мы меняем основной параметр этого рекорда, не меняя, соответственно, вычислимые чётности, то сработает второй анализатор, который скажет, ай-ай-ай, ты используешь, значит, with с параметром, который аннотирован с помощью атрибута danger, и, значит, надо либо поправить так, чтобы он не использовал его в инициализаторе, как мы говорили, то есть, например, сделать, ну, вычислимые свойства, которые просто она get возвращает, каждый раз считает, либо, соответственно, избавиться от инициализации, ну и после этого можно убирать все эти атрибуты про danger target, и всё становится хорошо. +3281.68 3403.92 "Игорь Лабутин" Интересный подход, на самом деле, с двумя анализаторами, я в основном ради этого как раз-таки ту статичку взял, ну, чтобы закончить уже историю, что всё, скид разобрался, он говорит, что он попробовал эти анализаторы натравить на свою кодовую базу, ну, естественно, он понял, что одиночный анализатор не работает, пришлось написать два, написал два, натравил на кодовую базу и выяснил, что на самом деле та проблема, с которой он столкнулся и которую он описывал, ну, по факту встречается типа всего лишь в нескольких местах в его коде, и в большинстве мест она тривиально исправляется на вот те самые вычислимые свойства, и только в паре мест, где там были очень большие классы, ну, классы, типа там контекст какой-то, там пришлось сделать магический трюк с тем, чтобы рекорд убрать во внутренний, сделать его внутренним, внутри класса, а из класса доступаться к этому рекорду снаружи, так чтобы этот класс не мог пересоздать свит, не перевычислив нужные свойства, ну, в общем, все оказалось не так страшно, как было, и здесь скорее эта статья хороший пример того, как можно подходить к разработке анализаторов, то есть если вы думаете, что у вас есть какая-то проблема, что вот вы там, нельзя использовать какую-то конструкцию, далеко не факт, что вам хватит одного анализатора, чтобы эту конструкцию правильно разрулить, ну, разрулить и найти проблему, ну, правильно отрепортить эту проблему, иногда вам придется писать два анализатора, первый, который скажет, что вы недоразметили нужные метаданными, а второй, который уже на основе нужных метаданных проанализирует ваш код, это, наверное, не самая тривиальная мысль для разработчиков, именно анализаторов, потому что, ну, вот у меня была в голове ментальная модель, что ну че, мы берем весь код, анализируем и одним анализатором все говорим, ну, для какой-то одной проблемы, а нет, не всегда так получается, ну, вернее, как технический анализатор, то может быть один, да, это, как проект, он один, но он должен диагностировать несколько, репортить несколько диагностик и друг от друга не зависит. +3403.92 3417.08 "Анатолий Кулаков" Слушай, ну, мне кажется, довольно странный вывод, что он не нашел ничего страшного, потому что если он нашел реальные баги с помощью своих анализаторов, то, наверное, значит, уже хорошие и полезные анализаторы. +3417.08 3426.44 "Игорь Лабутин" Не, не, анализаторы полезные и страшные имелось в виду, что из первой статьи, ну, из его каких-то общих соображений казалось, что таких проблем в коде будет просто огромное количество. +3426.44 3430.40 "Игорь Лабутин" То есть их было, они, конечно, важные, все нормально, но их немного. +3430.40 3435.84 "Игорь Лабутин" Вот, то есть проблема не такая, как бы, масштабная, что называется. +3435.84 3438.96 "Игорь Лабутин" Хотя понятно, что даже один баг - это уже проблема. +3438.96 3442.40 "Анатолий Кулаков" Ну, да-да, смотря в каком месте, это тоже может быть большая проблема. +3442.40 3458.72 "Анатолий Кулаков" Я бы, знаешь, больше про то, что я не думал, что кто-то вообще использует рекорды с Viva для начала, а если он их использует, и притом настолько массово использует, что в них есть вот этот баг, ну, прям это вообще и редкость, и большой сложный баг тогда получается. +3458.72 3461.56 "Анатолий Кулаков" Ну, то есть просто так бы он его не нашел без анализаторов. +3461.56 3462.56 "Игорь Лабутин" Ну, да. +3462.56 3467.76 "Игорь Лабутин" Не, ну, видишь, он его нашел, я так понимаю, каким-то другим образом, иначе не было бы прошлой статьи, а анализаторы. +3467.76 3471.76 "Анатолий Кулаков" Ну, давай скажем так, если ты не аджут скин, то ты бы его не нашел. +3471.76 3472.76 "Анатолий Кулаков" Хм. +3472.76 3473.76 "Анатолий Кулаков" Скин, может, и нашел бы, да. +3473.76 3480.68 "Игорь Лабутин" Не, ну, возможно, он нашел какой-то баг по внешнему поведению, и только тогда понял, что что-то не то, так что тут такое непонятно. +3480.68 3485.56 "Игорь Лабутин" Ну, да, в общем, интересная история, так чисто на это, на поразмышлять. +3485.56 3493.56 "Игорь Лабутин" Если вы задумываетесь о росте анализаторов, подумайте, может быть, вам нужен не один, в смысле не одна диагностика, а несколько и разноплановых. +3493.56 3494.56 "Игорь Лабутин" Такие дела. +3494.56 3510.00 "Анатолий Кулаков" А если вы захотите в свой язык программирования гнедать рекорды, то желательно дизайн их выстроить как-то лучше, подумать над ними подольше, и не лепить то, что приходит на ум прямо в текущий же релиз. +3510.00 3516.80 "Анатолий Кулаков" Потому что иначе появляются вот такие непонятные всякие баги, хочется их назвать, но это в принципе дизайн +3516.80 3517.80 "Игорь Лабутин" системы. +3517.80 3521.24 "Игорь Лабутин" Ну что, пойдем дальше, что у нас еще осталось? +3521.24 3524.16 "Анатолий Кулаков" Да, пойдем по-коротко, по-разному пробежимся. +3524.16 3526.40 "Анатолий Кулаков" У меня тут есть парочка мелких тем. +3526.40 3539.24 "Анатолий Кулаков" Во-первых, прошла новость, что Dependabot, та часть его, которая отвечает за наш Nuget Update, была переписана на .NET, и в принципе все стали от этого очень счастливы. +3539.24 3548.68 "Анатолий Кулаков" По порядку, Dependabot - это специальный бот, который ходит по гитхабу и предлагает обновить зависимость у ваших проектов. +3548.68 3550.56 "Анатолий Кулаков" Почему это полезно? +3550.56 3560.56 "Анатолий Кулаков" Ну как раз таки потому, что у проекта устаревает, у них появляется security уязвимости, и для того, чтобы ваши проекты не приносили дыры своим пользователям, их периодически необходимо обновлять. +3560.56 3583.04 "Анатолий Кулаков" И вот был написан специальный бот, который называется Dependabot, который ходит, пытается прежде всего найти security уязвимости, если они там есть, он обновляет ваши проекты на необходимые пакеты, в которых эти уязвимости обычно устранены, и предлагает вам pull-request для того, чтобы вы приняли и ваши проекты зажили новой счастливой обновленной жизнью. +3583.04 3594.56 "Анатолий Кулаков" Ну так вот, раньше .NETчики сталкивались с такой проблемой, что их проекты Dependabot сканировались очень медленно, но это не самое даже плохое. +3594.56 3620.16 "Анатолий Кулаков" Самое плохое было в том, что очень часто это сканирование и обновление завершалось с ошибкой, потому что Dependabot не мог нормально обновить проекты, и случалось это по той причине, что как раз-таки тот анализатор, который анализировал состояние .NET проекта, .NET solution, и обновлял их, он был написан на Ruby, и Ruby понятия не имел о разной специфике .NET. +3620.16 3654.04 "Анатолий Кулаков" Ну как, понятия не имел, его конечно каким-то костылям научили, но по сути, чтобы вы понимали, он например работал со всякими проектными файлами, как с .XML файлом, то есть он просто загружал .XML файл, он не мог нормально интерпретировать допустим условные кондишены, которые стоят в наших .CSS прош файлах, он понятия не имел там о Global JSON, который там указывал версию SDK, он очень плохо знал Central Package Manager, которыми практически все современные .NET проекты пользуются. +3654.04 3659.84 "Анатолий Кулаков" В общем, вот такие баги, недоделки, неосведомленности, у него их было очень полно. +3659.84 3677.40 "Анатолий Кулаков" В общем, перед командой Dependabot стояло как бы два решения, или пытаться угнаться за всем тулчейном .NET, или переписать Nuget Updater просто-напросто на .NET, и нативно как бы получить всю поддержку .NET инфраструктуры, которая есть. +3677.40 3706.68 "Анатолий Кулаков" И они пошли естественно по второму пути, поэтому теперь Nuget Updater написан на C#, с нативной поддержкой всего тулчейна, который есть в .NET, в частности он использует нормальный Nuget Client, MSBuild API, теперь они просто какие-то дурацкие XML файлики, .NET CLI, он теперь понимает Global JSON, он теперь нормально, нативно понимает полностью Central Package Manager, и много-много вот этих специфики всяких C#, .NET проектов, которые у нас есть. +3706.68 3719.28 "Анатолий Кулаков" И в результате скорость работы Dependabot выросла на 65%, например у них был комплект тестов, который он должен был пройти. +3719.28 3749.72 "Анатолий Кулаков" В общем тесты раньше исполнялись 26 минут, а теперь начали исполняться 9 минут, но не это самое главное, а самое главное в том, что раньше тестовые проекты, которые они обновляли .NET, обновление проходило на 82% всех проектов, а теперь проходит на 94% всех проектов, то есть больше проектов .NET смогут быть обновлены, обновлены правильно с учетом всяких SDK, Global JSON, конфликтов и прочих вот этих вещей. +3749.72 3760.00 "Анатолий Кулаков" Больше проектов сможет быть обновлено, теперь они смогут обновляться быстрее, ну и вообще такая в принципе минорная, но довольно интересная новость, поэтому всем радоваться. +3760.00 3779.98 "Анатолий Кулаков" Еще одна новость, которую я хотел с вами поделиться, я напомню, что у нас есть дружеский подкаст, называется .NET AdMob, на нем больше разговоров, больше рассуждений, поэтому если вам хочется больше веселья, больше мнений, более широкие темы, то попробуйте, послушайте ребятам, возможно вам понравится. +3779.98 3795.40 "Анатолий Кулаков" И вот у них иногда есть выпуски такие странные, они пытаются .NETчиков научить чему-нибудь другому, у них есть плейлист про то, как они .NETчиков учили писать на Rust, а сейчас они пытаются .NETчиков научить разбираться в Kubernetes. +3795.40 3804.08 "Анатолий Кулаков" И вот у них вот эта серия обучения к Kubernetes подошла к концу, поэтому если вы ждали полного комплекта, полной серии, полного плейлиста, он готов. +3804.08 3814.16 "Анатолий Кулаков" Можете приступать, можете слушать, если вы никогда раньше не столкнулись с Kubernetes, то наверное вам этот курс возможно будет полезен. +3814.16 3840.98 "Анатолий Кулаков" Там ребята обсудили низкоуровневые устройства, как работает не только Kubernetes, но и Dockers, и Containers, то есть токенном спейс, AC группы, как работает сеть в Kubernetes и как он балансирует запросы, как она распределяет поды, как определяется имена различных нод, то есть как DNS устроен, из чего рантайм состоит, как вольюмы мапить, маунтить различные ресурсы и так далее. +3840.98 3845.28 "Анатолий Кулаков" В общем прошлись про Kubernetes довольно хорошо. +3845.28 3853.32 "Анатолий Кулаков" Если вам такой формат заходит и повествование, которое там есть, нравится, то обратите внимание на этот плейлист. +3853.32 3864.92 "Игорь Лабутин" Да, будет наверное полезно, особенно если вы не встречались там довольно, но с моей точки зрения неплохо рассказываются всякие базовые термины и практические моменты, на что обратить внимание. +3864.92 3886.32 "Игорь Лабутин" А на сегодня мы будем заканчивать, мы посмотрели на седьмое превью десятого Дотнета, мы посмотрели на Nuget MCP сервер, Aspire 9.4, просуждали на тему того, как поддержан паскей в ASP.NET Core Identity, ну правда, всё может поменяться к релизу, ну и закончили, я надеюсь, разбираться с рекордами от Джона Скита. +3886.32 3889.40 "Анатолий Кулаков" На этом на сегодня всё. +3889.40 3898.72 "Анатолий Кулаков" Всем счастливо, до новых встреч, не забывайте нашарить, репостить, подписываться на нас, каналы и комментарии везде, где только нас найдете и советовать наши выпуски друзьям. +3898.72 3900.16 "Анатолий Кулаков" До новых встреч, всем пока. +3900.16 3900.80 "Анатолий Кулаков" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-122.txt b/input/Radio/Transcriptions/RadioDotNet-122.txt new file mode 100644 index 0000000..0a34f1d --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-122.txt @@ -0,0 +1,501 @@ +0.00 12.34 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Radio.net и в студии ее постоянный ведущий Анатолий Кулаков. +12.34 13.34 "Игорь Лабутин" И Игорь Лабутин. +13.34 14.34 "Игорь Лабутин" Всем привет. +14.34 23.32 "Анатолий Кулаков" Выпуск у нас уже 122-й, и все эти выпуски нас сопровождают наши блестящие помогаторы. +23.32 24.94 "Анатолий Кулаков" Спасибо вам огромное, друзья. +24.94 47.76 "Анатолий Кулаков" Среди них Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Оленька Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев и Юрий Лодейкин. +47.76 49.12 "Анатолий Кулаков" Друзья, спасибо вам большое. +49.12 55.08 "Анатолий Кулаков" Если вы хотите поддержать любыми подкаст, заходите на Boosty и посмотрите, что мы вам интересно можем за это предложить. +55.08 60.20 "Игорь Лабутин" И нас поддерживает Altenar, международная команда с центрами разработки в России и Мальте. +60.20 64.04 "Игорь Лабутин" Компания создает ПО для легальных битинг операторов в Европе и Америке. +64.04 75.96 "Игорь Лабутин" Код на C# помогает решениям Altenar держать высокие нагрузки в период крупнейших спортивных событий, работать с большим объемом входящих данных, моментально пересчитывать вероятности по ходу матчей, находить аномалии в поведении игроков. +75.96 85.54 "Игорь Лабутин" На стенде ребят на .NEXT можно будет познакомиться с .NET командами, поговорить про челленджи высоконагруженного реалтайма, запрограммировать необычные устройства и узнать больше о прогнозировании. +85.54 104.60 "Анатолий Кулаков" Ну что ж, во первых строках своего подкаста хочется поздравить команду SPBGU, которая в данные секунды, ну как мы записываемся, заняла первое место на мировом оси PC, в общем, это считается, на данный момент самый крутецкий программист у нас в мире теперь считается. +104.60 110.96 "Анатолий Кулаков" Так что отлично, молодцы ребята, также все те, кто участвовал в конкурсе, но к сожалению, не заняли такие высокие позиции. +110.96 115.04 "Анатолий Кулаков" SPBGU вообще прям порадовало, удивило и порадовало. +115.04 117.28 "Игорь Лабутин" Это точно, мои поздравления. +117.28 131.72 "Игорь Лабутин" Когда-то давно, я всем этим увлекался, но да, давно мы не пишем уже таких олимпиадных задачек, зато мы пишем самые обычные наши работяжные, так сказать, код на C# и других языках. +131.72 145.42 "Игорь Лабутин" И если вы пишете на C#, то для вас хорошая новость, если вы подождете еще немного, ну года полтора, не меньше, то у вас появятся в C# юнионы, как нам обещал автор языка C#. +145.42 153.56 "Анатолий Кулаков" Дискриминационные юнионы, т.е. те самые, которые мы ждали уже лет 10 или 20, поэтому подождем, подождем, давай, рассказывай, что же. +153.56 168.64 "Игорь Лабутин" Да-да-да, Мэтт Сторгерсон рассказал немножко про планы, естественно, он не мог не обойти, у него был такой доклад-обзор того, что происходит с языком, и в частности там есть кусочек, посвященный, конечно же, юнионам. +168.64 179.40 "Игорь Лабутин" И вот команда .NET наконец-таки придумала, как они будут выглядеть, по крайней мере, в их первой версии, и будет это, ну, относительно скоро, как я сказал, года через полтора, если нам повезет. +179.40 191.52 "Игорь Лабутин" Так вот, да, важно сказать, что весь доклад Мэтт говорил, что это не коммитмент, это possibility, т.е. они как бы не обещают, что будут, но они будут очень стараться, возможно, получится. +191.52 194.72 "Игорь Лабутин" Значит, что нам обещают и что нам предлагают? +194.72 197.12 "Игорь Лабутин" Предлагают нам следующую конструкцию. +197.12 213.80 "Игорь Лабутин" Представьте, что вам нужно, ну, у него в примере был, значит, юнион, который он обозвал pet, домашнее животное, которое мы хотим, чтобы имел один из трех, в смысле, объединял в себя три возможных варианта, dog, cat и bird. +213.80 216.60 "Игорь Лабутин" Ну, понятно, три домашних варианта животных. +216.60 220.80 "Игорь Лабутин" Для того, чтобы выложить, выразить это в C#, нужно будет сделать следующее. +220.80 245.24 "Игорь Лабутин" Во-первых, мы создаем три класса, ну, в примере это были просто public_record класс, там, dog от string_name, public_record класс bird от, там, string_species, ну, или что угодно, короче, могут быть необязательно одинаковые, естественно, параметры, аргументы у каждого из классов, пока это просто независимые классы или структура, то есть cat, например, у них объявлен как public_record_struct cat. +245.24 261.60 "Игорь Лабутин" И вы можете это сделать уже сейчас, но дальше вы делаете следующее, вы пишете public_union pet и в скобочках круглых указываете те самые названия классов, которые вы только что объявили, то есть dog, cat, bird. +261.60 276.40 "Игорь Лабутин" И получится, что у вас есть union pet, который по компилятору будет проверять, что значение этого union, переменной, у которой тип этот union, могут быть только экземпляры dog, либо cat, либо bird, и больше ничего другого. +276.40 324.48 "Игорь Лабутин" При этом обещано, что может быть, если они успеют, то будет вариант, когда вы будете объявлять не просто public_union pet и дальше в круглых скобках, как в прайме реконструктора, название трех классов, трех, ну, какие классы, сколько вам нужно туда запихнуть, а можно будет внутри public_union pet открыть фигурную скобочку, как будто это объявление класса, ну, или genome скорее, даже, да, такого, и внутри написать case, как в свитче мы пишем, cat, за большую букву это будет название класса, который один из вариантов внутри union, и дальше в стиле прайма реконструктора набор значений, набор параметров, ну, или полей, потом case dog и case bird, то же самое, то есть такое встроенное определение, нужно будет эти классы объявлять отдельно. +324.48 332.80 "Анатолий Кулаков" Но компилятор… Да, это больше похоже на то, как это есть, например, в функциональных языках программирования или в других языках, где уже поддерживается discrimination union. +332.80 341.04 "Игорь Лабутин" Но компилятор это все равно, по сути, развернет точно такую же конструкцию, просто эти классы будут объявлены, ну, они будут внутренними классами в классе pet. +341.04 342.04 "Анатолий Кулаков" Вот. +342.04 354.76 "Анатолий Кулаков" Ну, это один из аргументов, когда люди приводят плюсы discrimination union, в том, что ты ставишь намного меньше места для того, чтобы объявить более сложную иерархию и более сложные конструкции, поэтому компилятор просто там делает что угодно, но это довольно удобно. +354.76 355.76 "Игорь Лабутин" Да, да-да-да. +355.76 375.24 "Игорь Лабутин" При этом дальше, естественно, если вы объявили переменную типа pet, вы сможете написать строчку pet, значит, присвоить new dog, и несмотря на то, что, ну, вроде как вы объявили union pet, который напрямую синтаксически с dog не связан, но компилятор будет знать, что есть конвершен между dog и pet каким-то образом. +375.24 379.40 "Игорь Лабутин" Вот сейчас рассмотрим, каким. +379.40 380.40 "Игорь Лабутин" Дальше. +380.40 389.80 "Игорь Лабутин" Ну, в первой реализации, скорее всего, все-таки типы должны будут объявлены быть отдельно от union, но это вот обещают, что, может быть, пересмотрят. +389.80 395.96 "Игорь Лабутин" Как ты правильно сказал, в функциональных языках это обычно называется discriminated union или tag union. +395.96 410.00 "Игорь Лабутин" В подходе, который выбрал команда C#, это они называют type union или structural union, то есть это чуть-чуть другой подход, но по смыслу похожий, по сути. +410.00 442.12 "Игорь Лабутин" Естественно, поскольку такое объявление, то есть когда вы в union объявляете явно список классов, который может быть внутри, то, естественно, все type-чеки, то есть не type-чеки, все switch-стейтменты, естественно, могут начать проверяться компилятором на полноту, то есть если вы делаете switch по вашему, по переменной, у которой тип pet, компилятор сможет сказать, все ли кейсы вы рассмотрели, ну или вам нужен дефолт, например. +442.12 456.36 "Игорь Лабутин" Естественно, если вы после этого расширите pet каким-то новым элементом, новым типом, который вы внутрь хотите положить, то, естественно, все такие места вам компилятор подсветит и скажет, что вообще-то вот этот новый тип вы не рассмотрели. +456.36 458.16 "Игорь Лабутин" Еще и это нужно сделать. +458.16 465.00 "Игорь Лабутин" Они это называют, соответственно, closed union type, то есть вы не можете его никак расширять, вот как объявили, ну так уже и пользуемся. +465.00 468.08 "Игорь Лабутин" Как это работает внутри? +468.08 484.84 "Игорь Лабутин" Внутри сделано, то есть короче синтаксически сделали практически чуть-чуть, то есть будет новое ключевое слово, ну как новое, ключевое слово union, и вот синтаксис когда-то вы можете после имени вот этого union в круглых скобках написать, что в нем содержится, именно только имена типов. +484.84 489.60 "Игорь Лабутин" Такого, по-моему, у нас нигде так сходу, что-то я не припомню, чтобы C# так можно было писать. +489.60 490.60 "Анатолий Кулаков" Вроде да. +490.60 518.88 "Игорь Лабутин" Вот, то есть это небольшое синтаксическое изменение, а по факту компилятор это сгенерит из этого рекордстракт, то есть union это будут рекордстракты, которые будут иметь всего лишь одно единственное read-only поле, называемое value, с типом object, ну nullable object по факту, потому что может быть там, может быть null, если вы хотите туда null записать, в принципе тоже будет валидно, тогда он будет nullable. +518.88 562.20 "Игорь Лабутин" Вот, то есть это просто обыкновенное object поле, и если вы все классы, которые вы хотите использовать внутри union объявляете действительно классами, то тут проблем никаких нет, ну как бы вы можете ссылку на любой reference-тип положить в поле с типом object, и никаких проблем у вас не будет, но, как я сказал, никто вам не мешает объявить, например, как у них в примере cat объявлен как рекордстракт, и в этом случае, если вы кладете его в value, ну будет как обычный boxing, то есть здесь команда C# говорит, ну да, boxing будет, без него в данном случае пока, по крайней мере, никак, в первой реализации, скорее всего, это будет именно так и работать. +562.20 563.20 "Игорь Лабутин" Но. +563.20 588.56 "Игорь Лабутин" Дальше возникает вопрос, предположим, что у нас одни сплошные value-тайпы внутри union живут, казалось бы, можно было бы, не знаю, автоматически посчитать максимальный размер каждого value-тайпа, выделить соответствующее время места в объекте, и все value-тайпы, по сути, хранить in place в объекте, без boxing-а дополнительного. +588.56 630.00 "Игорь Лабутин" Но это сложная логика, ее, скорее всего, на первом этапе уж точно не будет, на втором этапе возможно появится возможность сделать кастомные типы, которые компилятор будет считать как будто это union, ну то есть можно будет не просто объявить public union что-то, а на самом деле объявить класс, который будет реализовывать интерфейс IUnion, он тоже будет добавлен, и этот класс с точки зрения компилятора будет вести себя в каком-то смысле так же как обычный union, switch statement и вот это все. +630.00 652.00 "Игорь Лабутин" Тут пока деталей мало, было показано только буквально пару кусочков кода без объяснения, как оно все будет работать в деталях, то есть либо надо читать спеку, либо ждать реализации, и я думаю, что правильно ждать реализации, потому что, скорее всего, не наткнутся на кучу проблем, с этим каких-нибудь непредвиденных обстоятельств, и опять же, это в любом случае не обещано не в первом варианте, а чуть-чуть попозднее. +652.00 656.04 "Анатолий Кулаков" Ну и в любом случае это как бы оптимизация для структуры, +656.04 658.56 "Игорь Лабутин" вполне можно жить без нее. +658.56 688.00 "Игорь Лабутин" Либо это какая-то супернужная будет, может быть для внутри runtime, там какие-то места, ну да, напишут кастомный union type, а так можно будет использовать обычный, более того, они даже говорят, что поработают плотненько с BCL, чтобы там уже были готовы какие-то полезные, как они сказали, типа unit type, да, то есть не просто union type, не в смысле, что они просто сделают feature в C#, да, и пользуйтесь, ребята, но как-то попытаются это в BCL тоже в нужные места пропихнуть. +688.00 705.88 "Игорь Лабутин" Например, как у нас есть класс tuple, ну и value tuple, да, которые помогают вам содержать там, t1, t2, t3, будет такой же тип, типа union, t1, t2, t1, t2, t3, ну и так далее. +705.88 707.52 "Игорь Лабутин" Типа union с дженериками, да? +707.52 718.56 "Игорь Лабутин" Union с дженериками, если вам не нужно по какой-то причине обращаться, ну, короче, как бы, никакого ничего специфического вам не нужно, то по большому счету, может быть, действительно этого будет достаточно. +718.56 719.56 "Игорь Лабутин" Вот. +719.56 729.60 "Игорь Лабутин" А если вы просто типами это все укажете, уже готовыми вашими типами, то есть если вам нужно создать union из уже готовых ваших типов, то почему нет? +729.60 730.60 "Игорь Лабутин" Вот. +730.60 739.08 "Игорь Лабутин" Если вы захотите, понятно, описать новый union вот в стиле там F# или других функциональных языков, in place, ну, конечно, тут уже такой дженерик не подойдет, пишите с нуля. +739.08 767.28 "Игорь Лабутин" Но вот как-то так, значит, работать над этим они начнут только когда C# 14 достигнет general availability, то есть, ну, грубо говоря, в ноябре этого года, и они надеются, что к 15-му C#, то есть это через годик, у нас это будет фича доступна, возможно, она будет все еще под каким-нибудь экспериментал или превью флагом, я думаю, что все будет зависеть от прогресса команды разработки в этом направлении. +767.28 794.04 "Игорь Лабутин" Но хотя бы появилась хоть какая-то конкретная реализация, которая выглядит разумной, и я, кстати, не видел особо каких-то больших обсуждений на тему, ну, вот сделали совсем не то, ну, или планируют сделать совсем не то, но поглядим, поглядим, может быть, сейчас 14 выйдет, начнут более детально обсуждать 15, и будет больше разговоров или больше статей, обозревающих, что там происходит, но, по крайней мере, уже оптимистично, что хоть что-то начало двигаться. +794.04 838.84 "Анатолий Кулаков" Ну да, новость довольно радостная, потому что мы не раз в наших выпусках обсуждали discrimination union в C#, мы обсуждали их проблемы, обсуждали, почему они нужны, зачем их хотят очень много, это самая сейчас запрашиваемая фича, которая есть, не реализована в языке C#, в общем, если вы вдруг не знаете, что это такое, зачем это нужно, посмотрите в наших предыдущих выпусках, там много информации по этому поводу, поэтому очень оптимистично, конечно, очень все рады тому, что мы это рассказал, и смотрим будущие версии, не знаю, может быть, это даже фича, которая переплюнет extension everything, несмотря на то, что экстеншонов тоже ждали очень много лет, и много их хотели, посмотрим, посмотрим на реализацию. +838.84 853.60 "Анатолий Кулаков" Будем надеяться, что команда не сбавит скорости, потому что предыдущие релизы нас кормили практически ничем, тут хотя бы сделали extension, тут пообещали discrimination union, то есть кажется, что они стали разгоняться. +853.60 871.60 "Игорь Лабутин" Хотел сказать, что про extension everything есть такой момент, что мы вроде как ее описали, это же было, ну в одном из первых превьюшек, по-моему, это появилось, и как ни странно, какая-то практически, ну по крайней мере в моем информационном поле, практически полная тишина на тему этой фичи. +871.60 889.36 "Игорь Лабутин" Что она есть, что она нет, обычно там выходит куча всяких разных обзоров, ну каких-нибудь типа а-ля beginner guide, что-нибудь, туториал по фиче, а тут прямо как-то тишина и спокойствие, не знаю почему, посмотрим, что будет ближе к релизу, может они ее выпилили под +889.36 890.36 "Анатолий Кулаков" шумок давно уже. +890.36 896.52 "Анатолий Кулаков" Они же ее хотели еще в предыдущем релизе и там выпилили, не знаю, два релиза подряд выпиливать. +896.52 897.52 "Игорь Лабутин" Хотя могут почему-то. +897.52 898.52 "Игорь Лабутин" Надеюсь, что нет. +898.52 899.52 "Игорь Лабутин" Ладно, давай дальше. +899.52 905.04 "Анатолий Кулаков" Может они там решили синтаксис изменить и поэтому паблик сильно не пускает такие статьи. +905.04 910.80 "Игорь Лабутин" Ну в смысле, они-то, может, конечно, и не пускают Microsoft, но кто мешает другим писать, ну даже другие не пишут +910.80 911.80 "Анатолий Кулаков" особо. +911.80 915.00 "Анатолий Кулаков" Другие тоже предупредили, типа слишком не рекламируйте, потому что все равно все поменяется. +915.00 917.56 "Анатолий Кулаков" Ну может быть, может быть. +917.56 925.88 "Анатолий Кулаков" Так, насчет другого, пойдем дальше посмотрим, интересная статья, практическая, вышла от автора, который называется Энтони Симмон. +925.88 942.96 "Анатолий Кулаков" Он работает в компании Worklib и они у себя решили объединить усилия на почве одного стандарта для кодирования, для того, чтобы улучшить в их компании процессы, процессы кодирования. +942.96 952.44 "Анатолий Кулаков" В общем, такая довольно бытовая ситуация и поэтому хотелось бы ее рассмотреть с вами вместе на практике, что из них получилось и куда они пошли и что сделали. +952.44 971.88 "Анатолий Кулаков" В общем, они столкнулись с тем, что у них есть большая организация, в этой организации рабочей работает куча разработчиков и они решили как-нибудь прооптимизировать свой цикл разработки, чтобы он проходил быстрее, чтобы качество кода было лучше, и вот они по всяческому подходили к этому процессу. +971.88 977.16 "Анатолий Кулаков" У них есть много разных статей, если вот это зайдет, мы другие тоже рассмотрим. +977.16 988.26 "Анатолий Кулаков" А эта статья, которую я хочу вам сегодня рассказать, она про то, как они оптимизировали стиль кодирования и прочие настройки вот такие низкоуровневые у проектов, у солюшенов дотнетовских. +988.26 1001.44 "Анатолий Кулаков" Ну, прежде всего, мы говорим про C# CodeStyle и с помощью CodeStyle они хотели улучшить качество и с помощью настроек низкоуровневых проектов они хотели улучшить перформанс стандартных их проектов. +1001.44 1011.56 "Анатолий Кулаков" Как я уже сказал, типичная большая интерфейс контора, у них там было несколько солюшенов, у них были сотни кодов, у них были там куча разработчиков и различные репозитории под это все. +1011.56 1018.90 "Анатолий Кулаков" То есть, как мы любим, микросервисы, куча независимых команд, каждый пилит, что хочет, полная анархия и демократия. +1018.90 1024.84 "Анатолий Кулаков" И они начали анализировать, что же у них происходит с процессом разработки. +1024.84 1030.72 "Анатолий Кулаков" Ну, например, самый простой случай, когда создается какой-то новый проект, что происходит? +1030.72 1036.20 "Анатолий Кулаков" Разработчик обычно приходит, создает новый солюшен, закидывает новый проект и думает, а чем бы его изначально наполнить. +1036.20 1047.60 "Анатолий Кулаков" Я думаю, многим вам известна такая ситуация, особенно если вы работаете в большой компании, то хочется наполнить этот проект чем-то, тем опытом, который уже вы проходили в каких-то других проектах. +1047.60 1048.60 "Анатолий Кулаков" Что это значит? +1048.60 1052.12 "Анатолий Кулаков" Это значит, что вы прежде всего копируете какую-то кучу boilerplate. +1052.12 1055.52 "Анатолий Кулаков" Ну, например, EditorConfig, святая вещь для копирования. +1055.52 1059.20 "Анатолий Кулаков" Я думаю, в каждом новом проекте, в каждом новом солюшене он обязан появиться. +1059.20 1075.04 "Анатолий Кулаков" Различные свойства MS Build, который настраивает ваши любимые флажочки, который подключает ваши любимые проекты ко всем местам, которые вы любите, какие-то различные MS Build хаки, компиляции. +1075.04 1086.24 "Анатолий Кулаков" И вот эти кусочки, которые помогают вам настроить новый проект, они вот таким образом копируются из одного репозитория в другой репозиторий. +1086.24 1097.40 "Анатолий Кулаков" И вроде бы это не так уж и плохо, потому что у вас какой-то EditorConfig и какие-то общие MS Build свойства переиспользуются с помощью копирования, но все же переиспользуются. +1097.40 1099.60 "Анатолий Кулаков" Вы все-таки не с нуля их пишете или вообще не забываете. +1099.60 1111.20 "Анатолий Кулаков" Но с другой стороны, если мы говорим про большие компании, в которых это происходит годами, мы постепенно приходим к той ситуации, когда вот эти уже копирования, они в каждом из проектов немножко меняются. +1111.20 1113.00 "Анатолий Кулаков" Там немножко разные фреймворки. +1113.00 1115.64 "Анатолий Кулаков" Некоторые флажки устаревают, некоторые переписываются. +1115.64 1120.44 "Анатолий Кулаков" И мы приходим к той источнике, когда уже у нас все репозитории становятся неконсистентными. +1120.44 1134.56 "Анатолий Кулаков" То есть, несмотря на то, что с одного источника мы их копировали, но так как эти источники поддерживаются по-разному, принцип синхронизации, обновления и модификации у них не синхронизирован, поэтому они становятся уже разными, они становятся неконсистентными, и поэтому качество падает. +1134.56 1140.00 "Анатолий Кулаков" Например, в каких-то проектах мы ввели новый флажочек для оптимизации, а в каких-то забыли. +1140.00 1146.48 "Анатолий Кулаков" В каких-то включили новый флажочек для того, чтобы новый анализатор проверял наш код на уязвимость, а в каких-то забыли. +1146.48 1147.48 "Анатолий Кулаков" Вот. +1147.48 1151.92 "Анатолий Кулаков" И все это привело в такую… превратилось в такую большую-большую помойку. +1151.92 1161.56 "Анатолий Кулаков" Авторы сели и проанализировали pull-реквесты, которыми разработчики обмениваются ежедневно. +1161.56 1174.84 "Анатолий Кулаков" И в этих pull-реквестах они также заметили, что все дискуссии, которые происходят, очень сильно на них влияет тот самый код-стайл, который различается у нас в различных репозиториях. +1174.84 1183.96 "Анатолий Кулаков" Они обнаружили, что очень много комментаторов вместо того, чтобы обращать внимание на реальные проблемы в разработке, начинают рассказывать, как правильно табы и пробелы ставить. +1183.96 1184.96 "Анатолий Кулаков" Наша любимая тема. +1184.96 1187.84 "Анатолий Кулаков" Как скобочки, запятые и так далее. +1187.84 1211.84 "Анатолий Кулаков" И все это, естественно, сказывалось на цикле разработки, потому что если тебе там рассказали, как поставить пробельчик, то уже, скорее всего, этот коммит не вмерзнется в эту секунду в мастер, а нужен будет какой-нибудь полдня на то, чтобы твой фидбэк увидели, потом полдня, чтобы починили, обратно прошел весь пайплайн и там на сутки, как минимум, с каждым таким комментарием задерживается мерш. +1211.84 1233.12 "Анатолий Кулаков" Также, если мы начинаем поднимать такие святые войны, как табы, пробелы, всякие скобочки, запятые, это очень негативно сказывается на атмосферу в команде, потому что у каждого разработчика свои чувства о том, как прекрасно должен выглядеть его код и они обычно с другими людьми, с другими разработчиками не совпадают и начинается какой-то негатив в компании. +1233.12 1258.80 "Анатолий Кулаков" Ну и, как я уже упомянул выше, когда у вас весь пулл-реквест загорожен комментариями о стиле кодирования, то для настоящих ошибок уже не хватает времени, они или просто до них не доходят руки, потому что все заняты обсуждением скобочек, или среди тучи комментариев уже настоящие ошибки не видно, поэтому пропускалось очень много важных ошибок. +1258.80 1268.24 "Анатолий Кулаков" Также авторы заметили в компании, что в принципе компилятор пытался каким-то образом им рассказать о том, какие проблемы есть в их проектах, но его никто не слушал. +1268.24 1278.12 "Анатолий Кулаков" И вполне проекты, которые вполне имели кучу там варнингов от компилятора, мёрзались в мастера и потом эти варнинги стреляли в виде каких-то ошибок на продакшенах. +1278.12 1297.48 "Анатолий Кулаков" В частности null reference, nullable reference тайпы никто у них не смотрел, росслен анализаторы были с маленькими уровнями показывались, поэтому тоже на них никто не видел, забивали на code style, у них не было аудирования nugget пакетов на счёт уязвимости, из-за чего они тоже ловили кучу косяков. +1297.48 1306.20 "Анатолий Кулаков" В общем, накопилась большая куча каких-то проблем, и все они примерно вот были в этой области. +1306.20 1316.36 "Анатолий Кулаков" Стиль кодирования, настройки компилятора, настройки солюшенов, переиспользование единых подходов, и компания села и начала вырабатывать решения. +1316.36 1334.20 "Анатолий Кулаков" В общем, в принципе, никаких новшеств или больших каких-то открытий они не сделали, они выработали стандартное решение, что им нужно унифицировать стайл гайды, им нужно унифицировать инструментарий и договориться в общем о стиле кодирования. +1334.20 1337.88 "Анатолий Кулаков" Любая большая компания к этому рано или поздно приходит. +1337.88 1352.68 "Анатолий Кулаков" Поэтому они сели, подумали, решили, что свои решения они будут строить на основе рослин-анализаторов, потому что у них там был еще вариант на основе стайл копа, это устаревший подход, таким лучше не пользоваться. +1352.68 1357.04 "Анатолий Кулаков" Медленный, глючный и так далее, поэтому рослин-анализатор это правильный выбор. +1357.04 1366.20 "Анатолий Кулаков" Плюс они заметили, что у рослин-анализаторов есть квикфиксы, которые помогут им смигрировать этот код, поэтому выбор был именно на них. +1366.20 1385.32 "Анатолий Кулаков" Они провели кучу митингов, кучу часов для того, чтобы выработать более-менее общие договоренности насчет того, какие правила у них будут именования, форматирования, какие конструкции языка они будут использовать, ну вот эти вот наши всякие любимые договоренности и холивары. +1385.32 1388.72 "Анатолий Кулаков" В результате у них получился эдитер конфиг на 200 строк. +1388.72 1393.24 "Анатолий Кулаков" В принципе не то чтобы совсем и много, вполне приемлемые размерчики. +1393.24 1398.36 "Анатолий Кулаков" После того, как они договорились о кодстайле, они пошли улучшать качество кода. +1398.36 1409.20 "Анатолий Кулаков" Они нашли там всякие флажочки, которые помогают компилятору, которые помогают MS Build системе анализировать код и советовать какие-то улучшения. +1409.20 1424.52 "Анатолий Кулаков" Они нашли флажочки, которые улучшают перформанс, они нашли настройки, которые улучшают security, тоже в принципе об этом по всем договорились и в результате у них появилось 800 правил рослин анализаторов, в принципе тоже неплохо. +1424.52 1440.12 "Анатолий Кулаков" Ну, чтобы представляли среди этих правил, допустим, не крутить E-нумер был по несколько раз, пробрасывать cancellation токен, делать rethrow для исключений, для того чтобы они не теряли стэк и так далее. +1440.12 1450.84 "Анатолий Кулаков" Ну, то есть такие полезные подсказки, которые в принципе компилятор советует уже довольно-таки давно и довольно-таки всем, но почему-то не все команды начинают прислушиваться к нему. +1450.84 1455.88 "Анатолий Кулаков" Вот, эти парни решили повернуть на правильный путь и прислушаться. +1455.88 1482.44 "Анатолий Кулаков" В основном у них было очень большое удивление в том, что время сборки, время анализа, ну и вообще весь pipeline не увеличились, то есть у них было же, у них по времени это заняло такое же время, как и было раньше, то есть при включении всех этих оптимизаций, всех этих флажков анализ в принципе тоже и компиляция сама и анализ они ускорились настолько, что сравнились с тем, с той ситуацией, когда они вообще ничего не анализировали. +1482.44 1485.76 "Анатолий Кулаков" В общем, это тоже хорошо, это их порадовало, но это не главное. +1485.76 1496.76 "Анатолий Кулаков" Дальше они перешли к настройке MSBuild Properties и там тоже было очень много интересных свойств, которые, опять же, наверняка многие даже не подозревают, что они есть. +1496.76 1507.64 "Анатолий Кулаков" Например, Analysis Level выставили в Latest All, это свойство позволяет рослин анализаторам использовать самые последние анализаторы и всегда все анализировать. +1507.64 1520.52 "Анатолий Кулаков" Наш самый любимый флажочек - это интерпретировать варнинги с эрроры, обязательно должен выставляться в True у всех, он как раз не позволяет вам, ваш мастер пролезть самым страшным ошибкам, которые существуют. +1520.52 1529.44 "Анатолий Кулаков" Ну и плюс те ошибки, которые вы считаете страшными, их тоже можно обозначить варнингами и они тоже больше не будут пролазить в ваш мастер. +1529.44 1544.62 "Анатолий Кулаков" Enforce Code Style in Build, если выставить в True, то за стилем кодирования уже будет следить непосредственно на рослин анализатор и он запретит вливать в мастер код, который не соответствует вашему код стайлу. +1544.62 1554.72 "Анатолий Кулаков" Обязательно про Nuget Audit, тоже многие забывают, если его включить, то ваши пакеты будут проверяться на уязвимости, тоже очень важная настройка. +1554.72 1572.28 "Анатолий Кулаков" Еще один пакет, который интересный, мы про него рассказывали, но все же его мало до сих пор используют, это пакет от Microsoft, который называется Bund API Analyzers, это специальный пакет, который позволяет вам заблочить различные .NET API. +1572.28 1578.20 "Анатолий Кулаков" Мы когда-то жаловались, что .NET разрастается, в нем становится очень много сложностей, никто не знает, как с ним работать. +1578.20 1588.48 "Анатолий Кулаков" Ну так вот, есть уже инструменты, которые позволяют упростить вам .NET, просто забанить некоторые классы, некоторые методы, которые вы считаете, что не должны использоваться в вашем солюшене. +1588.48 1598.24 "Анатолий Кулаков" Ну, например, DateTimeNow никогда не должен использоваться в приличном солюшене, в приличном бэкэнде, NewtonSoftJSON тоже не должен использоваться, поэтому его тоже можно забанить с помощью этого пакета. +1598.24 1616.92 "Анатолий Кулаков" Я еще не встречал пакета, который банит какие-то конструкции языка, но я думаю, что скоро мы к этому придем, потому что, например, у товарищей C++ давно уже есть такие инструменты, которые позволяют разработчикам сказать, какие структуры языка, какие выражения языка больше не нужно использовать. +1616.92 1620.80 "Анатолий Кулаков" Я думаю, в C# мы тоже скоро, рано или поздно к этому придем. +1620.80 1622.44 "Анатолий Кулаков" Если вы, кстати, знаете такой пакет, то напишите. +1622.44 1633.04 "Анатолий Кулаков" И, конечно же, NullBlurReferenceType обязательно нужно включать, потому что это самая лучшая фича, которая была введена в последних версиях в C#, наверное, после дженериков. +1633.04 1638.36 "Анатолий Кулаков" Это мега-мощная и мега-крутая штука, которую ни в коем случае нельзя игнорировать. +1638.36 1641.80 "Анатолий Кулаков" Она сделает просто ваши программы мягкими и шелковистыми. +1641.80 1642.80 "Анатолий Кулаков" Это они тоже подключили. +1642.80 1650.44 "Анатолий Кулаков" Теперь, настроили там все, подключили, флажочки разные наставили, анализаторов натыкали, теперь как же все это использовать? +1650.44 1653.26 "Анатолий Кулаков" Использовать очень просто. +1653.26 1670.20 "Анатолий Кулаков" Во-первых, нужно осознать, что если у вас нет какого-то хорошего механизма для переиспользования всего того, что вы настроили, у вас получится опять снова тот мусор, который мы описали выше, когда у вас каждый разработчик будет копировать себе какие-то анализаторы, какие-то забывать, а какие-то обновлять, а какие-то удалять. +1670.20 1671.88 "Анатолий Кулаков" Это не дело. +1671.88 1678.08 "Анатолий Кулаков" Поэтому нужен хороший способ распространения и актуализации и поддержки всех этих правил. +1678.08 1680.96 "Анатолий Кулаков" И такой способ есть, называется он Nuget. +1680.96 1692.78 "Анатолий Кулаков" Вполне возможно все вот эти правила, настройки, файлики, конфиги упаковать в один Nuget пакет и распространить его в какой-нибудь ваш корпоративный Nuget Storage. +1692.78 1704.08 "Анатолий Кулаков" После этого разработчики могут поставить вот этот один Nuget пакет к каждому новому солюшену, который они себе создали, и случается магия, автоматически применяются все эти свойства, все эти правила, которые описали. +1704.08 1713.32 "Анатолий Кулаков" Nuget пакет, как вы знаете, он уже давно может содержать не только какие-то полезные библиотечки для вашего солюшена, они уже могут содержать много чего угодно другого. +1713.32 1721.40 "Анатолий Кулаков" Мы в прошлом выпуске обсуждали, что там в них можно засунуть и провайдеры к ИИ, и глобальные тулзы, и так далее. +1721.40 1724.76 "Анатолий Кулаков" Но в том числе нет никаких проблем к ним засунуть конфиги. +1724.76 1726.96 "Анатолий Кулаков" Давайте подробнее рассмотрим. +1726.96 1736.08 "Анатолий Кулаков" У .NET SDK есть такое замечательное свойство, что он может импортировать файлы props и target файлы, если вдруг в пакете они есть. +1736.08 1762.60 "Анатолий Кулаков" Ну, допустим, если ваш пакет называется мой пакет, и вы в моем пакете в папочке build создадите файлики мой пакет.props и мой пакет.targets, то вот эти файлики с настройками msbuild, они зареференцируются автоматически в проекте в солюшене, в котором ваш новый пакет установлен. +1762.60 1772.60 "Анатолий Кулаков" Это вам позволяет в эти файлики props и targets засунуть абсолютно любые msbuild свойства, через которые уже можно подключить абсолютно все остальное. +1772.60 1782.76 "Анатолий Кулаков" Например, вы можете воспользоваться свойством, которое называется editor-config-files и засунуть туда пути к файлам конфигурации editor-config. +1782.76 1786.28 "Анатолий Кулаков" И таких editor-config файлов у вас может быть сколько угодно. +1786.28 1795.80 "Анатолий Кулаков" То есть вы их, допустим, можете подключать в зависимости от какого-то кондишена, от какого-то условия, потому что msbuild-файлы – это язык декларативного программирования. +1795.80 1800.76 "Анатолий Кулаков" Там можно и всякие условия вставлять, и файлы подключать, и много чего даже модифицировать. +1800.76 1813.04 "Анатолий Кулаков" И вот с помощью этих механизмов вы можете создать несколько editor-config-файлов, их подключить через props и targets и получить как раз то, о чем мы рассуждали чуть выше, все вот эти правила, все вот эти подключения. +1813.04 1821.68 "Анатолий Кулаков" Ну и также roster-анализаторы тоже можно подключить используя package-dependencies, в общем, через те же самые props и targets. +1821.68 1840.06 "Анатолий Кулаков" Таким образом, имея вот такой мощный механизм, как один единственный пакет, который умеет запускать msbuild-овские props и targets, мы можем подключить все анализаторы, все editor-config-и, все настройки, все носпеки, которые мы для нашей команды придумали. +1840.06 1855.22 "Анатолий Кулаков" И естественно, так как это Nuget-пакет, мы теперь можем его обновлять, то есть поддерживать всегда в актуальном состоянии все наши правила, проверять там на актуальность и проверять, что в каждом solution, допустим, этот пакет подключен. +1855.22 1864.52 "Анатолий Кулаков" Для того, чтобы данный подход в компанию внедрить, автор там тоже проделал кучу всякой работы, но в общем случае рекомендации банальные. +1864.52 1874.32 "Анатолий Кулаков" Начинайте с маленьких команд, то есть они выбрали несколько ключевых проектов, несколько ключевых команд, сначала внедрили к ним, собрали фидбэк, послушали, что все хорошо, потом пошли раскатывать на всю компанию. +1874.32 1881.56 "Анатолий Кулаков" Также он советует создавать побольше документации, особенно для того, чтобы начать каким-то образом с этим пользоваться. +1881.56 1893.32 "Анатолий Кулаков" Обязательно нужна документация по миграции, потому что, как вы понимаете, если мы подключим все наши правила, которые мы только что выдумали к проекту, которому там 10 лет, там выдастся 200 тысяч мэроров. +1893.32 1898.32 "Анатолий Кулаков" В общем, нужно сразу описать, как с этим работать, что делать, куда идти. +1898.32 1911.72 "Анатолий Кулаков" Он также посоветовал создать отдельный документ, в котором написана мотивация разработчиков, зачем они пошли на эти страдания, то есть зачем они предлагают всем другим страдать, зачем они создали такой страшный пакет, в общем, тоже объяснить. +1911.72 1934.16 "Анатолий Кулаков" Отметил, автор отметил, что очень сильно помогают квикфиксы, потому что, когда у вас вылазят 200 тысяч проблем, и вы четко понимаете, как их фиксить, то Рослиновские квикфиксы очень сильно помогают, вы можете буквально одной командой пофиксить всю тысячу проблем, если она понятная, и нет никаких исключений, и все такое. +1934.16 1936.20 "Анатолий Кулаков" В общем, тоже квикфиксы очень сильно помогают. +1936.20 1941.84 "Анатолий Кулаков" Ну и плюсы, которые он отметил после внедрения данного подхода. +1941.84 1951.80 "Анатолий Кулаков" Ну, во-первых, очень сильно уменьшился код ревью, потому что никто никогда теперь на код ревью не рассказывает про всякие стили, секьюрити-уязвимости и прочее безобразие. +1951.80 1956.76 "Анатолий Кулаков" Разработчик видит это сразу, в момент разработки, и до код ревью это все даже не доходит. +1956.76 1962.68 "Анатолий Кулаков" Поэтому никаких обсуждений, никаких траты времени на возврат мерш-реквестов и прочего. +1962.68 1968.92 "Анатолий Кулаков" Безусловно, улучшилось качество кода, потому что теперь он стал весь единообразный. +1968.92 1980.88 "Анатолий Кулаков" Улучшился перформанс, улучшилась секьюрити, потому что теперь Рослин анализаторы следят за бестпрактисами, советуют разработчикам каким образом улучшить перформанс и как починить секьюрити. +1980.88 1991.12 "Анатолий Кулаков" Также увеличился уровень познания разработчиков, потому что теперь разработчики в своем коде встречают различные советы от Рослин анализатора и идут копать. +1991.12 1997.16 "Анатолий Кулаков" Что же такого интересного-то в этом языке появилось или почему в этой конструкции нужно использовать так, а не вот так? +1997.16 2000.28 "Анатолий Кулаков" Почему там структуры копируются, почему консолешин токены передаются? +2000.28 2008.80 "Анатолий Кулаков" Это еще и послужило таким образовательным фактором для тех разработчиков, которые раньше писали код, как их деды, а теперь приходится писать по бестпрактисам. +2008.80 2011.44 "Анатолий Кулаков" То есть тоже такой интересный момент есть. +2011.44 2034.60 "Анатолий Кулаков" Меньше boilerplate, потому что теперь весь boilerplate собран в один пакет, теперь его не нужно копировать при создании нового репозитория, он не размазывается там где-то, не переименовывается, не обновляется, он весь централизованно хранится в одном пакете, поэтому в общем его во всех репозиториях стало поменьше. +2034.60 2037.32 "Анатолий Кулаков" Ну и однообразные пакеты, проекты. +2037.32 2056.56 "Анатолий Кулаков" Это тоже очень важно, потому что когда разработчики переходят между проектами, когда разработчики переключаются между разными репозиториями, они четко понимают, что здесь код-стайл, все договоренности, все подключенные пакеты, все версии пакетов везде одинаковые, и это очень сильно помогает переиспользовать разработчиков между различными проектами. +2056.56 2072.60 "Анатолий Кулаков" Если вдруг на одном проекте завал, а на другом есть свободные разработчики, они переходят, они кодируют в том стиле, в котором привыкли из предыдущего проекта и никаких проблем на код-ревью не получают, потому что в компании четко выстроена автоматическая проверка одного и того же стиля. +2072.60 2074.68 "Анатолий Кулаков" И это вообще прекрасно, это невозможно переоценить. +2074.68 2084.40 "Анатолий Кулаков" Ну и автор советует попробовать вам сделать такую же штуку, если в вашей компании есть какие-то код-стайлы, а тем более, если их нет, то их нужно сделать, упаковать. +2084.40 2091.00 "Анатолий Кулаков" И в качестве примера он приводит свой вот этот магический пакет, в котором они используют. +2091.00 2096.60 "Анатолий Кулаков" Этот пакет доступен на GitHub, поэтому можно посмотреть, какие правила выбрали ребята, как они это все упаковали. +2096.60 2104.64 "Анатолий Кулаков" Проект также есть на Nuget, то есть можно прямо их договоренности, прямо их рулы взять, подключить к себе и посмотреть, как оно будет работать. +2104.64 2115.24 "Анатолий Кулаков" Ну, я думаю, что именно их рулы вам будут не особо интересны, будет интересно, как они это сделали, что они смотрели, что они настраивали, потому что там действительно есть интересные флажочки, которыми они жонглируют. +2115.24 2133.76 "Анатолий Кулаков" В общем, подойдут они вам или не подойдут, это дело десятое, но полезный ресурс, куда посмотреть, что они там нащупали, он есть, поэтому пробуйте, дерзайте, стандартизируйте ваши репозитории, и это вам поможет в будущем в разработке и также в качестве и перформансе. +2133.76 2154.16 "Игорь Лабутин" Да, это однозначно полезная штука, унификация, даже если у нас нет миллиона разных всяких проектов, такая автоматическая унификация, которая не требует участия разработчиков и у всех работает абсолютно одинаково, это прям большая польза и действительно сильно сокращает время на код ревью и на вкатывание новых разработчиков и так далее. +2154.16 2156.32 "Игорь Лабутин" Так что полностью поддерживаю. +2156.32 2221.76 "Игорь Лабутин" Давай дальше, дальше у нас Andrew Log с попыткой запустить .NET в браузере без Blazor, понятное дело, что Blazor это штатный способ в каком-то смысле, то есть зачем вам еще .NET в браузере, если не Blazor, но в целом Blazor построен на Wasm, а с Wasm можно работать как, можно написать Blazor приложение, можно в принципе написать и заиспользовать Wasm в каком-нибудь сервер сайте, ну и можно вообще на .NET написать компоненты, которые совместимы со стандартом Wasi, да, это интерфейс, по сути, то есть некоторая спецификация, которая определяет как общаться между компонентами и тогда ваш компонент может быть вызван из других Wasm компонентов, если вам зачем-то это надо, но вот Эндрюс сосредотачивается на, по сути, первом варианте, то есть как можно поиспользовать Wasm в браузере, но не используя при этом Blazor. +2221.76 2227.64 "Анатолий Кулаков" У него была какая-то мотивация, то есть у него есть какой-то практический пример, который ему понадобился? +2227.64 2250.72 "Игорь Лабутин" Прям практического примера особо нету, скорее всего это его вечная любовь и любопытство раскопать как оно работает внутри, потому что фактически он разобрал как Blazor устроен, ну до некоторой степени, то есть такой микроблэйзер можно построить самому, по крайней мере в той части, которая обеспечивает запуск всего этого Wasm и как оно работает на самом деле. +2250.72 2258.40 "Анатолий Кулаков" В принципе похвально, похвально, да, это тоже хорошее его свойство, которое мы все время обозреваем и не нарадуемся, поэтому интересно посмотреть. +2258.40 2273.60 "Игорь Лабутин" Да, для того, чтобы со всем этим поработать и по-самому повторить, например, то, что происходит в статье, для начала вам нужны темплейты, ну можно конечно писать самому, но вам нужны кусочки SDK, которых по дефолту в поставке .NET нет, и вам нужно все это поставить. +2273.60 2296.08 "Игорь Лабутин" Значит, для начала, ну можно сделать .NET New Install Microsoft.NET Runtime WebAssemblyTemplates.NET 10, это добавит на вам три темплейта, либо WASI Console App, тот самый для реализации WASI, можно сделать WebAssembly Browser App и можно сделать WebAssembly Console App. +2296.08 2297.64 "Игорь Лабутин" Соответственно, три новых темплейта. +2297.64 2316.00 "Игорь Лабутин" Можно в принципе сделать .NET Workload Install Wasm Experimental, тоже в принципе нормальный вариант, но он поставит некоторое количество дополнительных всяких разных штук, про которые Андрю написал, он типа ставит какой-то став, что это за став и нафига он нужен, я не очень понял, поэтому типа я ограничился первым. +2316.00 2333.88 "Игорь Лабутин" А если же вы хотите потом ваше приложение там и что угодно делать еще в аут варианте, ну тогда нужно еще в Wasm Tools Workload, но надо помнить, что аут, он все-таки ну сильно влияет на размер и размер подрастет, если вы за аутите. +2333.88 2337.56 "Игорь Лабутин" Но тем не менее, если неинтересно, можно это сделать. +2337.56 2342.56 "Игорь Лабутин" Аут сейчас достаточно хорошо поддержан в .NET, что делаем дальше? +2342.56 2374.32 "Игорь Лабутин" Дальше мы, ну создаем новый Wasm Application с типом WebWasm Browser, то есть так и пишите в .NET New Wasm Browser, будет использоваться темплейт под названием Wasm Browser, вам создастся новая приложенька, и его можно сразу запустить, строечка достаточно длинная для запуска, то есть вы запускаете ее через Wasm App Host, указываете Use Static VWSS, указываете Рантайм Конфиг, указываете путь к вашему Рантайм Конфиг JSON, который там будет после сборки на месте, и вам все это запустится. +2374.32 2383.60 "Игорь Лабутин" У вас будет 2 URL, один соответственно для бэка, другой для фронта, ну и нормально можно что-нибудь поэкспериментировать. +2383.60 2398.96 "Игорь Лабутин" Стандартный темплейт, это просто обычный stopwatch, часы, control, секундомер, который показывает в браузере stopwatch и соответственно кнопочки там start, stop, pause и так далее. +2398.96 2419.84 "Игорь Лабутин" Дальше можно попытаться разобраться, а что же это за приложение, надо понимать, что с одной стороны, как мы вначале поговорили, что вроде бы практического применения для этого особо нет, но с другой стороны есть аж целый по сути шаблон для таких приложений, поэтому зачем-то это может быть вполне надо. +2419.84 2440.60 "Игорь Лабутин" Что происходит, во-первых, у вас есть некоторое количество обычного дотанет кода, который просто-напросто оборачивает stopwatch, ну создает экземпляр stopwatch, запускает некоторые run main из SDK, а также объявляет некоторое количество методов, которые аннотированы специальными атрибутами. +2440.60 2472.20 "Игорь Лабутин" Мы уже сегодня их упоминали, это атрибуты JS-import и JS-export, то есть JS-import позволяет вам заимпортить некоторую функцию, которая потом будет вызываться в джаваскрипте, то есть вы вызываете серфовый метод без тела, вы его объявляете как internal static partial, на данном случае partial void setInnerText и аннотируете атрибуты JS-import, передаете туда некоторую строчку DOM.setInnerText, потом посмотрим, что это такое будет, ну и файлик main.js, типа взять это из main.js. +2472.20 2489.84 "Игорь Лабутин" С другой стороны, вы можете сделать так, что ваш код на C# будет доступен джаваскрипту, для этого вы используете атрибут JS-export, то есть вы делаете вашу функцию, в данном случае, например, internal static bool isRunning, просто признак того, запущен или нет, аннотируете его JS-export, и эта функция может быть потом вызвана из джаваскрипт-кода. +2489.84 2493.76 "Игорь Лабутин" Потому что, ну, в правде говоря, пока совсем без джаваскрипта никак. +2493.76 2513.16 "Игорь Лабутин" При этом JS-import и JS-export — это атрибуты, которые source-генераторами разворачиваются в некоторые кусочки кода, которые правильно маршалят там все нужные джаваскрипт-типы, вы об этом не заморачивайтесь, они довольно эффективны из-за того, что это source-генератор, source-генерация. +2513.16 2514.16 "Игорь Лабутин" Дальше. +2514.16 2527.04 "Игорь Лабутин" Дальше у вас есть индекс html, он довольно простой, он референсит, собственно, вазам dotnet-runtime специальным тегом и содержит некоторое количество примитивной разметки. +2527.04 2532.24 "Игорь Лабутин" Типа кнопочка, элемент такой, элемент секой, просто html-ная примитивная разметка. +2532.24 2541.92 "Игорь Лабутин" И самое интересное, конечно же, происходит в JS-файлике, но без JS мы пока никуда не сможем без JS все это запустить, нам нужно каким-то образом монетизировать это все. +2541.92 2580.48 "Игорь Лабутин" Есть специальный JS-файл, расположенный в папочке подчеркиваем framework, называется dotnet.js, это собственно полный runtime dotnet, ну в смысле, это кусочек необходимый для инициализации dotnet в браузере, после чего мы получаем оттуда некоторое количество специальных методов, то есть set_module_imports, get_assembly_exports, эти две штуки нужны как раз чтобы сбандиться с JS-import и JS-export атрибутами, ну и get_config, это можно там конфиг получить, и run_main, это собственно самая главная основная функция, которая будет за все отвечать. +2580.48 2581.48 "Игорь Лабутин" Что мы делаем дальше? +2581.48 2617.08 "Игорь Лабутин" Дальше нам нужно рассказать, куда runtime должен идти, когда он встречает какой-нибудь вызов в dotnet, который отмечен атрибутом JS-импорта, для этого мы объявляем JSON-структурку в формате JSON, то есть как я говорил в JS-импорте мы писали DOM.set_intertext, поэтому в JS мы просто пишем JSON-объект, у которого есть property DOM, у которого есть property set_intertext, которое собственно имеет значение в виде лямбды, которое будет выполнено, когда вызван соответствующий метод C#. +2617.08 2702.80 "Игорь Лабутин" Дальше наоборот, нам нужно получить методы, которые мы можем вызывать с JS, для этого используется функция get_assembly_exports, она возвращает некоторую коллекцию экспорт, ну не коллекцию, а объект exports, у которого в качестве property есть те самые объекты, которые мы заэкспортили из объекта, точнее который создан в C# мире, с методами, которые соответствуют JS-экспорт, методам, которые помечены атрибутом JS-экспорт, то есть вот мы пометили точку из running, в смысле из running как атрибут JS-экспорт, поэтому мы можем вызвать export.stopwatch_sample.is_running, например, и узнать булевский ответ, true, false и так далее, то есть все нормально прекрасно работает, таким образом мы их сбайнили по большому счету, то есть мы сказали, что делать в одну сторону, что делать в другую сторону, ну и в этом случае теперь осталось все это просто запустить, для этого мы просто вызываем метод run_main, который нам предоставляет фреймворк, и фреймворк дальше будет, по сути все, что он делает, это кидает сообщения туда-сюда, ну маршалит сообщения между JS-рунтаймом и Wasm-рунтаймом, и таким образом, если Wasm-рунтайм требует что-то отрисовать, потому что мы в JS, то он соответственно все отрисует в JS и так далее. +2702.80 2861.68 "Игорь Лабутин" Для того, чтобы запаблишить такое приложение, мы используем стандартный dotnet_publish-c_release, и по дефолту то все это скомпилится, конечно, запаблишится, затримятся все ненужные фреймворковые кусочки, потому что это Blazor, и чем больше мы затримем, тем лучше, тем меньше будет размер, тем быстрее он будет грузиться, загазипится, я не знаю глагола от слова "бротли", сожмется короче газипом "бротли", мы про это рассказывали чуть раньше, там разные компоненты жмутся разным, и все это сложится сесть на ваутпут, например, на вот этом вот приложении, которое мы рассмотрели, то есть простое стартовое обычное тестовое приложение из шаблона, получается, что если мы просто все соберем, и не будем никак это все сжимать, ну с выключенным сжатием, то мы получаем 6.8 мегабайт, это, соответственно, довольно много для такого простого приложения, которое делает ничего, но если мы все это сожмем газипом либо "бротли", получится соответственно либо 2.5, либо 2 мегабайта, это все еще довольно много для такого простейшего приложения, я думаю, что на чистом JS, даже с каким-нибудь там, не знаю, css, до 2 мегабайт это явно бы не дотянуло, React, может быть, правда дотянуло бы, наверное, ну фиг знает, надеюсь, что все-таки нет, но при этом понятно, что довольно много из этого занимается андроидный трантайм, в эти 2 мегабайта он входит, поэтому в целом это не так уж и плохо, естественно, Эндрю пошел дальше и попытался понять, а что можно выпилить, ну единственное, что он попробовал, это стандартный вариант, если нам не нужна глобализация, если мы понимаем, что мы обходимся без этого, то есть какая-нибудь там, не знаю, админка, которая не требует какой-то хитрой глобализации и можно все сделать на английском, то тогда можно передать property invariant globalization, и в этом случае размер снижается где-то 30-37%, то есть получится где-то там 1,5 мегабайт или около того, чуть меньше, это, ну еще лучше, статья заканчивается выводами про то, что все это, весь этот подход, это гораздо более low-level, чем Blazor, конечно, вы не будете скорее всего такое использовать, берите Blazor и там будет все попроще, но понимать, как оно работает и если вдруг вам надо зачем-то прямо сделать такое низкоуровневое общение между Wasm и JS, то вот вы можете использовать эту статью как базу, тут показано общение в одну и в другую сторону, это минимально необходимый набор, чтобы хоть как-то поднять Wasm Runtime с дотнетом внутри браузера, дальше уже ваша фантазия подскажет вам, зачем этого может быть надо. +2861.68 2865.72 "Анатолий Кулаков" Может быть, если вы захотите, допустим, свой Blazor написать или свой UI-фреймворк. +2865.72 2876.36 "Игорь Лабутин" Ну, может быть, да, может быть, адаптировать какой-нибудь фреймворк к вот такому вот браузеру через Wasm, почему нет, например. +2876.36 2885.88 "Анатолий Кулаков" Ну или если, например, игру захочется написать на каком-нибудь конвасе, там же по идее нам Blazor сильно не нужен, нам нужен такой низкоуровневый доступ к конвасу как раз Wasm. +2885.88 2892.96 "Игорь Лабутин" По сути, да, по сути, да, и может быть иногда общение с JS для того, чтобы реагировать, ну, как с пользователем общаться. +2892.96 2897.24 "Игорь Лабутин" Ну или с браузером, например, там, редирект какие-нибудь чуть-чуть открывать и так далее. +2897.24 2900.96 "Анатолий Кулаков" Да, ну, в общем, практически use case, я думаю, можно придумать, если сильно захочется. +2900.96 2910.44 "Игорь Лабутин" Ну, мне кажется, для любой проблемы можно придумать, для любого технологии можно придумать практически use case, вопрос насколько будет такой нетривиальный. +2910.44 2917.24 "Игорь Лабутин" Ну, в общем, да, закопались в кишочке, поняли, как оно работает, если вдруг зачем-то надо, применяйте. +2917.24 2929.84 "Анатолий Кулаков" Ну, что ж, я хочу с вами теперь поговорить немножко о философии, об архитектуре, и тут попалась мне хорошенькая статья от Деррика Камартина, которая называется DDoM-маппинги. +2929.84 2947.00 "Анатолий Кулаков" В общем, Деррик это автор сайта CodeOpinion.com, наверняка многие из вас могли сталкиваться с ним на ютубе или может быть на самом его блоге, автор довольно популярный и иногда проскакивают у него довольно интересные мысли. +2947.00 2989.68 "Анатолий Кулаков" Например, как и вот это, потому что DTO-шки, казалось бы, блин, примитивная простая тема, все про нее должны знать, все про нее должны уметь, но может быть в этом-то ее и проблема, потому что все к DTO-шкам относятся слишком легко, они думают, в общем, есть куча заблуждений, особенно у тех, кто покусан какой-нибудь Java разработчиком, которые приходят и начинают рассказывать, что DTO-шки должны быть на каждом слое вашего приложения, если у вас там у приложения 5 слоев, то вам нужно, соответственно, 5 DTO-шек на каждом слое, их нужно перемапливать, их нужно переиспользовать и вы понимаете, что рано или поздно вы тратите время не на программирование, а на то, чтобы маппить DTO-шки. +2989.68 3001.20 "Анатолий Кулаков" В общем, есть очень много заблуждений с DTO-шками, может быть, как раз потому, что они слишком простые, слишком легкие, всем понятно, как их маппить, всем понятно, как это автоматизировать и поэтому их применяют слишком бездумно. +3001.20 3009.68 "Анатолий Кулаков" Вот Дерек попытался разобраться, что же такое DTO-шки, зачем они нужны, когда их нужно использовать, когда не нужно использовать и надо их маппить или не надо маппить. +3009.68 3018.92 "Анатолий Кулаков" В общем, давайте вместе с ним посмотрим на его путь, на путь его рассуждений и выясним, а как же правильно все-таки использовать DTO-шки. +3018.92 3019.92 "Анатолий Кулаков" Погнали! +3019.92 3024.44 "Анатолий Кулаков" Погнали упрощать нашу жизнь, погнали делать программирование понятнее и проще. +3024.44 3039.76 "Анатолий Кулаков" Итак, DTO расшифровывается как Data Transfer Object, это довольно популярный шаблон проектирования, который используется много где и, в частности, используется очень часто неправильно. +3039.76 3045.40 "Анатолий Кулаков" Прежде всего, DTO нужна для того, чтобы передавать данные между различными слоями приложения. +3045.40 3051.92 "Анатолий Кулаков" В общем, и на этом определении обычно все заканчивают и начинают данные между всеми слоями всех приложений гонять. +3051.92 3057.36 "Анатолий Кулаков" В общем, надо вникать дальше, надо понимать, зачем они были изобретены и какие пользы могут к вам принести. +3057.36 3068.48 "Анатолий Кулаков" И очень часто DTO-шки применяются как раз таки, когда вам нужно передать данные от одного слоя представления в другой слой представления. +3068.48 3086.20 "Анатолий Кулаков" Особенно они актуальны, когда у вас cross-bounding, как какой-то край, например, если вы общаетесь с вашей базой данных, вы общаетесь с UI, вы общаетесь с каким-нибудь API, вот там DTO-шки, кажется, что нужны обязательно. +3086.20 3089.84 "Анатолий Кулаков" Почему, рассмотрим чуть позже. +3089.84 3102.76 "Анатолий Кулаков" Но очень часто DTO-шки вставляют не только в cross-bounding общение, но и в любое общение между любыми слоями приложения. +3102.76 3114.56 "Анатолий Кулаков" Одна из причин этой проблемы, которую Derrick видит, это в том, что неправильно интерпретируются сущности, то есть неправильно интерпретируются entity иногда. +3114.56 3116.28 "Анатолий Кулаков" Давайте посмотрим на примеры. +3116.28 3127.28 "Анатолий Кулаков" У нас есть, допустим, Entity Framework, который является ORM-кой, и для него Entity – это всего лишь навсего некий объект, который мапится на таблицу в базе данных. +3127.28 3141.88 "Анатолий Кулаков" И у нас есть DDD – Domain Driven Design, и там Entity – это уже уникально идентифицированная концепция домена, которая идентифицирует сущность, и она обозначает совершенно другое. +3141.88 3148.04 "Анатолий Кулаков" Но несмотря на это, и там, и там у нас четкое определение Entity есть, и там, и там оно называется Entity. +3148.04 3166.92 "Анатолий Кулаков" И вот это вот избыточное определение Entity, люди часто, вот из-за него люди часто создают DTO-шки для того, чтобы как раз-таки избежать раскрытия внутренностей сущности для вышележащих слоев, и поэтому люди создают DTO-шки. +3166.92 3171.84 "Анатолий Кулаков" Итак, давайте же посмотрим, зачем разработчики все-таки создают DTO-шки. +3171.84 3189.00 "Анатолий Кулаков" Прежде всего они хотят добиться того, чтобы не раскрывать подлежащие данные какой-то модели, особенно если это богатая доменная сущность какая-то модельная, и они боятся раскрыть ее какие-то внутренности другим слоям, которыми эти внутренности им не нужны. +3189.00 3205.36 "Анатолий Кулаков" Ну, допустим, если у вас есть какая-то ORM-ка, в этой ORM-ке есть сущность, которая мапится непосредственно на базу данных, и вы хотите отдать вот эту сущность, которую вы прямо достали из базы данных, в другой слой. +3205.36 3221.36 "Анатолий Кулаков" И для этого вы делаете какую-то DTO-шку, которая скрывает от вас вот эту абстракцию базы данных, которая скрывает от вас то, каким образом эта сущность, этот рекорд, он хранится в базе данных. +3221.36 3225.00 "Анатолий Кулаков" Поэтому вы делаете какую-то DTO-шку после загрузки и отдаете ее наверх. +3225.00 3230.64 "Анатолий Кулаков" В принципе, вполне валидное использование, так можно делать. +3230.64 3233.84 "Анатолий Кулаков" Нужно так делать или не нужно так делать, зависит от контекста. +3233.84 3237.72 "Анатолий Кулаков" Но давайте этот вопрос немножко опустим, а зададимся другим вопросом. +3237.72 3243.32 "Анатолий Кулаков" А почему бы в этом случае конкретно не отдать DTO-шку наверх? +3243.32 3246.32 "Анатолий Кулаков" Вот в том виде, в котором мы загрузили, в том виде, в котором она у нас есть. +3246.32 3248.04 "Анатолий Кулаков" Что, собственно, такого страшного случится? +3248.04 3254.44 "Анатолий Кулаков" И вообще, почему у нас автоматически срабатывает какой-то рефлекс, что мы обязаны сделать DTO? +3254.44 3260.80 "Анатолий Кулаков" Почему когда мы из одного слоя передаем DTO-шку в другой слой, мы сразу начинаем создавать DTO-шку? +3260.80 3264.88 "Анатолий Кулаков" Это даже не обсуждается, потому что между слоями они должны передаваться. +3264.88 3271.96 "Анатолий Кулаков" Эту проблему хорошо иллюстрирует, например, создание HTTP-апиаев. +3271.96 3282.20 "Анатолий Кулаков" Очень часто встречается приложение, которое перекладывает просто JSON-чики из одного DTO-шки в другую DTO-шку и в базку. +3282.20 3295.24 "Анатолий Кулаков" Представьте, у вас есть какой-нибудь сервис, у него есть HTTP-апиаи, и единственное, что оно делает, оно принимает какие-то запросы и по этим запросам входит напрямую в базу данных. +3295.24 3299.72 "Анатолий Кулаков" Выполняет стандартные CRUD-операции напрямую с сущностями с базами данных. +3299.72 3309.48 "Анатолий Кулаков" Например, если в базе данных у нас лежит какой-нибудь shipment, то на GET мы достаем shipment, на POST мы создаем новый shipment, на DELETE мы удаляем новый shipment. +3309.48 3312.92 "Анатолий Кулаков" В общем, все делаем один к одному, простое-простое приложение, линейное. +3312.92 3341.28 "Анатолий Кулаков" И в принципе, в этом нет ничего плохого, таких приложений очень много, они есть, многие их часто пишут, но плохо в нем то, что оно формирует в разработчиках очень стойкое убеждение, очень четкий путь, что вы всегда начинаете думать об API, как о тонком слое, тонкой оберточке над вашей базой данных. +3341.28 3351.20 "Анатолий Кулаков" И когда вы уже сталкиваетесь с непосредственно каким-то более сложным приложением, у вас вот эта мысль, она остается на месте. +3351.20 3366.60 "Анатолий Кулаков" То есть вы по-прежнему пытаетесь вот это сложное приложение натянуть на вот эту простую тонкую прослойку, которая должна всего лишь навсего сделать оберточку крут операций вокруг вашей таблицы в базе данных, но это не обязательно так. +3366.60 3383.60 "Анатолий Кулаков" Ваш API не обязательно должен быть тонкой оберточкой над таблицей, и те ресурсы, которые выставляет наружу ваш API, они не обязательно должны быть похожи на те рекорды, которые вы загружаете из базы данных, они не обязательно должны быть один к одному мапятся в эти рекорды. +3383.60 3399.56 "Анатолий Кулаков" Ну, например, если вы, допустим, захотите на сервере, на бэкэнде собрать HTML-страницу с тем же самым shipment, допустим, то вам недостаточно будет сходить в одну базу данных, достать оттуда shipment, допустим, его дату, его статус и все. +3399.56 3411.76 "Анатолий Кулаков" Если вы, допустим, захотите собрать HTML-страницу красивую для пользователя, то кроме непосредственно shipment, вам нужно будет подключить какую-то информацию, допустим, о кастомере. +3411.76 3418.64 "Анатолий Кулаков" То есть, кто заказчик этой доставки, когда он ее заказал, какое наполнение в этой доставке и так далее. +3418.64 3434.80 "Анатолий Кулаков" То есть вы все равно сходите в несколько таблиц, вы наберете оттуда много данных и сформируете непосредственно красивую, хорошую HTML-страницу или какой-нибудь JSON-ответ, но он будет довольно полный, он не будет маппингом один к одному на вашу таблицу. +3434.80 3452.16 "Анатолий Кулаков" И вот, когда вы это сделаете, вы поймете, что одна из возможностей DTO-шек – это как раз брать вот эту богатую композицию, это собирать вот эту богатую композицию, быть чем-то больше, чем оберточка над одной таблицей. +3452.16 3456.72 "Анатолий Кулаков" Поэтому Дерек предлагает вам смотреть на DTO-шки чуть шире. +3456.72 3461.68 "Анатолий Кулаков" Он вводит две основные концепции, для чего нужны DTO-шки. +3461.68 3467.20 "Анатолий Кулаков" Самая первая концепция, для чего нужна DTO – это как раз управление связанностью. +3467.20 3482.24 "Анатолий Кулаков" То есть, как только вам нужно развязать связанность между разными слоями, допустим, между каким-нибудь внешним слоем и внутренним слоем, вот тогда вам нужна DTO-шка. +3482.24 3486.28 "Анатолий Кулаков" И второе свойство DTO-шки, когда она нужна – это композиция. +3486.28 3495.04 "Анатолий Кулаков" То есть, как только вы хотите собрать какой-то ответ из нескольких источников, вот тогда вам тоже нужна DTO-шка. +3495.04 3504.16 "Анатолий Кулаков" То есть, вы ее можете собрать в какую-нибудь одну структуру, этой структуре придать какую-то другую форму, не такую, как эти данные хранились в этих источниках. +3504.16 3509.12 "Анатолий Кулаков" Можно их там прооптимизировать, переназвать, еще что-то сделать, каким-то образом преобразовать. +3509.12 3515.16 "Анатолий Кулаков" И вот правило композиции в том, что если вам нужна композиция, то вам тоже нужна DTO-шка. +3515.16 3530.50 "Анатолий Кулаков" Если вам композиция не нужна или ваша DTO-шка не разрывает связь между различными слоями, и при этом она существует, то, скорее всего, DTO-шка в вашем приложении используется зря. +3530.50 3533.12 "Анатолий Кулаков" То есть, вы просто делаете ненужную работу. +3533.12 3553.72 "Анатолий Кулаков" И каждый раз, когда вы изменяете ваши данные, например, на уровне базы данных, вы добавили какое-то поле, это вынуждает вас добавить это поле на уровне DTO-шки, протянуть ее через все уровни, которые она промаплена, что собственно добавляет сложность, усложняет сопровождаемость кода. +3553.72 3570.16 "Анатолий Кулаков" И все это без какой-то пользы, то есть никакой пользы вас от этого не будет, никакого смысла вот эти 10 DTO-шек перемапливать и тащить через все слои, не нужно было бы, вы вполне могли бы отдать ту структуру, которая изначально была загружена из базы данных, с точно таким же эффектом, но убрали бы всю эту сложность. +3570.16 3592.40 "Анатолий Кулаков" С другой стороны, если посмотреть, и вам нужно именно управлять связанностью и контролировать, например, что одному слою нужно видеть, а другому не нужно видеть, допустим, внутренний слой должен иметь об этом представление, внешний не должен иметь об этом представление, вот тогда DTO-шка становится очень, очень полезна. +3592.40 3608.12 "Анатолий Кулаков" Например, если вам нужно поменять структуру базы данных, и при этом следующий слой настолько абстрагирован, что он не зависит от структуры базы данных, он зависит именно от тех данных, которые возвращает, допустим, ваш репозиторий, то вот здесь DTO-шка будет очень-очень полезна. +3608.12 3618.84 "Анатолий Кулаков" Вы меняете структуру данных, при этом DTO-шка как гарантия контракта остается неизменной, и вам другой код на следующих уровнях никак трогать не нужно, он прекрасно живет и сам. +3618.84 3633.40 "Анатолий Кулаков" То есть он выполняет роль такого защитного слоя, и вот если вам вот эта роль защитного слоя, она используется, она вам нужна, она защищает ваши внутренние модели, она помогает вам избежать breaking changes, вот тогда DTO-шка имеет смысл. +3633.40 3643.60 "Анатолий Кулаков" Очень полезную практику он для себя завел думать об DTO-шках в разрезе двух терминов, это термины inside и outside. +3643.60 3645.12 "Анатолий Кулаков" Давайте подробнее про них разберемся. +3645.12 3705.60 "Анатолий Кулаков" Термин inside – это ситуация, когда данные в вашей системе должны быть скрыты, когда вам важны детали имплементации, такие, например, как схема базы данных, допустим, и вы не можете просто так эти данные открыть, потому что вы должны открыть данные для внешних каких-то потребителей, да, представим, что у вас есть какие-то внешние консюмеры, которые читают из вас данные, вот вы не можете просто так открыть схему базы данных, почему, потому что как только вы захотите базу данных поменять, а любой сервис обязан иметь право изменить хранилище или структуру хранилища и прооптимизировать как-то его, любой сервис обязан иметь возможность менять базу данных, вы не сможете этого сделать, потому что на ваш контракт уже будут рассчитывать какие-то внешние консюмеры, то есть ситуация, когда у вас данные, то когда вы должны скрывать ваши детали реализации, когда эти данные приватные, когда они находятся внутри вашего слоя. +3705.60 3730.30 "Анатолий Кулаков" И второй случай – это outside, это когда данные как раз публикуются наружу, когда, например, API-контракт у нас есть, да, API-контракт в ваших ТТП-контроллерах или мы можем, допустим, тот же пример – это месседжи, которые мы публикуем в очередь сообщений, то есть какие-то внешние контракты, внешний способ обмена с другими сервисами. +3730.30 3761.18 "Анатолий Кулаков" И вот контракт, он должен быть версионирован, он должен изменяться очень-очень осторожно, потому что при любом изменении ваши консюмеры, ваши потребители могут упасть, потому что приложение не должно контролировать всех своих консюмеров, оно не должно знать о всех своих клиентов, оно должно рассчитывать на то, что клиенты есть, они подписались на какой-то контракт и хотят этот контракт получать, поэтому мы не можем просто так наломать эти контракты. +3761.18 3763.82 "Анатолий Кулаков" Во всех этих случаях нужно создавать ДТО. +3763.82 3809.50 "Анатолий Кулаков" Если вы владеете обеими сторонами, то есть, допустим, обоими слоями, слой, который загружает вашу сущность из базы данных и слой приложения, который потом эту сущность использует, в общем, если и тот и тот слой под вашим контролем, если вы можете правильно управлять их связанностью, то вам не нужны ДТОшки, потому что ДТОшка внесет просто-напросто ненужную сложность, так как управление этими слоями в ваших руках, то при изменении одной сущности в одном слое, ее отображение в другом слое опять же будет полностью на вашей совести, никаких проблем, ни к чему плохому это не приведет. +3809.50 3839.02 "Анатолий Кулаков" Ежели вы опубликуете данные наружу, во внешних каких-то потребителей или вы хотите управлять вот этими слоями независимо, ну, допустим, если у вас разные команды отвечают за разные слои в одном приложении, извращение, наверное, может такое быть, и вы хотите независимо менять эти слои, то ДТОшки будут очень полезными. +3839.02 3855.42 "Анатолий Кулаков" Поэтому, задумываясь о ДТОшках в разрезе того, где они применяются внутри или снаружи, вы вполне можете составить картину, которая ответит на вопрос, а нужно вам его создавать или не нужно его создавать. +3855.42 3860.74 "Анатолий Кулаков" Еще один способ, как можно об этом подумать, может быть, он будет более применим к вашей практике. +3860.74 3876.02 "Анатолий Кулаков" Это как много потребителей есть у ваших ДТОшек, и насколько они зависят от как раз внутренней реализации той модели, которую вы пытаетесь перемапить. +3876.02 3891.94 "Анатолий Кулаков" Если у вас только один или два потребителя, и вы при этом контролируете связанность между слоями, то скорее всего вы можете вернуть непосредственно ту сущность, которой вы пользуетесь, без всяких ДТОшек, ДТОшки вам здесь не нужны. +3891.94 3903.54 "Анатолий Кулаков" Если у вас же 50 всяких потребителей, то это признак того, что вам нужен лишний слой абстракции, и вот этим с лишним слоем абстракции уже выступает непосредственно ДТОшка. +3903.54 3904.86 "Анатолий Кулаков" Зачем она в этом случае нужна? +3904.86 3907.94 "Анатолий Кулаков" Опять же, для того, чтобы не делать breaking changes. +3907.94 3915.90 "Анатолий Кулаков" 50 потребителей, если вы там удалите какое-то одно поле, то все они сломаются, это очень плохо, ну и при этом вы не контролируете каплинг. +3915.90 3931.30 "Анатолий Кулаков" Если же у вас здесь ДТОшка, то вы в базе данных удаляете какое-то поле, при этом в ДТОшке вы вставите какой-нибудь дефолт или какое-нибудь вычисление, или смотрите просто usage этого поля быстренько и думаете, как бы его зафиксить. +3931.30 3941.50 "Анатолий Кулаков" В общем, у вас там уже развязаны руки, вы уже можете каким-то образом, анализируя ваших консумеров, естественно, понять, каким образом эволюционировать данный контракт. +3941.50 3944.46 "Анатолий Кулаков" Поэтому по количеству потребителей тоже можно посмотреть. +3944.46 3947.90 "Анатолий Кулаков" Итак, когда же не нужно создавать ДТОшки? +3947.90 3952.58 "Анатолий Кулаков" Ну, во-первых, не нужно создавать только для того, чтобы создать ДТОшку. +3952.58 3959.78 "Анатолий Кулаков" То есть если для вас это догма, то есть вы видите какие-нибудь два слоя, говорите, что между ними ДТО – это обычно подход неправильный. +3959.78 3967.26 "Анатолий Кулаков" Для создания ДТОшки у вас четко должна быть причина, потому что любое создание ДТОшки – это внесение лишней сложности. +3967.26 3973.06 "Анатолий Кулаков" Сложности в код, сложности в поддержку, сложности в объяснении, в документацию и так далее. +3973.06 3978.24 "Анатолий Кулаков" Поэтому любая новая сложность, она обязана быть аргументирована. +3978.24 3987.42 "Анатолий Кулаков" Если вы не можете аргументировать это, кроме того, что в какой-то книжке что-то написали про передачу между слоями, то ДТОшку заводить не нужно. +3987.42 3989.70 "Анатолий Кулаков" Сначала разберитесь, зачем она вам нужна. +3989.70 3995.98 "Анатолий Кулаков" ДТОшки нужно создавать, если они решают настоящие какие-то проблемы, которые есть в вашем приложении. +3995.98 3997.98 "Анатолий Кулаков" Например, управление связанностью. +3997.98 4006.22 "Анатолий Кулаков" Например, создание композиции из нескольких слоев, мы собираем данные и формируем какой-то один конверт. +4006.22 4015.34 "Анатолий Кулаков" Например, для версионирования, для того, чтобы обеспечить стабильность контракта и его эволюцию в будущем. +4015.34 4019.14 "Анатолий Кулаков" Для того, чтобы, например, обеспечить стабильность контракта для публичных API. +4019.14 4023.74 "Анатолий Кулаков" Вот в этих местах четко и понятно, зачем нужны ДТОшки. +4023.74 4024.74 "Анатолий Кулаков" Без них там не обойтись. +4024.74 4026.34 "Анатолий Кулаков" Они дают там какую-то гарантию. +4026.34 4033.14 "Анатолий Кулаков" Их сложность там намного меньше, чем те плюсы, которые привносят ДТОшки. +4033.14 4038.78 "Анатолий Кулаков" Также не нужно ДТОшки делать избыточными. +4038.78 4048.78 "Анатолий Кулаков" Автор упоминает, что очень часто слышал кошмарные истории, когда одна ДТОшка мапится в другую ДТОшку и после этого перемапливается потом еще в другую ДТОшку. +4048.78 4062.02 "Анатолий Кулаков" И вот этот, опять же, глупый непонятный маппинг ДТОшки в ДТОшке и в ДТОшке ничего хорошего не приносит, кроме того, что добавляет сложность и никаких плюсов от этого настоящему приложению нет. +4062.02 4067.94 "Анатолий Кулаков" Итак, немножко суммаризируем, что же мы сегодня пообсуждали. +4067.94 4073.46 "Анатолий Кулаков" Когда и зачем использовать ДТОшки. +4073.46 4079.94 "Анатолий Кулаков" Во-первых, главные функции ДТОшки – это устранение связанности и дата композиции. +4079.94 4101.70 "Анатолий Кулаков" В ДТОшке помогает вам как раз избежать раскрытия внутренних деталей и помогает сформировать некий образ выходного результата для определенных потребителей и удержать этот образ как раз в стабильном зафиксированном контракте. +4101.70 4107.82 "Анатолий Кулаков" Не создавайте ДТОшки, если для вас это просто какая-то догма или договоренность, или вы так привыкли. +4107.82 4111.02 "Анатолий Кулаков" Это можно сравнить с какой-то преждевременной оптимизацией. +4111.02 4119.70 "Анатолий Кулаков" Если вы не понимаете, зачем вам ДТОшка, то, скорее всего, вы можете пропустить ДТОшку, и как только поймете, зачем она нужна, ее, в принципе, несложно добавить. +4119.70 4124.02 "Анатолий Кулаков" Поэтому изначально стоит идти по пути упрощения. +4124.02 4131.98 "Анатолий Кулаков" Если вы же поняли, что у вас есть какой-то контракт или вам нужна какая-то связанность, вот тогда можно ДТОшку добавить. +4131.98 4138.38 "Анатолий Кулаков" Иначе возвращайте, используйте просто ту сущность, которая у вас есть. +4138.38 4143.46 "Анатолий Кулаков" Не нужно бояться, что с ней что-то страшное произойдет. +4143.46 4156.54 "Анатолий Кулаков" Никогда не переусложняйте ДТОшки, то есть если у вас там есть миллион слоев, и у каждого слоя есть своя собственная ДТОшка, и ничего этот слой не делает, кроме того, чтобы маг папит одну ДТОшку в другую ДТОшку, а потом передает ее на следующий слой. +4156.54 4157.54 "Анатолий Кулаков" Вот все это чушь. +4157.54 4161.00 "Анатолий Кулаков" Все это ненужная сложность, и вот этим точно заниматься не стоит. +4161.00 4164.14 "Анатолий Кулаков" Это нужно почистить, удалить и никогда больше об это руки не вымазывать. +4164.14 4176.42 "Анатолий Кулаков" Думайте об вашем кодеке как о приватном и публичном контракте, как про внутреннем контракте и внешнем контракте. +4176.42 4199.02 "Анатолий Кулаков" И это должно вам помочь как раз таки определить, что если ДТОшка ваша внутри контракта, и она используется несколькими маленькими потребителями, там 1-2 потребителя, то она прекрасно нивелируется путем того, что используется обычная сущность, и эта сущность прекрасно меняется между слоями, и никаких проблем с этим нет. +4199.02 4218.46 "Анатолий Кулаков" Но если вам нужно зафиксировать какой-то контракт, если вам нужно версионировать публичный API, если у вас на этот API завязаны какие-то публичные контракты, публичные консюмеры, то просто так вы эту ДТОшку, ваши данные просто так менять не можете, поэтому контракт очень выгодно фиксировать в какой-то постоянной ДТОшке. +4218.46 4239.04 "Анатолий Кулаков" Вот так у нас получается такой расклад, может быть немножко запутанно, если хотите разобраться с большими примерами или с более красивым кодом, то милости просим на сайт автора, там же у него есть видосик, можно визуалом посмотреть, каким образом это оформляется, и выглядит уже непосредственно на ютубчике. +4239.04 4289.90 "Игорь Лабутин" Да, вечная тема, мне кажется, каждый раз, начиная какой-то новый продукт, проект, или даже просто небольшую опишку внутри, начинаются споры, что будем выставлять, нужно ли нам здесь делать ДТОшки, будем ли мы прям сущности эти фреймворка возвращать наружу, а что делать, если вот так, а что делать, если и так, а давайте, значит, какие-нибудь дополним их, потому что нам нужна какая-то специфическая форма JSON, ну в общем, каждый раз, мне кажется, эти обсуждения идут, и каждый раз пытаешься понять, где же та самая грань, чтобы действительно не получить себе 10 слоев, когда кто-то из команды приходит и говорит, давайте теперь еще и автомаппер заведем, потому что надоело маппить ДТОшки друг друга руками. +4289.90 4298.86 "Анатолий Кулаков" Вот кажется, что когда вы приходите с автомаппером, то, наверное, вот это вот тоже показатель того, что у вас слишком много лишних ДТОшек. +4298.86 4303.02 "Игорь Лабутин" Ну, наверное, это уже поздно, надо было раньше остановиться. +4303.02 4306.30 "Анатолий Кулаков" Ну, да-да, показатель того, что уже у вас все плохо. +4306.30 4310.38 "Игорь Лабутин" Ну, хорошо, давай посмотрим на последнюю тему на сегодня. +4310.38 4326.82 "Игорь Лабутин" Это довольно старая серия статей про мультитенантность, но она, несмотря на то, что старая, она написана для восьмого дотнет, она не потеряла своей актуальности, и она может быть весьма полезной, если вы хотите сделать что-то подобное или близкое. +4326.82 4328.18 "Игорь Лабутин" Сейчас поясню, о чем речь. +4328.18 4346.62 "Игорь Лабутин" Что вообще такое мультитенанс, это когда ваше приложение работает для, ну, предоставляет сервис кому-то, и вы хотите этих кому-то ассегрировать, то есть данные разных клиентов, разных компаний, например, если у вас клиенты для компании, расположить так, чтобы они не видели друг друга. +4346.62 4351.06 "Игорь Лабутин" То есть каждый из них будет считать, что они используют сервис, гробо говоря, в одиночку. +4351.06 4359.22 "Игорь Лабутин" Понятно, что, ну, они могут знать, что это шареный сервис, но критично важно не дать одним посмотреть на других. +4359.22 4362.06 "Игорь Лабутин" И это можно добиваться несколькими способами. +4362.06 4367.70 "Игорь Лабутин" Вы, в принципе, можете задеплоить несколько копий вашего приложения для разных клиентов, и это будет прекрасно работать. +4367.70 4371.38 "Игорь Лабутин" Каждый со своей базой данных, вот это все замечательно, все здорово. +4371.38 4380.18 "Игорь Лабутин" Только ресурсов требует огромное количество, плюс вам нужно поддерживать, соответственно, обслуживать кучу баз данных, кучу, возможно, сервисов, которые работают, не очень удобно. +4380.18 4384.38 "Игорь Лабутин" Можно сделать чуть более экономичный вариант. +4384.38 4419.74 "Игорь Лабутин" Вы можете задеплоить одно приложение, но для каждого тенента, то есть для каждого клиента вы используете свою базу данных, таким образом данные точно не пересекаются, но у вас возникает большая проблема с тем, что у вас есть одна версия кода, которая работает с большим количеством баз, вероятно, при росте количества клиентов вам нужно будет, соответственно, огромное количество баз данных, вам нужно будет каким-то образом поддерживать их схемы, плюс-минус, ну, более или менее одинаковыми, чтобы одна и та же версия кода могла с ними работать, в общем, огромное количество головной боли. +4419.74 4427.98 "Игорь Лабутин" Либо делается то, что называется sharded multi-tenant, когда вы делаете шарды для multi-tenancy в том или ином виде внутри одной базы. +4427.98 4441.02 "Игорь Лабутин" Можно делить физически на шарды, можно внутри одной базы как-то все, грубо говоря, во все таблички добавить колонку tenant_id и все данные, соответствующие одному тененту, всегда хранятся с нужным tenant_id. +4441.02 4455.66 "Игорь Лабутин" Самое главное, что вот в этом последнем случае вся изоляция вокруг тенентов, ну, кстати, в предпоследнем тоже в некоторой степени, она ложится на уровень кода приложения, вы деплоите одно приложение, вы деплоите условно одну базу данных, а все остальное вы делаете в коде. +4455.66 4462.58 "Игорь Лабутин" И для того, чтобы все это нормально работало, есть несколько требований к таким приложениям. +4462.58 4467.50 "Игорь Лабутин" Ну, во-первых, приложение должно уметь понимать, с каким тенентом оно сейчас работает. +4467.50 4480.06 "Игорь Лабутин" Это понятно, что в основном мы ведем речь про всякие веб-приложения, веб-API, и тут речь идет о том, что делать, как понять внутри конкретного запроса, к какому тененту относится этот запрос. +4480.06 4490.50 "Игорь Лабутин" Второй момент, у вас могут быть у разных тенентов специфичные какие-то настройки, или даже заинжекционные сервисы. +4490.50 4506.66 "Игорь Лабутин" Может так получиться, что, например, одни конфигурируют какой-нибудь модуль дополнительный, а другим этот модуль не нужен или нужна какая-то другая его реализация, ваших внутренних алгоритмов, и вы это сделали через инжекцион разных модулей и разных реализаций одного и того же интерфейса. +4506.66 4515.94 "Игорь Лабутин" Таким образом, получится, что для каждого тенента вам нужно, чтобы в рамках обработки одного запроса был заинжекцион тот или иной сервис, либо те или иные специфические настройки. +4515.94 4522.86 "Игорь Лабутин" Ну и, наконец, должна быть изоляция данных, т.е. тенент не может доступиться к данным другого тенента. +4522.86 4540.66 "Игорь Лабутин" Это обычно делается как-то на уровне запросов КПД, но, к сожалению, автор, видимо, предполагал эту серию статей продолжить как раз этой изоляцией, это можно сделать на уровне эти фреймворка, по-моему, кстати, мы даже обсуждали какую-то подобную статью, но, к сожалению, вот эта часть осталась не покрытой. +4540.66 4549.26 "Игорь Лабутин" Но две других, они интересны, потому что они правильные, показывают, как хорошо и удобно это можно заинтегрировать именно в S/P/Net Core. +4549.26 4559.34 "Игорь Лабутин" Значит, начнем мы сначала, начнем мы с того, что называется Internet Resolution, т.е. понимание, к какому тененту мы вообще должны относиться, обрабатывая заданный запрос, который к нам пришел. +4559.34 4565.90 "Игорь Лабутин" Ну и тут логика простая, мы берем что-нибудь из запроса и используем это что-нибудь для понимания. +4565.90 4580.90 "Игорь Лабутин" Это может быть доменное имя, т.е. если у нас сервис опубликован один, но к нему можно прийти по разным доменным именам, тогда у запроса можно посмотреть на заголовок host и узнать, по какому доменному имени к вам пришли, и, соответственно, вы будете знать, к какому тененту это относится. +4580.90 4584.26 "Игорь Лабутин" Можно, например, использовать что-нибудь из пути, т.е. +4584.26 4603.46 "Игорь Лабутин" например, у вас тенент — это часть пути, и все живут на общем домене, либо это может быть, например, заголовок, тоже вариант, какой-нибудь токен, не знаю, IDшник, UID заголовки, наличие которого однозначно определяет, к какому тененту вы относитесь, точнее, этот запрос конкретно и относится. +4603.46 4605.98 "Игорь Лабутин" Что нам, собственно, нужно сделать? +4605.98 4624.14 "Игорь Лабутин" Нам нужно его, эту информацию достать оттуда, откуда мы ее ожидаем, дальше понять, проверить, что этот тенент существует, загрузить какую-то, возможно, дополнительную информацию про него, ну и самое интересное — надо это все как-то заинтегрировать в Aspire.NET Core пайплайн. +4624.14 4664.18 "Игорь Лабутин" Причем поскольку мы можем работать, и вот эти настройки специфичные для какого-то тенента могут быть нужны на довольно ранних стадиях, включая различные middleware, то было бы неплохо это все встроить на как можно более самый ранний этап обработки, и в статье предлагаются кусочки кода, как это сделать, с помощью iStartupFilter, зарегистрировать максимально ранние middleware, и дальше показывается также, как сделать специальный класс, который называется TenantAccessor, который позволяет в любой момент времени в любом месте вашего кода получить вашего текущего тенента, с которым вы работаете. +4664.18 4718.70 "Игорь Лабутин" Идея абсолютно похожа на то, как работает httpContextAccessor, ровно такая же идея с AsyncLocals, насколько я понимаю, чтобы они правильно переживали всякие асинк методы, асинк в смысле вызовы методов, но интересно посмотреть на код, он там попроще, чем в httpContextAccessor, и вполне можно использовать в ваших проектах, даже если вам не нужны тененты, но вот такую штуку, которая глобально проставляется в middleware и потом дальше где-то используется может быть полезной, хотя я такое использовал только для всяких технических штук, типа какой-нибудь, ну не логгер, логгер мы обычно просто инжектируем или создаем как поле, но какие-то более такие диагностические необязательные для бизнеса штуки, все-таки бизнес-сценарий я бы не завязывал на какую-то такую информацию, которая где-то в глобальной по сути переменной лежит. +4718.70 4735.14 "Игорь Лабутин" Дальше, ну хорошо, мы допустим поняли, что какой тенент нам нужен, мы даже поставили в tenant-accessory, проставили текущего тенента и теперь нужно сделать самое, пожалуй, сложное. +4735.14 4740.78 "Игорь Лабутин" Это сделать так, чтобы у нас Dependency Injection Container правильно все резолвил. +4740.78 4745.70 "Игорь Лабутин" Значит, как оно работает внутри FastPay.NET Core обычно? +4745.70 4757.06 "Игорь Лабутин" Обычно у вас есть некоторый стандартный рутовый так называемый iservice provider, который вы на самом деле и конфигурите, когда вы описываете ваше дотнет-приложение. +4757.06 4781.78 "Игорь Лабутин" В момент обработки запроса, соответственно, из этого провайдера создается некоторый scoped provider, который будет как раз создавать все scoped ваши объявленные зарегистрированные сущности в scoped-варианте и в конце обработки запроса такой scoped-провайдер просто разрушается, ну закрывается, используется и, соответственно, используются все scoped-сервисы, связанные с ним. +4781.78 4799.50 "Игорь Лабутин" Так вот нам нужно сделать этот scoped не просто так, чтобы он не просто был созданный scoped-провайдером от имени SP.NET Core, а нужно, чтобы он был создан так, чтобы в нем уже были специфические для тенента какие-то возможные сервисы, либо чтобы он был, по крайней мере, настроен соответствующим образом. +4799.50 4803.26 "Игорь Лабутин" Ну, для этого, собственно, есть все необходимые механизмы. +4803.26 4812.14 "Игорь Лабутин" То есть, во-первых, мы создаем новый сервис-провайдер в Factory, который, соответственно, и будет создавать. +4812.14 4866.42 "Игорь Лабутин" Берем внутри простую штуку, мы берем сервис Collection, создаем новый сервис Collection, копируем все сервисы из рутового контейнера, потом, соответственно, мы берем тенент-специфичные конфигурации, которые у нас записаны специальным образом, когда мы конфигурируем это все, и применяем их, соответственно, к этой сервис-коллекции, и потом после этого мы, если, допустим, тенент добавил какие-то специфические штуки в этот сервис Collection, они не попадут в рут, и они будут видны только внутри обработки этого запроса, ну, и потом заменяем через IServiceProviderFeatures одну, один сервис-провайдер на другой сервис-провайдер, то есть S/PanelCore предлагает некоторый набор так называемых feature-интерфейсов, как я их обычно называю. +4866.42 4892.86 "Игорь Лабутин" То есть это интерфейсы, а не что-нибудь feature, которые позволяют доступаться ко всяким внутрянки S/PanelCore, вот как раз IServiceProviderFeatures позволяет заменить сервис-провайдер, и мы заменяем на новый сервис-провайдер, и именно он дальше S/PanelCore будет использоваться для создания всяких scope-сервисов, когда будут создаваться стандартные штуки или если вы будете звать внутри BeginScope и что-нибудь создавать, вот как раз самый сервис-провайдер будет использоваться. +4892.86 4922.46 "Игорь Лабутин" В результате, когда вы внутри, в конфигурации вашего приложения будете говорить BuilderServicesAddMultiTenancy, AddMultiTenancy будет возвращать некоторый стандартный билдер, который написан тоже, и у него будет функция, называется WithTenantServices, которая позволит, приняв к себе сервис и тенант, каким-то образом настроить, возможно, какие-то специфические штуки в зависимости от того, например, какой это тенант или что-то подобное. +4922.46 4930.38 "Игорь Лабутин" Ну и последний компонент, который тоже очень важно поменять и который, скорее всего, вам будет нужен разным в зависимости от разного тенанта, это опции. +4930.38 4960.70 "Игорь Лабутин" Вообще в Тотнете, мы когда-то очень давно описывали всю эту механику работы с опциями, в AndroLog поищите, есть серия, чтобы я помнил, по-моему, из десяти статей на тему того, как все эти опционы работают, потому что там есть iOptions, есть iOptions, мониторы, всякие, ну, короче, огромное количество всех разных опционов, которые позволяют либо статически резолвить опции, либо мониторить за ними, смотреть, что они изменяются, изменять в момент, когда они изменились, пропагедировать эти изменения, уведомлять об этом. +4960.70 4961.70 "Игорь Лабутин" В общем, много чего. +4961.70 4964.90 "Игорь Лабутин" Есть соответствующие интерфейсы, iOptions, что-нибудь. +4964.90 4982.20 "Игорь Лабутин" И мы делаем следующим образом, мы реализуем эти интерфейсы новыми классами, которые будут уже тенант-специфичными, мы расширяем TenantBuilder, это тот, который возвращается из AdMultiTenancy, чтобы можно было настроить, соответственно, отдельные конфиги. +4982.20 4996.90 "Игорь Лабутин" Методом, например, называем его withTenantConfigure, который, применяя, принимая, опять же, Options и Tenant, позволяет, например, в зависимости от Tenant, что-то конфигурить. +4996.90 5009.02 "Игорь Лабутин" Если, напомню, что из Tenant мы загрузили, у него могут быть какие-то флаги настроек, которые мы хотим, в зависимости от этих флагов, мы можем настраивать по-разному именно опции внутри S/Pen&Core. +5009.02 5040.24 "Игорь Лабутин" На этом серия статей заканчивается, к сожалению, автор обещал ее дописать, но так пока руки у него и не добрались, наверное, видимо, уже и не доберутся, но вот эти три статьи, они показывают очень кратко по делу и без воды, как встроиться в стандартный pipeline S/Pen&Core, если вам нужно что-то сделать с сервис-провайдерами и подменять их на лету внутри запросов или что нужно сделать с Options, если вы хотите как-то их тоже отдельно подменять в разных запросах за чем-то по-разному. +5040.24 5047.54 "Игорь Лабутин" Очень хороший практический гайд, может пригодиться, если вам вдруг зачем-то это надо, советую почитать. +5047.54 5085.06 "Анатолий Кулаков" У меня реже довольно приходилось делать мультитенансные приложения, но гораздо чаще возникали всякие инфраструктурные задачи, которые как раз таки решались через вот эти все хаки, которые описаны в статье, поэтому статьи целой серии с трех частей действительно классные, интересные, и если вдруг вы не знали, как можно поднастроить S/Pen&Core, или контейнер, или опции, то вот это хороший пример того, как открыть внутрянку и немножко сделать там своей собственной магией, на практике довольно часто все-таки пригождается. +5085.06 5094.10 "Игорь Лабутин" Ну да, ну чувак, давай кратенько пробежимся по коротким нашим новостям, вкратко разным, и будем раздругляться на сегодня. +5094.10 5106.50 "Анатолий Кулаков" Давай, есть, вышла статейка про EF Core Visualizer, это сложно блин прям как-то описать, кроме того, что это визуалайзер EF Core. +5106.50 5112.18 "Анатолий Кулаков" В общем, у EF Core есть запросики, эти запросики идут к базе данных. +5112.18 5123.46 "Анатолий Кулаков" В общем, очень часто вообще бывает, первая проблема, да, очень часто бывает, нужно посмотреть, какой SQL-запрос сформирует сам EF Core, то есть что он туда, какой SQL пошлет в базу данных. +5123.46 5130.26 "Анатолий Кулаков" Это несложно сделать с помощью стандартных средств, то есть есть логирование у EF Core, и можно заставить его писать в консольку эти запросы. +5130.26 5133.74 "Анатолий Кулаков" Не то чтобы очень, конечно, удобно, но вполне терпимо. +5133.74 5143.06 "Анатолий Кулаков" Также вот это логирование, оно вполне умеет определять медленный запрос, он там говорит, что запрос просто столько-то времени исполнялся, наверняка он медленный. +5143.06 5155.98 "Анатолий Кулаков" Но, в принципе, вот если вы отлаживаете ваше приложение, то вам вот это, первые этапы, это, конечно, хорошо, посмотреть на сам запрос, узнать, что он медленный, но хочется немножко больше. +5155.98 5158.46 "Анатолий Кулаков" Хочется, например, посмотреть план выполнения запроса. +5158.46 5169.26 "Анатолий Кулаков" И для того, чтобы посмотреть план выполнения, уже вам нужно будет открывать какие-то специальные редакторы, вставлять там запрос, что-то с ними делать. +5169.26 5175.60 "Анатолий Кулаков" А вот этот плагин позволяет вам смотреть план сразу непосредственно из студии, прямо из-под дебаггера. +5175.60 5197.40 "Анатолий Кулаков" То есть у вас есть, допустим, обычный EF Core контекст, там выполняется какую-то линку, вы можете прямо в Visual Studio жмакнуть на специальную кнопочку под дебаггером, и он вам откроет специальное окошко, в котором будет написан скреж-запрос, который пойдет в базу, и плюс еще весь план, план выполнения запроса, который будет выполнять база данных. +5197.40 5205.10 "Анатолий Кулаков" Более того, план этот не просто какой-то абстрактный мусор. +5205.10 5209.90 "Анатолий Кулаков" План этот рассчитывается с точностью до непосредственно самого движка. +5209.90 5220.38 "Анатолий Кулаков" То есть, естественно, плагин сам не может вам выдумать, какой план будет выполнять SQL Server или Postgre, а он запрашивает этот план у непосредственно движка. +5220.38 5234.94 "Анатолий Кулаков" И, естественно, возникает первая проблема, что у каждого движка свой формат планов, свой формат возвращения в свои протоколы и так далее, и этот плагин прекрасен как раз тем, что он объединяет внутри себя все самые популярные базы данных. +5234.94 5255.90 "Анатолий Кулаков" Это SQL Server, Postgre, SQLite, MySQL, Oracle, в общем, он умеет к каждому движку, к каждому серверу базы данных обращаться по ее собственному протоколу, доставать их собственный план выполнения, и гениальное изобретение в том, что под каждый движок он рендерит его план с помощью рендера этого движка. +5255.90 5272.50 "Анатолий Кулаков" Например, если вы привыкли к SQL-серверным планам, наверное, самым лучшим на рынке, которые только есть для визуализации, из MS SQL Studio, то от Visual Studio с помощью этого плагина вы получите практически такую же визуализацию. +5272.50 5274.46 "Анатолий Кулаков" Она будет настолько же прекрасна. +5274.46 5281.10 "Анатолий Кулаков" Ну и ко всем остальным, насколько уродлив SQLite или Oracle, вы такой же уродливости получите. +5281.10 5288.18 "Анатолий Кулаков" Ну, в общем, если движок предоставляет хороший план и хороший рендерер, то плагин прекрасно это рендерит. +5288.18 5292.98 "Анатолий Кулаков" Если нет, то вы не получите ничего хуже, а будет все точно так же, как вы и привыкли. +5292.98 5299.86 "Анатолий Кулаков" В общем, удобная штука, смотреть SQL-запросы, смотреть планы прямо под дебаггером, вообще классно. +5299.86 5307.14 "Анатолий Кулаков" Следующая новость, это пост в блоге Microsoft о том, что вышел GPT-OSS. +5307.14 5314.70 "Анатолий Кулаков" Это очередная E-модель, но она немножко примечательна для нас, так что мне захотелось ее добавить в выпуск. +5314.70 5315.70 "Анатолий Кулаков" Примечательна над чем? +5315.70 5320.74 "Анатолий Кулаков" Во-первых, это модель от OpenAI, это сейчас лидер рынка моделей. +5320.74 5325.10 "Анатолий Кулаков" И, во-вторых, самое главное в том, что это модель с открытыми весами. +5325.10 5334.38 "Анатолий Кулаков" То есть это та штука, которую вы можете скачать к себе и запустить нормальную EI без привязки ко всяким облакам. +5334.38 5338.78 "Анатолий Кулаков" Эта моделька выходит в двух параметрах – 120B и 20B. +5338.78 5346.82 "Анатолий Кулаков" И 20B как раз таки прекрасна тем, что вы можете ее запустить даже на вашей рабочей машинке, потому что она требует всего-навсего 16 гигабайт памяти. +5346.82 5355.38 "Анатолий Кулаков" И 120B, в принципе, если у вас есть хороший сервак, то можно даже внутри корпорации запустить и 120B. +5355.38 5369.62 "Анатолий Кулаков" То есть вы можете запустить хорошую модельку на своем локальном ноутбуке или на корпоративном сервере от лидера рынка, которая работает очень даже прилично на самых последних технологиях и достижениях. +5369.62 5376.62 "Анатолий Кулаков" И самое главное, что вы не будете никуда, независимо от каких облаков или от других непонятных блокировок. +5376.62 5385.62 "Анатолий Кулаков" То есть она дает вам прежде всего прайвази, куда ваши данные не утекают, все хорошо, и прежде всего она дает вам бесплатность. +5385.62 5388.26 "Анатолий Кулаков" Потому что по сути ни за какие запросы вы после этого не платите. +5388.26 5394.34 "Анатолий Кулаков" Все открыто, все open-source, все веса лежат в паблике и прекрасно устанавливается. +5394.34 5402.06 "Анатолий Кулаков" Более того, если вы используете какую-нибудь OLAMU, то там эта установка делается в пару кликов. +5402.06 5434.86 "Анатолий Кулаков" Есть анонс от OpenAI, но я дал ссылочку именно на майкрософтовский, потому что там сразу уже есть пример на C#, как использовать пакет Microsoft Extension AI и OLAMU# библиотеку для того, чтобы вот эту модельку прямо на вашем ноутбуке запустить, попробовать, замерить как раз, насколько приемлемо быстро или медленно она для вас работает, но самое главное – осознать, что все это, самая мощная, самая красивая и самая прекрасная моделька, бесплатна и ваши данные никуда не утекают. +5434.86 5438.70 "Анатолий Кулаков" Все это вы можете попробовать прямо на себе на ноутбуке. +5438.70 5446.14 "Анатолий Кулаков" Еще одна ссылочка – это захотелось отметить отдельный выпуск подкаста Бриславы Ложечкин. +5446.14 5450.42 "Анатолий Кулаков" Товарищи Бриславы Ложечкин в этом выпуске говорили про корпоративные метрики. +5450.42 5459.54 "Анатолий Кулаков" Выпуск даже так интересно называется – «Вред и бред», или «Бред и вред», в общем, смысл тот же – «Вред и бред корпоративных метрик». +5459.54 5477.66 "Анатолий Кулаков" Они как раз рассуждают о том, чем плохи корпоративные метрики, что в них такого, что заставляет всех сотрудников страдать, почему они вредят организациям больше, чем помогают, и как избежать вот этого вреда, и как вообще с метриками работать. +5477.66 5511.50 "Анатолий Кулаков" В общем, очень частый бич компаний – это то, когда компания пытается сделать какие-нибудь метрики на сотрудников, тем более на разработчиков, и очень хорошо послушать именно с точки зрения менеджеров, почему это не работает, и каким образом все вот эти метрики сломаны, и каким образом вообще можно хоть как-то померить, что происходит в компании, и интересные, там есть интересные примеры с работ Ложечкина, он работал очень много в Майкрософте. +5511.50 5522.06 "Анатолий Кулаков" В общем, есть интересные примеры о том, как в Майкрософте пытались внедрить всякие корпоративные метрики, что из этого вышло, как их хакали, и почему там рано или поздно от них отказывались. +5522.06 5540.26 "Анатолий Кулаков" В общем, выпуск довольно интересный, практически много классных баек, ну, я думаю, если в вашей компании менеджеры пытаются очень сильно насаждать вам всякие зарплату в зависимости от строк чек кода и прочей глупости, то им тоже можно дать послушать довольно интересный выпуск от авторитетных людей. +5540.26 5545.38 "Игорь Лабутин" Подтверждаю, Брислав и Ложечкин, прям шикарный подкаст, с удовольствием слушаю каждый выпуск, жалко, что выходит раз в месяц. +5545.38 5628.54 "Игорь Лабутин" Я наткнулся на проект, сам не попробовал, но выглядит прям очень интересно, называется «Консолония», и название как бы намекает, что он немножко связан с Авалонией, действительно, по сути Авалония для консольки, то есть вы точно так же как для Авалонии рисуете в экзамле ваше приложение, лэйаут, там все дела, окошки, кнопки, рамочки, скролл и вот это все, а он это все, этот проект рендерит в консольке, причем там поддержано огромное количество контролов, просто надо только понимать, что, ну, рендер Авалонии, он умеет работать с пикселями, а у вас вроде как консолька, и они решили эту проблему довольно эстетичным способом, у них один пиксель равен одному символу консоли, поэтому если вы делаете, например, прямоугольник 10 на 10 пикселей, он займет собственно 10 на 10 символов в консольке, ну и весь лэйаутинг соответственно работает так же, вот, есть забавный момент, что у такого пикселя, у него на самом деле получается как бы три характеристики, два цвета и символ, который может быть выведен, то есть цвет фона, цвет самого символа и сам символ, который тоже можно считать в некотором смысле как бы, ну, таким, псевдоцветом, да, потому что он может использоваться для того, чтобы так или иначе отрисовывать различные линии, там, не знаю, углы и так далее. +5628.54 5631.02 "Анатолий Кулаков" Да, стиль границы такой, стиль линии. +5631.02 5648.34 "Игорь Лабутин" Да-да-да, при этом поддержано нативное всякое рисование линий, прямоугольников, границы, битмапы даже можно пытаться выводить, но понятно, что какой-нибудь большой битмап вы не выведете, потому что, напомню, один пиксель — это один символ, вот, но какой-нибудь маленькие иконочки зачем-то отрисовать в виде битмапа можно. +5648.34 5687.98 "Игорь Лабутин" При этом, согласно Вики, там есть страничка довольно длинная, то есть у меня она где-то играла 3 или 4 с полным списком контроллов в Авалонии, насколько я понимаю, и почти все эти контроллы имеют рядом с собой зеленую галочку в том смысле, что они поддержаны, всякие дропдауны, списки, вот это все, это все поддержано, все работает, и поэтому скорее всего, если у вас есть какое-то ваше приложение, то может быть даже его можно с помощью этого проекта показать и в консольке, чтобы оно работало, вопрос только конечно в размере и лайаута, потому что понятно, что у вас наверное будут какие-нибудь минимумы, не знаю, 300 на 300, и это в консоль уже не влезет. +5687.98 5701.86 "Игорь Лабутин" Также есть ряд специфических контролов, которые нужны только в консоли, ну например, курсор, который вы можете в какой-то из клеточек нарисовать, например, чтобы подсказать, что в ней нужно что-то вводить, ну и другие там специфичные для консольки. +5701.86 5723.70 "Игорь Лабутин" А также, если вам вдруг почему-то не нравится разметка в XAML, и вы хотели бы использовать Razer разметку, то есть специальная библиотечка для этого проекта, называется Consolonia.Blazor, которая позволяет писать в таком Razer Blazor синтаксисе, а потом это вместо XAML, но при этом это все еще полноценная авалония. +5723.70 5736.78 "Игорь Лабутин" В общем, если вы вдруг зачем-то хотите написать такое интерактивное UI, то что называется tool и приложение, да, TextUserInterface, то посмотрите, авалония, в принципе, неплохой продукт. +5736.78 5744.86 "Игорь Лабутин" А консольная версия, вероятно, тоже не самая плохая, особенно если это всего лишь изменение рендера на консольку, а вся внутренняя кухня остается как есть. +5744.86 5755.66 "Анатолий Кулаков" Ну и выглядит он шикарно, в принципе, все вот эти контролы, которые есть, там дататайм пикеры и все такое, сплиттеры, они великолепно выглядят, хорошо работают, судя по анимации, вообще классно. +5755.66 5758.50 "Анатолий Кулаков" Поэтому просто огонь, надо брать срочно. +5758.50 5765.18 "Анатолий Кулаков" Всем переходим, бросайте все ваши UI, надо писать настоящее приложение в консоли, тем более мы теперь умеем красивые приложения в консоли писать. +5765.18 5766.98 "Игорь Лабутин" Добро пожаловать в турбовижен времена. +5766.98 5771.90 "Анатолий Кулаков" Да-да-да, будем делать новые DE, наконец-то, которые не тормозит. +5771.90 5772.90 "Анатолий Кулаков" Точно. +5772.90 5782.34 "Анатолий Кулаков" В общем, классная штука, классная задумка, я вообще люблю XAML, хорошо, что у нас появляются инструменты, которые позволяют в консоли на XAML что-то прикольное делать. +5782.34 5783.34 "Игорь Лабутин" Будем пробовать. +5783.34 5829.98 "Игорь Лабутин" Ну, а на этом мы на сегодня будем завершаться, мы поговорили про то, что нас ожидает в пятнадцатом сушарпинг касательно юнионов, discriminated юнионов, мы посмотрели, как же мы можем распространять наши кодинг стандарты внутри компании на все проекты дотнеты путем единого нукет-пакета, в котором сразу все собрано, посмотрели, как устроен запуск дотнета в браузере без блейзера на голом базме, узнали, когда нужно использовать DTO, зачем и когда, может быть, не стоит и какие признаки, что вы это делаете зря, посмотрели, как один из вариантов можно устроить мультитенанс в S/4, ну и разобрали разные мелкие новости, которые нам попались, пока проходили время записи прошлого подкаста. +5829.98 5847.46 "Анатолий Кулаков" Я напомню, что в принципе мы будем на dotnext, который пройдет в Питере в этом году, и если вы докажете, что вы подписаны на нас на Boosty, то вас ждет приятный сюрприз, поэтому ищите нас, доказывайте, требуйте ваши подарочки, и до встречи на конференции. +5847.46 5848.86 "Игорь Лабутин" Да, всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-123.txt b/input/Radio/Transcriptions/RadioDotNet-123.txt new file mode 100644 index 0000000..7c5e5f8 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-123.txt @@ -0,0 +1,406 @@ +0.00 14.64 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Радио Тотнет выпуск 123, наверное, даже круглый в каких-то системах числения. +14.64 19.28 "Анатолий Кулаков" 123 выпуск, и в студии постоянный ведущий Анатолий Кулаков. +19.28 20.28 "Игорь Лабутин" И Игорь Лабутин. +20.28 21.28 "Игорь Лабутин" Всем привет. +21.28 34.32 "Анатолий Кулаков" И нам помогают наши замечательные помогатели, и среди них такие люди, как Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко. +34.32 37.16 "Анатолий Кулаков" Кстати, Оля пробежала 30 километров за 2,40. +37.16 40.08 "Анатолий Кулаков" Оля молодец, будь как Оля. +40.08 55.36 "Анатолий Кулаков" Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев и Юрий Лодейкин. +55.36 59.28 "Анатолий Кулаков" Друзья, спасибо всем, а также тем, кто пожал остаться неизвестным. +59.28 68.84 "Игорь Лабутин" А также нас поддерживает компания Altenar, которая разрабатывает масштабируемое и надежное решение для индустрии спортивных данных, которым пользуются по всему миру. +68.84 97.64 "Игорь Лабутин" В основе большинства продуктов, конечно же, тотнет C#, идеи не теряются, инженеры прекрасно работают с высоконагруженным реалтаймом, разработка международная, можно качать английский, можно использовать удобные IDE, облачные платформы, сотрудники могут продолжать карьеру в европейском офисе, ну а также ребята активно делятся опытом и проводят митапы, участвуют в конференциях, которая недавно прошла, в частности, выступают за докладами и следить за их новостями можно в Телеграм-канале. +97.64 105.84 "Анатолий Кулаков" А я напоминаю, что у нас есть Boosty и много других социальных сетей, где нас можно поддержать, оставить комментарии. +105.84 125.20 "Анатолий Кулаков" В частности, мы на Boosty записали закрытый выпуск разговорного клуба очередного, где Александр Ергин рассказал про свой опыт разработки IE-агентов, рассказал, что такое Rack, что такое эмбеддинги, как все это используют программисты, какие есть инструменты, как платить, что, где. +125.20 128.88 "Анатолий Кулаков" В общем, хороший такой практический выпуск у нас получился. +128.88 137.08 "Анатолий Кулаков" Поэтому всем, кто интересуется тем, как начать разработку с IE-агентами и использовать в повседневной жизни, выпуск должен быть очень полезный. +137.08 150.18 "Анатолий Кулаков" Также у нас прямо буквально на днях закончился .NEXT, поэтому хотелось бы сказать спасибо всем, кто посетил конференцию, кто нас встречал, кто передавал приветы. +150.18 151.98 "Анатолий Кулаков" Были очень рады всех видеть. +151.98 158.10 "Анатолий Кулаков" Действительно классно увидеть, услышать и увидеть с настоящих живых слушателей, которые слушают наш подкаст. +158.10 162.50 "Анатолий Кулаков" В общем-то, там же мы собирались нашим чатиком и раздаривали много-много подарков. +162.50 164.68 "Игорь Лабутин" Ну чё, пойдём к новостям? +164.68 167.78 "Игорь Лабутин" Сегодня у нас выпуск, посвящённый новостям Майкрософт. +167.78 181.72 "Анатолий Кулаков" Ну, неплохо-неплохо, хотя да, мы ожидали, что, в принципе, там будет какой-то ажиотаж у Майкрософта ближе к анонсам, но он даже здесь умудрился захватить на себя практически весь наш выпуск. +181.72 185.18 "Анатолий Кулаков" То есть, навыпускал тут кандидатов, инструментов и прочего. +185.18 186.64 "Анатолий Кулаков" И поэтому да, давай начнём. +186.64 199.18 "Анатолий Кулаков" Первая тема, о которой хотелось бы рассказать – это то, что вышел релиз «Кандидат 1» Дотнета 10-го, и это первый кандидат из двух запланированных. +199.18 200.18 "Анатолий Кулаков" То есть, ещё будем ждать второго. +200.18 233.82 "Анатолий Кулаков" Одна из самых интересных, наверное, новостей, которая нас здесь ожидает, это то, что для Дотнета 10-го Майкрософт рекомендует использовать Visual Studio 2026 Insiders, то есть бету, по сути, о которой мы поговорим немножко попозже, но смысл в том, что она сейчас находится как бы в бета-ветке, в тестировании, по сути, и очень многим пока не нравится из-за большого количества багов, из-за каких-то несовместимостей, ещё из-за чего-то, ну, бета она и есть бета. +233.82 234.82 "Анатолий Кулаков" Вот. +234.82 250.34 "Анатолий Кулаков" А на любые вопросы, а будет ли поддерживаться Дотнет 10-й в предыдущей студии 2022, Майкрософт стратегически молчит, что многих людей наводит на какие-то панические комментарии по всему интернету. +250.34 265.86 "Анатолий Кулаков" То есть, может быть, есть шанс, что в 2022-й студии не будет поддержки Дотнета 10-го, но пока мы об этом точно не знаем, поэтому подождём ближе к релизам, а на момент выпуска, на тот момент, пока мы записываем этот выпуск, ответа от Майкрософта всё ещё не последовало. +265.86 266.86 "Анатолий Кулаков" Поэтому ждём. +266.86 268.46 "Анатолий Кулаков" Хорошая интрига получается. +268.46 278.78 "Анатолий Кулаков" Кроме Visual Studio, в Дотнете 10-й можно попробовать Visual Studio Code, если поставить туда C#, DevKit и последнюю бету, опять же, Visual Studio Code. +278.78 291.90 "Анатолий Кулаков" Теперь пробежимся по нововведениям, их не то чтобы много, ну, в основном, по всем секциям можно отметить багфиксы, импрувменты, стабилити, перфомансы и прочее, что полагается делать в релиз-кандидатах. +291.90 298.22 "Анатолий Кулаков" Улучшаем, стабилизируем все библиотеки, но некоторые новые фишки всё-таки появляются, и вот про них хотелось бы поговорить подробнее. +298.22 305.98 "Анатолий Кулаков" В библиотеках, в библиотеках задекларировано API-комплит для постквантовой криптографии. +305.98 311.98 "Анатолий Кулаков" Это как раз та криптография, которая должна спасти нас от нашествия квантовых компьютеров. +311.98 320.22 "Анатолий Кулаков" Напомню, что как только придут квантовые компьютеры, они будут способны взломать практически все шифрования, которые у нас сейчас есть на планете. +320.22 327.18 "Анатолий Кулаков" Это не просто взломывание вашего HTTPS-трафика, который вы гоняете на веб-сайты и смотрите котиков. +327.18 340.10 "Анатолий Кулаков" Это все медицинские данные, все военные данные, все государственные данные, которые сейчас лежат довольно свободно в интернете и защищены, по сути, только криптографией. +340.10 348.50 "Анатолий Кулаков" Поэтому нормальные люди, нормальные разработчики, нормальные страны активно начинают вредрять постквантовую криптографию. +348.50 365.14 "Анатолий Кулаков" Microsoft в этом плане не отстает, а может быть даже бежит впереди вселенной всей, потому что в датной десятом уже будет такой хороший набор всяких постквантовых алгоритмов, который вполне может заменить в повседневной жизни обычные алгоритмы. +365.14 368.90 "Анатолий Кулаков" То есть там есть и шифрование, и подпись, и проверки, в общем, все, что надо. +368.90 380.82 "Анатолий Кулаков" Вот, поэтому объявлен API-комплит, это значит, что большинство API-ов стабилизировано, выведены из разряда экспериментальных и советуются к использованию. +380.82 391.06 "Анатолий Кулаков" А из прочей мелочи, это поддержка утф-конвертации между утф-8 и 16-ричными строчками в классе System.Convert. +391.06 401.86 "Анатолий Кулаков" В общем, теперь вы можете гонять строки и байты туда-сюда с использованием новомодных сигнатур типа Redundant Spanner от байтов, или просто Spanner от байтов, и так далее. +401.86 411.14 "Анатолий Кулаков" Улучшена поддержка типов Tensor, TensorSpan, Redundant TensorSpan, то есть тензорные API-ы появились еще в 9.NET, а сейчас они объявлены стабильными. +411.14 424.46 "Анатолий Кулаков" То есть с 10.NET они считаются стабильными, в них добавилось очень много полезных всяких фишек, в том числе GenericMath для тензоров, и с ними теперь можно писать синтаксис гораздо более короче и понятнее, вот благодаря математике. +424.46 428.14 "Анатолий Кулаков" Это, в принципе, все, что коснулось библиотек. +428.14 431.66 "Анатолий Кулаков" Следующей на очередь у нас под разбор попал ISP.NET Core. +431.66 446.14 "Анатолий Кулаков" Для Blazor там расширили персистентный стейд при навигации, то есть, допустим, если у вас есть какие-то Arid Only данные, которые очень редко меняются, то теперь вы можете их обновлять в фоне во время навигации. +446.14 460.66 "Анатолий Кулаков" Это, например, полезно, когда у вас есть закэшированные данные, которые, например, с кэша доставать относительно сложно, но при этом мы знаем, что они будут меняться довольно мало, и эти данные отображаются на UI, вот теперь их можно удобно хорошо обновлять. +460.66 488.22 "Анатолий Кулаков" Из приятного в ISP.NET Core Identity добавилась куча различных метрик, связанных с юзер-менеджментом, то есть такие, как, например, создание пользователей, смена паролей, установки всяких ролей, логины, логауты, двухфакторная аутентификация, в общем, все это пронизано полностью метриками, и можно рассматривать красивые графики и размышлять о том, что там интересного пользователь делает в ваших приложениях. +488.22 523.50 "Анатолий Кулаков" В Blazor и Minimal API подтюнили довольно много валидации, например, теперь атрибут валидации, Validation Attribute, можно применять не только к свойствам, но и к классам и рекордам, что довольно удобно, например, вы можете навесить какой-то Validation Attribute Limit 42 над классиком Point, над целым классом, и забацать ему кастомный валидатор, в котором уже разберете, что это такое, как валидировать весь класс Point и что должно происходить. +523.50 534.98 "Анатолий Кулаков" Это помогает описывать одним маленьким атрибутом над всем классом какие-то сложные валидации, которые не относятся к конкретному полю, а являются агрегацией ограничений на уровне всей структуры. +534.98 543.38 "Анатолий Кулаков" Добавился новый атрибут Skip Validation, то есть вы можете теперь не только захотеть валидировать, но и скипнуть валидацию. +543.38 560.10 "Анатолий Кулаков" Этот атрибут помогает вам пропустить валидацию на свойствах, параметрах, типах и нужен, когда вы используете одну и ту же модель для разных сценариев, например, в одном сценарии эта модель должна быть валидирована, а в другом не должна быть валидирована. +560.10 566.18 "Анатолий Кулаков" Довольно сомнительный, конечно, кейс, но, наверное, на практике в сложных ситуациях такое тоже нужно. +566.18 581.58 "Анатолий Кулаков" А еще интересная штука, это немножко изменили поведение JSON Ignore атрибута, в общем, если у вас над пропертивой на весь JSON Ignore атрибут, то теперь он также, такая проперти также скипается из валидации, то есть она не будет валидирована. +581.58 593.18 "Анатолий Кулаков" Это сделали специально для того, чтобы соблюсти какую-то консистентность между сериализацией и валидацией, то есть если мы это свойство не сериализуем, то в принципе валидировать ее не надо. +593.18 595.66 "Анатолий Кулаков" Ну, есть в этом какая-то логика. +595.66 606.86 "Анатолий Кулаков" Много нововведений коснулась OpenAPI схемы, то есть вот этого документа, который генерируется у нас вместо свэш-бакла, я напомню, его там заменили, и Microsoft теперь сама генерирует OpenAPI спецификацию. +606.86 613.78 "Анатолий Кулаков" Вот она продолжает улучшаться и, в принципе, такими довольно бодрыми темами, которыми свэш-бакла даже и не снилось. +613.78 636.18 "Анатолий Кулаков" Например, улучшена поддержка nullble-тайпов, теперь nullble-типы генерятся в one-off элемент для OpenAPI схемы, что лучше отражает, соответственно, тип, который будет представлен и помогает генераторам и компиляторам лучше понять, а что же ваш API выплюнет. +636.18 647.78 "Анатолий Кулаков" Добавилось описание свойств для рефов в OpenAPI спецификации и куча там и тоже улучшений и оптимизаций по генерации документа. +647.78 663.58 "Анатолий Кулаков" Еще в OpenAPI тоже такое довольно сомнительное какое-то нововведение, в общем, сделали так, что методы http, методы, которые не поддерживаются в спецификации, теперь не экспортятся в документ. +663.58 682.26 "Анатолий Кулаков" Ну, кажется логичным, зачем нам экспортить то, что не понимает спецификация, но при этом под раздачу попал query-метод, то есть query-метод, он не поддерживается в OpenAPI спецификации официально и поэтому сейчас он эксклудится из генерированного документа. +682.26 692.34 "Анатолий Кулаков" Проблема заключается в том, что, конечно, всякими свагер-UI'ами он, может быть, и не поддерживается, но существует куча сторонних тулзов, например, генераторы клиентов. +692.34 696.18 "Анатолий Кулаков" И вот генераторы клиентов вполне поддерживают различные вот такие расширения. +696.18 704.66 "Анатолий Кулаков" То, что выкинули из документа, ну, довольно спорное решение, лучше бы его оставили и выкинули просто из UI. +704.66 722.94 "Анатолий Кулаков" Тем, кто не знаком query-метод, мы его обсуждали тоже в подкасте, кратко напомню, что одна из самых больших проблем HTTP-API'ев, которые стоят перед современностью, это в том, что иногда мы хотим сделать метод get какому-то ресурсу и передать туда кучу параметров. +722.94 736.98 "Анатолий Кулаков" Например, это часто нужно для поиска, когда мы ищем какой-то объект и передаем ему там 200 полей для фильтров, для поисков, для всяких ограничений, то обычно в get query string эти поля не помещаются. +736.98 754.62 "Анатолий Кулаков" И хочется очень сильно засунуть их в body, но к сожалению метод get не поддерживает body, точнее очень много инструментов, которые проксирует метод get, такие как там всякие HTTP-прокси, HTTP-серверы, вот они не поддерживают get в body. +754.62 762.10 "Анатолий Кулаков" Поэтому считается, что засовывать body для get нехорошо, так делать нельзя. +762.10 770.26 "Анатолий Кулаков" И чтобы эту проблему решить, было введено даже новое ключевое слово, новый ключевой глагол для HTTP-метода, который называется query. +770.26 775.22 "Анатолий Кулаков" Query - это тот же самый get, но только в него можно засовывать body со всеми вытекающими. +775.22 786.18 "Анатолий Кулаков" Ну так вот, это прекрасное нововведение, которое мы ждем очень сильно во всех спецификациях и во всех инструментах, пока выкинули из OpenAPI схемы. +786.18 794.70 "Анатолий Кулаков" Ну, надеюсь в будущем, когда все-таки спецификация дойдет до рекомендации, это все вернут обратно и мы заживем счастливо. +794.70 798.22 "Анатолий Кулаков" Так, погнали еще про OpenAPI спецификацию. +798.22 806.22 "Анатолий Кулаков" Теперь используется Invariant Culture для форматирования чисел и дат, что довольно-таки удобно. +806.22 813.12 "Анатолий Кулаков" Это нужно для консистенции, опять же, чтобы те же самые генераторы, UI-ки показывали на интерфейсе все правильно и красиво. +813.12 823.34 "Анатолий Кулаков" И это дает возможность генерить даты и числа в одном и том же формате, независимо от того, под какой культурой запущен сервер. +823.34 835.98 "Анатолий Кулаков" Кстати, это довольно часто ошибка бэкенд-разработчиков, когда они не учитывают, точнее, наоборот, они полагаются на ту культуру, под которой запущен сервер. +835.98 852.90 "Анатолий Кулаков" То есть, если у них там сервер работает под какой-нибудь английской культурой и у них всегда чиселки форматируются в английской культуре, то они, в принципе, про это забывают очень часто, и это сопряжено с большим количеством ошибок. +852.90 865.38 "Анатолий Кулаков" Например, когда наш сервер вдруг запускается на каком-то другом дата-центре, который располагается, допустим, не в английской культуре, а в какой-нибудь испанской или бразильской, или аргентинской, или еще какой-то, то начинают все циферки, все даты ехать. +865.38 871.74 "Анатолий Кулаков" В общем, это типичная проблема разработчиков, которые не думают о той культуре, в которой они форматируют выходные строки. +871.74 876.36 "Анатолий Кулаков" Поэтому основная рекомендация – это все должно быть в инвариантной культуре. +876.36 889.58 "Анатолий Кулаков" Если вы бакенд-разработчик и почему-то преобразовываете эти флоуты, всякие даблы или даты в строки, то это обязательно нужно сделать в инвариантной культуре и потом выводить на экран. +889.58 899.30 "Анатолий Кулаков" Исключения составляют, конечно же, те области, где вы форматируете эти данные для пользователя, и пользователь живет в какой-то конкретной культуре. +899.30 901.42 "Анатолий Кулаков" Вот там нужно вам подстроиться под пользователя. +901.42 907.26 "Анатолий Кулаков" В общем случае, если вы делаете форматирование в строку, то всегда должны указывать культуру. +907.26 911.74 "Анатолий Кулаков" Если есть культура пользователя, то в нее, если нет культуры пользователя, то в инвариантную. +911.74 921.98 "Анатолий Кулаков" Вот как раз и майкрософтовцы наступили на этот же бак, то есть первая версия у них там с вами генерировался в текущей культуре, что выдавало иногда полную жесть. +921.98 925.66 "Анатолий Кулаков" В общем, теперь они справились и генерят все в инвариантной, за что молодцы. +925.66 931.62 "Анатолий Кулаков" Итак, к Entity Framework можно перейти в Entity Framework, но основные нововведения касаются SQL-сервера. +931.62 945.66 "Анатолий Кулаков" В SQL-сервере поддержали VectorSearch, это одна из новых фишек последнего SQL, то есть поддерживается векторный тип данных, функция VectorDistance и для того, чтобы засовывать им бейдинги. +945.66 954.74 "Анатолий Кулаков" В общем, все у нас введет в направлении AI, настолько, что даже SQL-сервер теперь научился хранить им бейдинги, ну, в принципе, почему бы и нет. +954.74 972.54 "Анатолий Кулаков" А также в SQL-сервере улучшена поддержка JSON Type, то есть у нас колонка может быть типа JSON и вы к ней можете обращаться через LINQ, через Entity Framework, через какие-то там специальные другие выражения и операнды. +972.54 975.98 "Анатолий Кулаков" В общем, все это поддерживается довольно хорошо. +975.98 982.06 "Анатолий Кулаков" Хотя мне казалось почему-то, что JSON Type в SQL-сервере уже давно был поддержан. +982.06 983.06 "Анатолий Кулаков" Странно. +983.06 985.02 "Анатолий Кулаков" Ладно, может просто улучшили. +985.02 994.86 "Анатолий Кулаков" И тут же есть анонс то, что улучшили сериализацию комплекс-тайпов, точнее, добавили возможность точно так же сериализовать комплекс-тайпы в JSON-колонку. +994.86 1004.74 "Анатолий Кулаков" Я напомню, что раньше комплекс-тайпы сериализовались только в колонке, которые располагались в той же таблице, в которой был главный тип. +1004.74 1006.86 "Анатолий Кулаков" Теперь они могут засериализоваться в одну JSON-колонку. +1006.86 1010.14 "Анатолий Кулаков" Что-то мне казалось, что такая штука тоже была. +1010.14 1013.90 "Анатолий Кулаков" Не знаю, может, просто для Postgre была, а не добавили для entity-фреймворка. +1013.90 1014.90 "Анатолий Кулаков" Для SQL-сервера. +1014.90 1015.90 "Анатолий Кулаков" Ну ладно, добавили-добавили. +1015.90 1016.90 "Анатолий Кулаков" Хорошо. +1016.90 1021.42 "Анатолий Кулаков" Что у нас по UI-фреймворкам? +1021.42 1026.58 "Анатолий Кулаков" .NET Mojave получил много всего интересного, естественно, performance, improvements. +1026.58 1030.30 "Анатолий Кулаков" Из того, что хотелось бы выделить, это расширенную диагностику. +1030.30 1034.94 "Анатолий Кулаков" То есть там добавили кучу всяких метрик, трекингов, диагностиков. +1034.94 1041.50 "Анатолий Кулаков" Наверное, самый большой плюс, который мы из этого получили, это в том, что теперь Mojave-ские приложения очень хорошо выглядят в Espire. +1041.50 1045.94 "Анатолий Кулаков" Как вы помните, в Espire там всякие красивые дэшборды, которые нам показывают. +1045.94 1048.38 "Анатолий Кулаков" Графики красивые, анимация там приятная. +1048.38 1056.22 "Анатолий Кулаков" Ну так вот, вся эта анимация, графика теперь распространяется хорошо и на моё приложение, потому что там куча-куча метрик, которые использует фреймворк. +1056.22 1061.70 "Анатолий Кулаков" У WinForm тоже есть куча всяких мелочей, контролов. +1061.70 1065.62 "Анатолий Кулаков" Из примечательного - полная поддержка DarkMode. +1065.62 1069.70 "Анатолий Кулаков" Ведь DarkMode уже давно вводили, давно тюнили. +1069.70 1073.06 "Анатолий Кулаков" И сейчас вот задекларировали, что всё, дотюнили, доввели. +1073.06 1079.22 "Анатолий Кулаков" Теперь все интегрированные компоненты полностью поддерживают тёмный режим, тёмную тему. +1079.22 1085.82 "Анатолий Кулаков" И, наверное, ваши WinForm-приложения, старые и красивые, заиграют теперь новыми тёмными красками. +1085.82 1094.34 "Игорь Лабутин" Ну, я бы сказал, что это похоже на релиз Кандидат в том плане, что нету каких-то прям прорывных фич. +1094.34 1098.58 "Игорь Лабутин" Всё довольно ровненько, тут что-то дофиксили, тут немножко улучшили. +1098.58 1108.06 "Игорь Лабутин" Но, пожалуй, вот только… Ну да, видимо, они потихонечку к релизу докидывают побольше метрик, чтобы это покрасивше смотрелось в том же спайре. +1108.06 1113.54 "Игорь Лабутин" Ну, как вот с примером спиноткора Identity и Мауи с метриками. +1113.54 1122.82 "Игорь Лабутин" То есть из каких-то больших штук это, пожалуй, только… Да я даже не знаю, есть ли тут что-то такое большое и суперважное. +1122.82 1125.22 "Игорь Лабутин" Не, мне кажется, что особо ничего такого нету. +1125.22 1127.10 "Анатолий Кулаков" Просто потихонечку полируем. +1127.10 1133.38 "Анатолий Кулаков" Причёсывание, всякие отладки, может быть там что-то недотянули, какие-то атрибутики проставляются. +1133.38 1137.54 "Анатолий Кулаков" Самое главное, что должно быть в релиз Кандидате, это стабильность и перформанс. +1137.54 1148.38 "Игорь Лабутин" Да, тем более обычно, я не знаю, как в этот раз, обычно Майкрософт говорил, что РЦ2 уж точно можно начинать использовать, и он полностью поддерживается, типа как продакшн. +1148.38 1167.86 "Анатолий Кулаков" Да, здесь тоже есть приписка, что релиз Кандидат 1 можно использовать в продакшне, но при этом у комментаторов, как я уже сказал, подгорает, потому что в продакшне Кандидат 1 использовать можно, а вот в Visual Studio, в который он поддерживается, новую, большими красными буквами написано, что в продакшне использовать ещё нельзя. +1167.86 1170.26 "Анатолий Кулаков" И вот они теряются, каким же образом-то это всё дело +1170.26 1171.26 "Игорь Лабутин" можно поддерживать. +1171.26 1173.46 "Игорь Лабутин" Иском онлайн, иском онлайн, как по-другому. +1173.46 1179.22 "Игорь Лабутин" Ну вот, а давай как раз про Visual Studio и поговорим, потому что есть у нас и про это статья. +1179.22 1186.22 "Анатолий Кулаков" Вот может сначала про перформанс, импруманс, это же Кандидат, ему обязательно нужны перформанс и стабильность. +1186.22 1198.66 "Игорь Лабутин" Ну, давай про перформанс поговорим, действительно, может быть так логичнее дополнить то, что вышло в РЦ1, и напомнить, что мы много раз рассказывали, сколько у нас 7 же превьюшек было, насколько я помню, или 8. +1198.66 1202.46 "Игорь Лабутин" Да, там что-то, да, хорошая такая пачка, я уже не помню. +1202.46 1204.90 "Игорь Лабутин" Седьмая точно была, вот я не помню, была ли восьмая. +1204.90 1212.70 "Игорь Лабутин" И в каждом из них что-то улучшали, и как обычно Стивен Кауп дописал свою мега-статью про то, что же там улучшили. +1212.70 1220.06 "Игорь Лабутин" Статья огромная, статья большая, я её, ладно, не буду врать, не прочитал, но просмотрел, постарался. +1220.06 1226.42 "Анатолий Кулаков" Тебе не кажется, что он её там уже с помощью ящики сгенерил, потому что она там, по-моему, такая очень огромная, очень большая. +1226.42 1246.02 "Игорь Лабутин" Мне что-то кажется, что он её пишет, ну, грубо говоря, итеративно несколько месяцев, то есть это не то, что он там сел в понедельник, и надо там к пятнице написать, а это прям работа, полномерно там, не знаю, по паре часов, по 3-4 часа раз в неделю посидеть, дописать какой-то очередной кусочек. +1246.02 1251.82 "Анатолий Кулаков" В чатике высказывались предположения, что он её специально пишет такой большой, чтобы поиздеваться над тобой. +1251.82 1253.74 "Анатолий Кулаков" У тебя как, после прочтения сложилось такое впечатление? +1253.74 1257.02 "Игорь Лабутин" Ну, на самом деле я что-то новое из неё даже узнал. +1257.02 1320.66 "Игорь Лабутин" Например, если прочитать первые 3 или 4 абзаца, можно много узнать о мультфильме "Frozen", я, честно говоря, пока читал первый экран, по сути, думал, что это не статья Тауба, а обзор мультфильма, вот, как-то он там очень потом от этого переходит к перформансу, но, ну, если серьёзно говорить, то там и дальше в теле статьи, если внимательно вчитываться, то можно узнать всякие детали того, как работают 3G-эксп-штуки внутри, как весь этот бэктрейк оптимизируется, например, или ещё всякие разные другие моменты, поэтому, если заинтересованы, если интересно посмотреть и что-то новое узнать, я рекомендую, может быть, пропускать все эти осебленные листинги, но как только вы увидите протянку простого текста без какого-то либо кода, ну или без вставок кода, так скажем, там, inline-код, понятно, какой-то может быть прямо в тексте, то рекомендую почитать, там сами довольно интересно и познавательно. +1320.66 1332.38 "Игорь Лабутин" Но давайте немножко пробежимся по тому, что я выцепил для себя за быстрые просмотры этой статьи в течение всего сегодняшнего дня, начиная с утра. +1332.38 1353.82 "Игорь Лабутин" Ну, во-первых, это, понятно, огромное количество микробенчмарков, при этом все эти микробенчмарки вы можете поставить у себя, там есть подробнейшие инструкции, что для этого нужно сделать, какой 3G-эксп-шу создать, и дальше микробенчмарки они в формате, когда копипастишь код целиком из конкретного бенчмарка, вставляешь, вставляешь с файлик, запускаешь, все работает. +1353.82 1355.94 "Игорь Лабутин" Ну, должно, я не пробовал, честно скажу. +1355.94 1381.86 "Игорь Лабутин" И начинается все, конечно же, с джита, джит это, наверное, самый главный кусочек, который, ну, наверное, ответственен за такое, то, что называется, ощущение перфоманса, то есть понятно, что туда контрибутирует большое количество всяких разных штук, и розлин может, и виртуальная машина, и проектор это все, понятное дело, обеспечивает, но все-таки джит это, наверное, самое главное, что приходит в голову, когда мы говорим про перфоманс. +1381.86 1386.78 "Игорь Лабутин" Чем оптимальнее мы сгенерим ассемблярный код, тем, понятное дело, быстрее будет выполняться наше приложение. +1386.78 1498.42 "Игорь Лабутин" И здесь довольно много у нас изменений в 10-ом дотнете, во-первых, это то, что объединено общим словом de-abstraction, то есть убирание абстракций, проблема, ну, не проблема, а факт состоит в том, что в дотнете, когда вы пишете на C# или на F#, ну, на чем угодно, на любом языке, который поддерживает дотнет, вы пишете довольно абстрактный код, в плане что у него довольно высокий уровень абстракции, это позволяет писать компактно, позволяет писать понятный код, использовать конструкции типа linq и прочие, ну, которые довольно хорошо выглядят и легко читаются, но являются довольно-таки проблемой, что ли, для джита, потому что в силу того, как оно сделано, в языке это приводит к тому, что если реализовывать все в лоб, то нужно реализовывать это все через вызов миллион разных функций, а фактически, ну, это будет долго и дорого, поэтому джит использует различные техники, чтобы это все соптимизировать, и конечно, одной из первых вещей, которая обозревается в статье, это object-stack allocation, мы про него уже много раз говорили, это возможность джита, когда он понимает, что заданный объект не будет покидать пределов функции, не будет передаваться никуда наружу, не будет возвращаться из этой функции, а используется только в самой функции, либо в тех, которые вызываются, и про них он тоже может гарантировать, что они не будут дальше никуда лезть, то тогда такой объект может быть залазирован на стэке и не тратить как бы хип, не тратить время garbage-коллектора, потому что такой объект, залазированный на стэке, не будет считаться кусочком хипа, и garbage-коллектор на него вообще смотреть не будет. +1498.42 1526.38 "Игорь Лабутин" В прошлом дотнете было уже зачатки этого поведения, и там для маленьких классов, состоящих из примитивных типов это уже выполнялось, сейчас потихонечку это дело развивается, мы явно рассказывали, что как раз для делегатов это завезли, для тех, которые точно никуда не деваются, то есть просто если вы объявляете какой-то локальный делегатик, то он конечно будет постараться его заоптимизировать так, чтобы его не надо было аллоцировать реально на хипе. +1526.38 1536.30 "Игорь Лабутин" Массивы он понимает теперь, что если функция например возвращает какой-то небольшой массив, или вы объявляете какой-то небольшой массив, то этот массив можно закинуть на стэк. +1536.30 1540.86 "Игорь Лабутин" В общем, уменьшаем аллокации памяти таким способом. +1540.86 1541.86 "Игорь Лабутин" Дальше. +1541.86 1547.50 "Игорь Лабутин" Дальше вторая штука, тоже довольно важная в GT, это де-виртуализация. +1547.50 1572.02 "Игорь Лабутин" То есть по умолчанию у нас довольно много методов являются виртуальными, вызовы через интерфейс являются всегда виртуальными, то есть нужно сходить в реальную таблицу методов того объекта, который вы пытаетесь через интерфейс позвать, из этой таблицы методов достать ссылку на нужный метод, ее вызвать, то есть это все лишние походы, они не такие, кажется, большие, но все равно тут наносекунда, тут наносекунда, и в итоге вроде долго. +1572.02 1581.46 "Игорь Лабутин" Но по факту, даже если вы дергаете что-то через интерфейс, по факту у вас за этим интерфейсом может в вашем каком-то конкретном сценарии быть всегда один и тот же класс. +1581.46 1587.54 "Игорь Лабутин" Ну например, вы там, не знаю, куда-то передаете IEnumerable, но там на самом деле всегда лист. +1587.54 1624.54 "Игорь Лабутин" И благодаря ProfileGuidedOptimization, то есть благодаря некоторой статистике, которую GT собирает внутри себя во время выполнения, он может сообразить, что за этим интерфейсом в этом месте всегда практически появляется лист.t и он соответственно добавляет нужные проверки, что если к нам пришел лист.t, то используем оптимальный вариант именно конкретно для листа.t, как будто было бы написано лист.t, то есть код, который будет выполняться дальше, будет знать, что он работает конкретно на листе, что открывает простор для следующих оптимизаций, зная, что там может быть с листом. +1624.54 1639.42 "Игорь Лабутин" При этом вот в 10.NET как раз-таки появился довесок, добавок к этой штуке, а именно нормальная работа, улучшенная работа с интерфейсами, которые на массивах. +1639.42 1661.54 "Игорь Лабутин" То есть у массивов есть, как вы понимаете, свои методы, которые тоже, они внутри себя реализованы, внутри runtime, которые реализуют там всякие I что-нибудь, и вот с ними были некоторые трудности, теперь в общем все это тоже де-виртуализируется, нормально работает и стала гораздо быстрее работа с массивами. +1661.54 1692.56 "Игорь Лабутин" И в результате всех этих оптимизаций даже в статье написан такой тейк, что вообще говоря, сейчас есть такой подход, что все говорят, вот, итерироваться по IEnumerable может быть не очень здорово, но это типа долго, да, дорого, гораздо дороже, чем допустим по какому-нибудь там IList или IReadOnlyList, поэтому давайте мы не будем передавать IEnumerable в аргументы, а будем требовать IList либо IReadOnlyList. +1692.56 1718.10 "Игорь Лабутин" Так вот со всеми этими оптимизациями, которые появились в 10.NET, Стивен говорит, что кажется, что в некоторых сценариях forEach по IEnumerable будет быстрее, чем forEach по IList, вот такой вот переворот, так сказать, подходов, и пора возможно будет пересматривать рекомендации того, как писать быстрый код. +1718.10 1723.46 "Анатолий Кулаков" Может, они сделают такую же поддержку для IList лучше, чтобы не переписывать? +1723.46 1729.18 "Игорь Лабутин" Ну, может быть, и какая-то она есть, но это все потихонечку развивается. +1729.18 1741.02 "Игорь Лабутин" Понятно, что они пытаются везде, но тут тоже надо понимать, что баланс того, сколько у джета есть времени, чтобы все это проанализировать, он все-таки бюджет конечен, поэтому посмотрим. +1741.02 2030.98 "Игорь Лабутин" Дальше, bound-чеки, ну bound-чеки, понятно, что тоже некоторая головная боль дотнета, дотнет у нас безопасный runtime, то есть он гарантирует, что вы точно не сможете обратиться за пределы массива, за пределы спана и так далее, и джет теперь научился делать такую штуку, что если вы, например, сначала, у вас есть какой-то спан, вы посмотрели на его пятый элемент, джет, естественно, в этот момент добавит туда bound-чек, про то, что если значит размер превышает необходимый индекс, наоборот, если размера не хватает, чтобы обратиться к нужному индексу, будет, конечно, индекс out of bound exception, но дальше, если вы при этом вызываете, следующей строчкой вызываете, там, span.slice от 4 элементов, то есть вы только что проверили, что пятый на месте, то есть на строчке span.slice от 4 точно ничего не сломается, мы уже проверили длину, раньше джет этого не понимал и добавлял туда bound-чек, теперь понимает и bound-чека лишнего не будет, вот, также есть еще такой момент, что если, например, мы придумываем код, ну, например, мы берем и заполняем в функции первые там, ну, в статье, по-моему, было типа 8 элементов массива, ну, прямо пишем код, там типа array от 0 присвоить 1, array от 1 присвоить 2, array от 3 присвоить 3, ну и так далее подряд, то в зависимости от того, какой массив мы передадите, ну, понятно, что там может быть индекс out of bound exception, потому что он может быть короткий, может быть длинный, казалось бы, давайте мы сделаем простую проверку, в самом начале первым напишем, что if длина массива больше, чем 8, то индекс out of bound exception, наоборот, меньше, чем 8, то сразу throw index out of bound exception, проблема в том, что так делать нельзя, в смысле вы-то в коде так можете написать, и тогда, естественно, оно будет работать, ну, оптимально, но JIT такое не имеет права вставить в самое начало, потому что это будет изменение поведения, отличие от той версии, когда у вас будет индекс out of bound exception просто так, без ваших проверок дополнительных, заключается в том, что если бы JIT добавил такую проверку в самом начале, то если вы передадите короткий массив, то вам прилетит обратный exception и полностью незаполненный массив, в то время как если, вот мой исходный код, который я описал, исполнять как обычно, то все элементы этого массива будут заполнены какими-то вот, пока хватало элементов, и только на несуществующем будет индекс out of bound exception, это изменение поведения JIT так не имеет права сделать, поэтому фактически JIT делает клонирование, теперь в десятом дотнете, ну, понятно, что это зависит от размера массива, но для некоторого не очень большого количества элементов, не очень большого кода, окажется, что это может быть довольно популярный паттерн, если вы инициализируете какой-нибудь массив небольшой какими-нибудь элементами, индексы, еще что-нибудь, он делает следующее, он вставляет такую проверку, то есть в моем примере, когда мы заполняем 8 элементов, он проверит, что входящий массив, он больше, чем 8, и если он больше, чем 8, он забивает вообще на проверки этих самых bound checks, и понятно, что более оптимальными векторными инструкциями вот это все как-то инициализирует, а вот если оно меньше, то он, по сути, просто дублирует ваш код еще один раз и там аккуратненько заполняет поштучно со всеми проверками, чтобы сохранить вот то самое поведение, когда все-таки массив короткий, а поскольку в большинстве случаев, наверное, все-таки будет передаваться массив нормального размера, то это клонирование, конечно, код немножко раздувает, но зато делает его пошустрее, вот, а дальше еще момент в такое же клонирование, и тоже такая очистка делается для, там, try-finaly-блоков, там есть некоторые моменты, почему с ними может потребоваться такой вот тоже клоунинг, потому что, опять же, в хорошем случае, когда мы не кинули exception там одной, когда кинули другую, в общем, тоже с ними дело происходит, почитайте повнимательнее, там более сложная кухня, я так уже на слух не опишу, но основной пойнт, почему именно try-finaly, потому что это очень популярный паттерн, который вы руками пишите редко, но на самом деле используется очень часто, потому что это по сути юзинг, то есть все оптимизации вокруг именно try-finaly, не try-catch, а именно try-finaly, это оптимизация юзингов, а их много, и поэтому они важны. +2030.98 2046.54 "Игорь Лабутин" Дальше переходим к инлайнингу, инлайнинг - это штука, с моей стороны, хорошая, казалось бы, ну, как я говорил, основная головная боль - это что если строго следовать тому, что вы написали в программе, то будет миллион разных вызовов методов, а вызов - это относительно дорого. +2046.54 2070.46 "Игорь Лабутин" Но при этом, если мы все будем инлайнить, то мы будем раздувать код, а это тоже плохо, потому что он перестанет эффективно попадать в кэши процессора, все это надо будет загружать из памяти, что тоже медленно, и непонятно, что быстрее было бы - сделать обычный функциональный вызов или подгрузить очередную портянку кода из памяти, которая в кэш, естественно, не влезла, потому что была вытеснена другой. +2070.46 2093.00 "Игорь Лабутин" И с одной стороны, кажется, что нужно бороться и находить какую-то золотую середину, с другой стороны, инлайнинг помогает применять остальные оптимизации, то есть как я говорил с тем самым скейп-анализом, естественно, если переменная передается в какой-то другой метод, JIT в принципе понятия не имеет, что в этом методе с этой переменной будет происходить. +2093.00 2103.90 "Игорь Лабутин" И если такое происходит, то такая переменная автоматически помечается, что, а может, она и будет куда-то передана наружу, и поэтому она не может быть стеклоаллоцирована. +2103.90 2117.42 "Игорь Лабутин" Но если вы вызываемый метод заинлайните, то JIT уже сможет понять, что ага, все-таки она нигде наружу не передается, то есть может быть заинлайнена, то есть может быть стеклок на нее, например, сделан. +2117.42 2121.90 "Игорь Лабутин" Поэтому инлайнить с одной стороны надо, а с другой не надо. +2121.90 2122.90 "Игорь Лабутин" Дальше. +2122.90 2140.66 "Игорь Лабутин" В JIT с незапамятных времен существует некая эвристика, их на самом деле много, на тему того, какие методы надо инлайнить, какие не надо, а какие строго запрещено инлайнить, потому что там довольно сложная внутренняя логика. +2140.66 2156.54 "Игорь Лабутин" И, например, до недавнего времени никакие методы с обработкой исключений, то есть если вы написали в методе try, можно было на 99, а то и на 100% быть уверенными, что этот метод никогда заинлайнен не будет, потому что в нем есть блок от слова исключений, try_catch, либо try_final, либо еще что-нибудь. +2156.54 2170.98 "Игорь Лабутин" Теперь в 10-ом дотнете try_final, методы, в которых есть именно try_final, могут быть заинлайнены без проблем, ну точнее они будут рассматриваться как кандидат на inlining, дальше понятно, что все остальные эвристики тоже могут на это повлиять. +2170.98 2176.14 "Игорь Лабутин" Вот с try_catch пока сложно, поэтому если у вас именно try_catch, он скорее всего заинлайнен пока не будет. +2176.14 2186.06 "Игорь Лабутин" Но, опять же, try_catch это все-таки не такая частая штука относительно try_final, которую, еще раз напомню, по сути, то, во что превращаются юзинги. +2186.06 2217.42 "Игорь Лабутин" Более того, с try_catch все-таки есть тоже оптимизация, если JIT каким-то образом может доказать, например, в результате inlining, то есть не глядя, конечно, на исходный код, не глядя на исходный код, у вас в try_catch может вызываться какая-то функция, которая тоже вызывала функцию, но благодаря всем inlining, например, JIT поймет, что конкретно в этом кейсе с этим, не знаю, комбинацией generic параметров с этим еще чем-нибудь, у вас внутри точно не может быть никакого исключения. +2217.42 2224.02 "Игорь Лабутин" Тогда try_catch вообще удаляется из итогового кода, и никакого overhead на тот факт, что там был try_catch не будет. +2224.02 2229.30 "Игорь Лабутин" Это, наверное, довольно редкий сценарий, но, тем не менее, он имеет место быть. +2229.30 2238.10 "Игорь Лабутин" Также добавили оптимизации про generic виртуальные методы, но там уже совсем низшая штука, и не буду детально про это рассказывать. +2238.10 2242.42 "Игорь Лабутин" Значит, про эвристики, про эвристики тоже немножко поменяли. +2242.42 2254.42 "Игорь Лабутин" Как я говорил, были эвристики про, если есть try, то точно нельзя, все при этом, inlining тоже плохо, поэтому у JIT есть некоторое количество так называемого бюджета. +2254.42 2290.30 "Игорь Лабутин" То есть JIT на каждый метод выделяет некоторый бюджет inlining, на каждую компиляцию выделяет некоторый бюджет inlining, и потихонечку рассматривает методы, у методов тоже рассматривают какие-то вероятности, если метод проходит, соответственно, он inlining, этот бюджет уменьшается, и как только бюджет заканчивается, JIT говорит, ладно, все, что-то я много inlining, наверное, код теперь станет слишком большим, хватит-ка мне пока inlining, и в следующий раз, возможно, в статье не очень было описано, но я так понимаю, что есть вероятность, что дальше он inlining практически вообще не будет. +2290.30 2292.82 "Игорь Лабутин" И тут возникает два момента. +2292.82 2296.82 "Игорь Лабутин" Во-первых, как понять, нужно ли метод inlining или не inlining. +2296.82 2317.18 "Игорь Лабутин" Тут вступает в дело те самые оптимизации, про которые мы говорили раньше, если, например, у вас в методе используется маленький массивчик, то его хорошо бы заинлайнить, потому что тогда есть большая вероятность, что именно этот метод получится, точнее, именно этот маленький массивчик получится анализировать на стэке. +2317.18 2326.26 "Игорь Лабутин" И поэтому теперь, если метод возвращает маленький массив, то шансы на то, что он заинлайнится, гораздо выше, для того чтобы применить дальше stack allocation. +2326.26 2371.38 "Игорь Лабутин" С другой стороны, тот самый бюджет, как я сказал, оказалось, что он тратится, но надо понимать, что программа начинает работать, джит начинает что-то там как-то работать, что-то inlining, и бюджет, по сути, тратится на то, что называется top-level методы, то есть всякие там инициализационные штуки, еще что-то, и они видели кейсы, когда в какой-то довольно сложных программах этот бюджет полностью исчерпывался еще до того, ну или там существенно до того, как выполнение доходило до реально горячих методов на горячих ворклоудах, а джита уже весь бюджет кончился, все как бы, уже inlining-ить нечего, поэтому они его удвоили. +2371.38 2379.02 "Игорь Лабутин" А кроме того, есть еще одна метрика, по которой джит решает, надо ли не надо inlining-ить. +2379.02 2391.70 "Игорь Лабутин" Дело в том, что по мере того, как происходит inlining, у вас по сути, вы получаете все более жирный метод, в котором все больше и больше локальных переменных, ну по сути своей, да, потому что все локальные переменные внутренних методов, они тоже добавляются. +2391.70 2410.66 "Игорь Лабутин" И у джита раньше была некоторая захардкоженная вообще прям в коде константов в виде 512 вот этих самых локалов, так называемых, которые джит трекал, и как только эта величина превышала 512, опять же, inlining точно останавливался для данного метода. +2410.66 2423.46 "Игорь Лабутин" Теперь они убрали фиксированный лимит и добавили такое скорее процентное соотношение, то есть довольно большой процент, но это все-таки теперь процент, и поэтому фактически лимит, ну по замерам, он по сути удвоился. +2423.46 2425.22 "Игорь Лабутин" Два раза больше можно заinlining-ить. +2425.22 2438.66 "Игорь Лабутин" В общем, это все про inlining, то есть стараются настроить теористики так, чтобы inlining-ить так, чтобы другие оптимизации тоже срабатывали, потому что большинство оптимизаций, они все-таки именно внутри одного метода, а не на комплексе методов. +2438.66 2456.02 "Игорь Лабутин" Улучшили там свертку constant, не буду сильно распространяться, код layout, то есть расположение блоков кода, опять же, смотрите, когда у нас есть jit, у него, по сути, когда он скомпилировал метод, получается на выходе некоторое количество ассемблерных инструкций. +2456.02 2466.74 "Игорь Лабутин" Естественно, просто так переупорядочивать все-все ассемблерные инструкции нельзя, но некоторое переупорядочивание допустимо, если понять следующую логику. +2466.74 2486.30 "Игорь Лабутин" У вас весь код одного метода развивается на блоке, по сути, по границам любых возможных переходов, то есть все if-ы, циклы, try-catch-и и вот это все, каждый вот атомарный блок, то есть там, где набор команд выполняется строго последовательно, это получается некоторый, они называют basic-блоком. +2486.30 2488.90 "Игорь Лабутин" И дальше их нужно всех разложить в нужном порядке. +2488.90 2490.78 "Игорь Лабутин" Что значит нужный порядок? +2490.78 2503.22 "Игорь Лабутин" Понятно, что в каком бы порядке вы их не разложили, нужно сгенерить код, который позволит выполнить эту логику так, как задумывал программист, то есть добавить все переходы, все бранчи правильные и так далее. +2503.22 2528.26 "Игорь Лабутин" И вот тут идея в том, чтобы придумать такой layout этих блоков так, чтобы максимально вероятный путь был максимально прямолинейен, но чтобы процессор, понятно, не получил довольно много ошибочных предсказаний переходов до branch predictions, чтобы у него работала эта логика, и чем лучше она работает, тем лучше конвейеризируется исполнение на процессе, тем быстрее все это работает. +2528.26 2553.58 "Игорь Лабутин" Дальше там есть куча проблем, во-первых, там есть циклы, поэтому она точно не линеаризуема, во-вторых, полное решение этой задачки, это на самом деле задачка мивы и жора, которая, ну как, не решается за конечное время, а я напомню, что мы в контексте джита, то есть у него джита есть там не очень много времени, чтобы ее решить, поэтому там используются различные оптимизации, их тоже пооптимизировали немножко. +2553.58 2559.34 "Игорь Лабутин" В общем, джит теперь чуть более оптимально раскладывает вот этот самый код при компиляции. +2559.34 2681.02 "Игорь Лабутин" А также поработали немножко над write-barriers, то что называется, значит, смотрите, в чем идея, когда у нас аллоцируется новый объект, ну тут все понятно, аллоцировался он попал в нулевое поколение, при каждой сборке мусора нулевое поколение просматривается всегда, тут проблем нет, проблемы начинаются, когда мы такой объект помещаем в поле, ну или в массив объекта более старшего поколения, то есть мы, например, создали какой-нибудь объектик и положили его в массив, который уже давно лежит в втором поколении, и возникает вопрос, если мы будем смотреть только на нулевое поколение, то ссылки на такой объект не будет, и его тогда можно, казалось бы, удалять, но нельзя, потому что нужно смотреть на второе поколение, но каждый раз смотреть на все поколения это очень дорого и долго, и дотнет тогда поработала медленно, поэтому используется механизм, называемый card table, то есть каждый раз, когда мы присваиваем ссылку на объект нулевого поколения, точнее, когда мы присваиваем, да, ссылку на объект нулевого поколения в любой объект более старшего поколения, в специальной табличке в структуре данных отмечается bit, что вот эту страничку надо будет посмотреть в старшем поколении, ну и garbage collector знает, что да, при сканировании объектов младшего поколения нужно заглянуть в card table в старшее поколение в ссылке, нет ли там ссылок, и чем, ну, технически после каждого присваивания такую штуку надо делать, то есть добавлять вот этот самый write barrier, потому что только gc знает jit без понятия, это объект нулевого первого или второго поколения, по идее после каждого присваивания, но фактически, фактически мы в некоторых случаях можем вполне знать, что мы присваиваемся в объекты, которые только тоже только-только создали, значит они скорее всего в нулевом поколении, в общем jit теперь старается этих write barriers оставлять поменьше в тех случаях, когда он гарантирует, что ссылка точно не убежала в старшее поколение. +2681.02 2759.50 "Игорь Лабутин" Вот, а также есть еще такой момент, что в некоторых calling conventions внутри, то есть когда мы должны вернуть какую-то чуть более сложную структуру, там анализировался некий промежуточный буфер, и технически он опять же мог ассоциироваться в heap, мог ассоциироваться на стэке, передаваться в вызываемую функцию, вызываемую функцию его как-то наполняла и возвращала, по стандарту вообще говоря не было никаких, не знаю, ограничений, что оно должно быть строго на стэке, но фактически во всех реализациях эта сила была на стэке, поэтому теперь правила поменяли и сказали, что вот этот спецбуфер для jit должен быть строго на стэке, за счет чего еще уменьшили аллокации взаимодействия с gc, в общем jit всячески умнеет, всячески становится более продвинутым, пытается укладываться в тоже коротенькое время, но при этом максимально не нагружает систему, теперь пойдем дальше, по остальным кусочкам тут уже не так может быть подробно будет, потому что они более высокоуровневые, и здесь получается такое, что с одной стороны мы рассматриваем какие-то довольно высокоуровневые штуки, а с другой стороны микробенчмарки на доли на на секунды, и поэтому сильно вдаваться в детали, кажется, тут большого смысла нет, но концептуально я постараюсь рассказать, что и где поменялось. +2759.50 2760.50 "Игорь Лабутин" NativeOut. +2760.50 2790.90 "Игорь Лабутин" NativeOut это по сути тот же jit, который работает заранее, который без понятия о какой-либо статистике того, как часто будет вызываться тот или иной метод, зато у него есть, скажем так, возможность посмотреть на весь компилированный код, а не только на код одного метода, и понять, что в том коде, который он компилирует, например, вот эта функция всегда вызывается с листом, и можно сразу генерить код оптимальный только под лист, потому что ничего другого в вызове этой функции не будет. +2790.90 2795.42 "Игорь Лабутин" Но при этом размер все еще важен, поэтому тут есть некоторый баланс. +2795.42 2842.10 "Игорь Лабутин" В виртуальной машине, то есть это все, что нет jit, то есть это gc, всякие системные вызовы внутри и так далее, там еще больше произошел переход из C в C#, опять же с целью инлайнинга, то есть если, казалось бы, да, всякие интринсики хорошо писать на C или на плюсах, потому что они же low-level, но по факту это не так, потому что каждый переход из managed в unmanaged мира довольно дорого, поэтому ключевые кусочки сейчас в том числе переписываются на C#, чтобы даже вызов всяких таких интринсиков приводил в итоге к обычному C# вызову, а обычный C# вызов это смотри выше, возможности jit оптимизации, инлайнинга и соответствующих всяких других оптимизаций, и это действительно ускоряет. +2842.10 2848.42 "Игорь Лабутин" В трейдинге тоже произошли интересные изменения, в тредпуле. +2848.42 2908.06 "Игорь Лабутин" Я не помню, рассказывали ли мы детально в подкасте когда-либо про тредпул, но по сути это некоторые наборы трейдов, каждый из которых просто выполняет задачки, таски или какие-то другие, в общем делегаты, неважно какие, при этом наивной реализацией выглядело бы как что у вас есть одна какая-нибудь конкаратная очередь, куда все складывают задачки, которые надо выполнить, и трейды потихонечку разбирают, но если бы так сделали, то на этой одной единственной очереди был бы большой контеншн, то есть все бы хотели из нее забирать, особенно если задачки-картка живущей, что довольно бывает часто в мире тасков, поэтому трейды, тредпул устроен чуть сложнее, это несколько очередей, есть одна глобальная, туда конечно попадают те задачки, которые вы снаружи туда закидываете, и на каждый поток есть своя локальная очередь, куда попадают те задачки, которые генерятся этим самым потоком, а поток, соответственно, прежде чем лезть в большую задачку, в большую очередь главную, он разбирает всегда задачки из своей локальной очереди. +2908.06 3068.14 "Игорь Лабутин" Работает все здорово, работает хорошо, за одним исключением, если у нас локальный поток вдруг заблокировался и ждет, например, какой-нибудь тасочки, которая, ну так оказалось, тоже лежит в локальной очереди этого же самого потока, то до нее дойдет исполнение только когда полностью опустошится большая очередь глобальная, и потоки начнут пытаться стащить работу соседних потоков, что может произойти непонятно когда, особенно если у вас есть постоянный поток таких задачек, поэтому довольно большое изменение, и важно, в десятом интернете, если поток понимает, что он сейчас заблокируется, отдельный вопрос, как он это делает, он первое, что делает, прежде чем заблокироваться, он все задачки из своей локальной очереди выгружает в глобальную, чтобы они побыстрее разобрались, и потом спокойно блокируется, особенно на тасках, как-то так сказано, видимо они понимают, что там сейчас будет, что мы там вызвали какую-нибудь таску wait, wait1 или что-то такое, и соответственно это означает, что мы зависим от какой-то другой таски, и надо бы тогда все таски, которые могли быть в моей локальной очереди, скинуть в глобальную, чтобы было больше шансов, что они разберутся. Если вы фанат без, как, lock free, забыл, короче алгоритмов без блокировок, то вы конечно же знаете про всякие там memory-барьеры и вот это все, у нас добавили два новых метода, у нас были методы в классе volatile, называлось volatile_read, volatile_write, теперь есть volatile.read_barrier и volatile.write_barrier, это те самые memory-барьеры, соответственно, ну, read_write семантика, в общем, вы знаете, зачем они вам нужны, если вы знаете эту тему. Ну и для ченнелов тоже там есть некоторые performance-улучшения, они довольно нишевые, но есть. В Reflection добавились тоже ускорения, Reflection довольно сильно ускорили в девятом .NET, а также в девятом, если я правильно помню, добавили такой атрибут как unsafe_accessor, который позволяет довольно оптимально доступаться к private-мемберам какого-нибудь класса, и это будет быстрее, чем через Reflection обычный, но есть проблемы с этим unsafe_accessor, нам же нужно описать полностью сигнатуру того же, например, private-метода, который мы хотим вызвать в соседнем классе, и потом его уже вызывать, но проблема в том, что в этом private-методе, например, в аргументах могут использоваться какие-нибудь объекты, которые private тоже для того класса, в котором этот метод объявлен, и вы физически не можете описать сигнатуру метода снаружи класса, в котором он объявлен. +3068.14 3090.74 "Игорь Лабутин" Вот, для этого теперь у нас есть новый атрибут unsafe_accessor_type, который позволяет, то есть вы пишете эту сигнатуру метода через просто объекты, и каждый такой параметр размечаете новым атрибутом unsafe_accessor_type, куда передаете просто строчкой fully qualified name того типа, который нужен, даже если он внутри private-тип в каком-нибудь классе, private-класс. +3090.74 3105.34 "Игорь Лабутин" И все будет работать, это, как казалось бы, напрямую на performance не влияет, но если вам нужен reflection, но вы заморачиваетесь за performance, то вот unsafe_accessor, возможно, путь куда надо посмотреть, и теперь стало с ним чуть попроще. +3105.34 3124.14 "Игорь Лабутин" Про primitives и numerics я сильно много рассказывать не буду, там, конечно же, всякие тензоры, оптимизации в рандоме, много оптимизации вокруг utf-8 парсинга и обратно, в общем, просто по мелочи улучшается. +3124.14 3134.54 "Игорь Лабутин" С коллекшенами, с коллекшенами есть там интересный тоже вот, кстати, секс про коллекшены, я бы, наверное, рекомендовал почитать, чтобы вы понимали, как там что происходит. +3134.54 3142.58 "Игорь Лабутин" С enumerations теперь девиртуализируются вызовы enumerable, то, про что я говорил. +3142.58 3179.38 "Игорь Лабутин" То есть, если мы понимаем, что мы в цикле, в какой-то функции в качестве enumerable всегда итерируемся, например, по листу, то это все будет девиртуализировано, вызываются конкретные типы, все это благодаря profile_guided_optimization, но при этом есть некоторый забавный момент, который пришлось 10 минут нотификсить, когда они это только сделали сначала, выяснилось следующее, если мы, например, делаем такой forage на enumerable, под капотом которого лист, в котором, например, 10 элементов, он прекрасно работает и аллоцирует 0 байтов. +3179.38 3189.42 "Игорь Лабутин" Если мы делаем такую штуку на 500 элементов, то он тоже прекрасно работает, быстро, все замечательно, но аллоцирует уже память. +3189.42 3190.42 "Игорь Лабутин" Стали выяснять почему. +3190.42 3215.14 "Игорь Лабутин" Выяснилось, что в enumerator, ну, точнее, в enumerator, который возвращается из обычного enumerable, есть спецоптимизация, поскольку мы боремся за inlining и вот это все, то фактически же у нас есть у move_next, напомню, что у enumerator, current, это текущее значение, move_next подъем на следующий, он вернет true/false в зависимости от того, есть ли он или нет. +3215.14 3235.62 "Игорь Лабутин" Так вот в среднем, в коллекции, у вас move_next будет почти все время возвращать true и только один раз вернет false, и поэтому move_next, он был реализован следующим образом, там стоял if, что если все хорошо и можно вернуть следующий элемент, верни его сразу, иначе вызови функцию move_next_rare, которая вернет уже там false или кинет какое-нибудь исключение. +3235.62 3241.78 "Игорь Лабутин" Напомню, там есть версионирование списков, что если вы поменяли список во время версионирования, то он кинет исключение. +3241.78 3243.50 "Игорь Лабутин" Вот это, короче, делалось функцией move_next_rare. +3243.50 3254.82 "Игорь Лабутин" И дальше проблема в том, что если у вас список короткий, то у вас получается, что вроде как, ну, примерно одинаково вызывается move_next и move_next_rare, и профайл гайдэт оптимизейшн говорит, что, ну, я примерно поровну, поэтому, значит, это, илайним все целиком. +3254.82 3272.38 "Игорь Лабутин" А если у вас список длинный, то move_next начинает серьезно превалировать над move_next_rare, и профайл гайдэт оптимизейшн говорит, что rare-вариант вызывается что-то очень редко, давай мы под него не будем оптимизироваться, и в итоге, когда он все-таки вызывается, он гарантированно вызывается в конце, получается, что он из-за этого приводит к аллокации, потому что надо забоксить интерфейс. +3272.38 3283.06 "Игорь Лабутин" В общем, вот такая вот история, при этом пришлось по этому попереписывать move_next, move_next_rare, чтобы они все-таки с профайл гайдэт оптимизейшн работали нормально вместе. +3283.06 3288.62 "Игорь Лабутин" Ну и такие же изменения для очереди, стэка и номераторов сделали, тут детально додаваться не буду. +3288.62 3375.58 "Игорь Лабутин" В linq, в linq прямо довольно много изменений, во-первых, тоже напомню, что linq — это не просто набор методов, которые вызываются друг за другом, это на самом деле довольно сложная кухня оптимизации внутри, когда вы вызываете, ну классический пример, какая-нибудь коллекция .where.select, естественно, никто не интегрируется два раза по ней, в смысле, никто для каждого элемента не вызывает два делегата, на самом деле там, конечно, внутри делается один-единственный итератор, который называется where_select_iterator, в котором сразу все делается и проверяется через иф предегат, и, соответственно, вызывается делегат, который в селекции у вас объявлен, и вот таких штук не было для contains, и поэтому, например, если бы по какой-то причине вдруг получилось так, что эффективное linq выражение входит в какой-нибудь набор, например, что-нибудь там order_by, потом select, а потом contains, то получается, что вроде как вы потратите время на order_by, а contains вообще, говорят, плевать на порядок, вот, и в итоге они запилили что-то там 30 плюс всяких разных экстендженов вокруг вот этого contains, ну, внутри для энумераторов, чтобы как раз нивелировать необходимость что-нибудь там сортировать, какой-нибудь distinct тоже для contains не важно, потому что либо contains, либо не contains, ну и так далее, в общем, contains должен заработать сейчас теперь в разы быстрее. +3375.58 3408.50 "Игорь Лабутин" Дальше добавили два новых метода, да, это не совсем про performance, это про sequence и про shuffle, и если sequence не такой интересный, то shuffle прямо интересно, для него тоже пришлось писать кучу специализаций, потому что, ну, если вам нужен shuffle, например, shuffle — это новый метод, который просто существующую последовательность по сути просто рандомно переставляет, грубо говоря, и вот, например, если вы делаете shuffle, а потом contains, то понятно, что shuffle делать не надо вообще, можно просто сделать contains, потому что как ни переставляй, contains либо да, либо нет. +3408.50 3421.22 "Игорь Лабутин" Там есть разные очень интересные моменты, типа там, а что если делать всякие skip-takes и вот это все, ну, в общем, почитайте статью, там прямо хорошо про это расписано. +3421.22 3490.22 "Игорь Лабутин" Новые оптимизации, точнее, два новых метода left_join и right_join, которые можно было выразить старым способом, старыми методами, через всякие select_many, вот это все, но эти два метода написаны более оптимально, и в link.io, если вы не знали, есть две версии, то есть на самом деле в рентайме существует две версии link.io, одна называется size_optimized, другая называется speed_optimized, по дефолту у вас работает speed_optimized, но для native-auto сценариев вы можете теперь использовать feature switch, который в csproj вы передаете, говорите use size_optimized link.io, и у вас будет не такой быстрый, но гораздо более компактный код, потому что link.io, это же огромные дженерики, и если вы используете link.io довольно широко в вашем проекте, вам на etfout компилятор сгенерит огромное количество вариаций этого link.io, даже если вы используете один wear, ну все равно будет сгенерено все методы для класса, который реализует этот wear итератор, для всех типов, которые вы используете, поэтому это прям довольно сильно может раздувать при активном link.io использовании. +3490.22 3543.02 "Игорь Лабутин" Так, что еще дальше у нас, дальше вот вывод i/o, не буду погружаться, есть там какие-то мелкие импровменты, все же в спортинге с RegEx'ами тоже довольно много изменений, более качественный detect так называемых auto-atomic blocks или disjoint analysis они это называют, т.е. это понимание, что если у вас есть, например, какой-то паттерн, и после него стоит звездочка, и дальше следующий паттерн, ну классический пример, а звездочка b, т.е. сколько-то символов а, и потом b, то теперь RegEx парсер понимает, что эти блоки гарантированно не пересекаются, т.е. не может b никогда входить в первые а звездочка, очевидно, потому что там только символ а, и за счет этого можно довольно сильно сократить варианты всяких backtracking'ов, переборов и т.д. и гораздо быстрее работает. +3543.02 3596.78 "Игорь Лабутин" Такая же штука, ну такая же в смысле, тоже оптимизация сделана для 0-width matches, т.е. всякие conditional look-up'ы и прочие, точнее look-ahead конструкции, которые чего-то match'ят, но они не consume'ят символы из строки, т.е. они просто проверяют, что следующие символы чего-то match'ят, но дальше не идут, вот для них тоже там есть некоторое количество оптимизаций, и плюс добавили некоторое количество аналайзеров, которые тоже помогают ваш код поправить, потому что, например, если вы написали regex.match.success, то это очень неоптимально, потому что там балансируется объект, собираются группы, которые match'ятся, а вы всего лишь вызвали success, гораздо правильнее просто вызвать regex.ismatch, и все как бы будет гораздо более оптимально, и меньше памяти потребуется. +3596.78 3606.78 "Игорь Лабутин" Church values улучшили, там некоторые алгоритмы внутри, memory extensions улучшили, и в общем с поиском на этом, наверное, все. +3606.78 3631.34 "Игорь Лабутин" С JSON'ом, ну, довольно нишевые изменения, единственное такое полезное практическое изменение, если вам нужно, например, у вас есть строка JSON'а, и вам нужно из нее добыть JSON-элемент, единственный, ну, не единственный, но один из, наверное, классических что ли способов это сделать было создать JSON-документ, в JSON-документе есть метод parse, т.е. вы говорите JSON-документ.parse от нужной вам строки. +3631.34 3634.62 "Игорь Лабутин" После чего у документа говорите root-элемент, и вот вам JSON-элемент. +3634.62 3640.42 "Игорь Лабутин" Проблема в том, что JSON-документ там тянет внутри себя некоторое количество ресурсов, его нужно диспользовать обязательно, и так далее. +3640.42 3647.72 "Игорь Лабутин" Это сложно, это можно забыть, или там в некоторых сценариях, когда вы возвращаете JSON-элемент, это может быть даже невозможно сделать. +3647.72 3653.62 "Игорь Лабутин" Теперь в JSON-элемент у самого есть метод parse, можно просто парсить строчку в JSON-элемент сразу, это прям кажется удобно. +3653.62 3658.86 "Игорь Лабутин" Нужно делать это побыстрее немножко, за счет отсутствия необходимости там хранить кое-что дополнительное. +3658.86 3690.34 "Игорь Лабутин" В диагностике тоже добавили, была жалоба, что у нас есть прекрасный класс stopwatch, все замечательно, многие его используют для каких-то микрозамеров, ну не микробенчмарков, но таких микрозамеров внутри своего кода, ну просто например залогировать какую-нибудь метрику, насколько долго что-то у вас выполнялась какая-нибудь джоба, и все бы ничего, но stopwatch это класс, и соответственно всякие startnew, elapsed, stop, они, это по сути вызовы методов. +3690.34 3699.38 "Игорь Лабутин" Теперь в десятом доте они fully inlinable, то есть они будут полностью заинлайнены, и не будет никакого overhead на то, чтобы использовать stopwatch. +3699.38 3705.74 "Игорь Лабутин" Дальше добавили немножко аналайзеров вокруг логинга, чтобы более оптимально с ними было в криптографии улучшение. +3705.74 3728.50 "Игорь Лабутин" Ну и много-много-много других мелких штук, я прям все они перечислил, gc немножко потюнили, gc_handle типы тоже потюнили, если вы работаете напрямую с gc_handle, стало побыстрее, если вы работаете с enum и парсить их строк и обратно, тоже стало побыстрее, в общем огромное количество всяких мелочей, я уже все перечислять наверное не смогу. +3728.50 3739.22 "Игорь Лабутин" Ну вот примерно так, такая вот у меня получился обзор того, о чем написал Тауб, то что я успел прочитать и выцепить для себя. +3739.22 3749.78 "Анатолий Кулаков" Ну отличная выжимка, отличная работа от Тауба, и от тебя тоже, интересно, они во втором тогда релиз кандидате ничего не собираются улучшать, раз Тауб уже статью свою выпустил? +3749.78 3765.02 "Игорь Лабутин" Слушай, на самом деле могут, потому что в статье в двух или трех местах встречаются конструкции вида, когда я первый раз написал этот бенчмарк, мы увидели какие-то подозрительные цифры, пошли разбираться, нашли проблему, пофиксили, и вот теперь в этой статье типа правильные цифры. +3765.02 3784.14 "Игорь Лабутин" То есть я так понимаю, что когда Тауб пишет эту статью, он видимо, ну я не удивлюсь, если он находит какие-то примеры, перфа, вот, пытаясь подобрать какие-то примеры, и я допускаю, что может быть, пока он ее писал, он там еще каких-нибудь ишуев завел на гитхап, и в РЦ2 мы тоже еще что-то успеем увидеть. +3784.14 3786.78 "Анатолий Кулаков" А есть ли признаки того, что он эту статью меняет? +3786.78 3794.10 "Анатолий Кулаков" Потому что если выйдет там РЦ2, они там что-то пофиксят, и он прямо в этой же статье может, наверное, поменять бенчмарки или выводы свои. +3794.10 3807.82 "Игорь Лабутин" Ну видишь, там выводов особых нет, то есть там скорее она такая информирующая, что вот тут мы поменяли это, например, в 10-ом дотнете, вот оно там было, не знаю, 20 наносекунд, стало 15 наносекунд, ну типа улучшили. +3807.82 3815.18 "Игорь Лабутин" Каких-то таких глобальных выводов, на которые может повлиять какие-то изменения, мне кажется, нет. +3815.18 3816.18 "Игорь Лабутин" Правит ли он статью? +3816.18 3817.18 "Игорь Лабутин" Я не видел такого. +3817.18 3827.78 "Игорь Лабутин" Ну знаешь, честно говоря, я не думаю, что я ее буду второй раз открывать, только если мне не потребуются какие-то прям точные числа или точные бенчмарки конкретно для 10-ого дотнета, поэтому, ну, наверное, не отследим уже. +3827.78 3840.70 "Анатолий Кулаков" Уже на предыдущей релизе они очень там сильно гордились, что ваш дотнет, допустим, то же самое в 10-ом, когда дотнет фреймворк выходил, ваше дотнет-приложение можно просто перекомпилировать, оно там начнет работать во много раз быстрее. +3840.70 3846.86 "Анатолий Кулаков" Вот не прослеживаются ли здесь такие лозунги, то есть можно ли мне просто перекомпилировать на 10-ку и все будет быстрее? +3846.86 3847.86 "Игорь Лабутин" Будет быстрее, однозначно. +3847.86 3848.86 "Игорь Лабутин" То есть насколько… +3848.86 3855.22 "Анатолий Кулаков" Без того, что ты рассказал, понятно, что будет быстрее, а есть ли прямо вот, не знаю, бенчмарки, заявления, +3855.22 3856.22 "Игорь Лабутин" еще что-то такое? +3856.22 3888.60 "Игорь Лабутин" Нет-нет, в этой статье точно нет, более того, если почитать комментарий под статьей, я немножко пробежался по ним, там как раз народ говорит, что блин, микробенчмарки это все, конечно, здорово, классно, что здесь вы сэкономились 20 на секунду 15, но давайте вы еще дополнительно какое-нибудь, ну типа модельное приложение, понятно, что оно будет модельным, то есть понятно, что это не будет какой-то готовый там, не знаю, CMS-ка, не знаю, сайт-магазин, еще что-нибудь, на нем, скорее всего, вы не увидите какой-то, хотя может увидите, то есть в общем нужно какое-то модельное приложение. +3888.60 3889.60 "Игорь Лабутин" Хотелось бы. +3889.60 3890.60 "Игорь Лабутин" Хотелось бы увидеть. +3890.60 3911.22 "Игорь Лабутин" Да, вы каждый релиз будете гонять одни и те же тесты и видеть, что там, не знаю, на 10% улучшилось, на 5, ну как бы это, ну это, конечно, нет, 30 круче, чем 5, но и 5 тоже неплохо, как бы тут 5, тут 5, тут 5, и уже хорошо, вот, с каждым релизом, но как бы Талоб сказал да, спасибо за идею, ну как бы и дальше комментировать не стал. +3911.22 3931.58 "Игорь Лабутин" Вот, поэтому посмотрим, я думаю, что к, ну смотри, на самом деле такая статистика у них есть, потому что я практически уверен, что все их first-party-customers, да, те, кто, ну и внутри они, они, конечно, берут как бы свой этот самый какой-нибудь продукт, ну условный bing, да, компилируют его десяткой и смотрят, что поменялось. +3931.58 3974.78 "Игорь Лабутин" Ну во-первых, сначала они смотрят, где упало, да, а потом насколько быстрее стало, вот, я думаю, что все эти числа мы увидим в итоговой презентации, когда вот будут про дотант 10 рассказывать уже на дотант конфе в ноябре, да, ноябре же, да, у нас данный ноябре, мы там скорее всего какие-то числа увидим, другое дело, что это не какой-то готовый модель, например, на гитхабе, который все могут скачать, это скорее всего какой-то агрегированный такой саморис, той информации, которая доступна внутри команде, посмотрим, но на самом деле после выхода, на самом деле даже еще до выхода девятки или там восьмерки, в Твиттере довольно много народу показывало свои графики, что вот, обновился, и смотри, как круто стало, так что я думаю, что мы увидим еще пример. +3974.78 3995.34 "Анатолий Кулаков" Ну хорошо, да, может быть здесь стоит не Microsoft такое приложение выкладывать и постоянные версии его поддерживать и графики показывать, а может какой-нибудь энтузиасту, который на своем настоящем рабочем приложении, который неподдельный, продакшн рейди и все такое, вот он сам может все это делать, почему бы и нет. +3995.34 3996.34 "Игорь Лабутин" Наверное. +3996.34 3998.22 "Игорь Лабутин" Ну что, теперь точно про студию. +3998.22 4003.10 "Анатолий Кулаков" Да, да, надо теперь понять, как всего тех ништяков, которые ты рассказал, нам добиться. +4003.10 4008.06 "Анатолий Кулаков" Как вы поняли, добиться этого можно только, если вы поставите десятку и начнете ее использовать. +4008.06 4009.50 "Анатолий Кулаков" Как же ее поставить? +4009.50 4022.14 "Анатолий Кулаков" Ну, как я уже сказал, есть Visual Studio Code с плагином, естественно, никто у вас не отнимал командлайны, но большинство интерпрайсер-заработчиков по статистике все еще предпочитают Visual Studio. +4022.14 4043.14 "Анатолий Кулаков" И вот на Visual Studio мы уже долго-долго, уже 4 года там или пусть даже 3 года пинаем, когда она из 22-й превратится в какую-то современную, и наконец мы дождались, вот этот светлый момент, когда Visual Studio 22-я прекратит наконец-то быть 22-й и станет 2026-й. +4043.14 4054.82 "Анатолий Кулаков" Давайте же посмотрим, что же нам такого экстраординального готовили все эти 5 лет, 4 года, то есть получается, 4 года, и что же нас такого ждет и что там будет. +4054.82 4072.90 "Анатолий Кулаков" По этому поводу Мэдс Кристенсен выпустил статью, в котором объявил вот как раз об анонсе, ну не только выпустил статью, там снял видосик, еще записал несколько подкастов, в общем, много чего наболтал, сейчас мы с вами разберемся, что же нам такого интересного ожидается в новой студии. +4072.90 4091.34 "Анатолий Кулаков" Ну, прежде всего, основные векторы развития новой студии, зачем мы ее выпускали, что мы делали, ну, конечно же, это повсеместное внедрение в работу разработчика искусственного интеллекта, это улучшение перфоманса и современный самый лучший, самый удобный на свете дизайн. +4091.34 4095.90 "Анатолий Кулаков" Кроме вот этих громких заявлений, также изменилось название. +4095.90 4119.94 "Анатолий Кулаков" Если раньше у нас студия выпускалась, такие превью студии выпускались под названием Beta, то теперь это будет Insiders, они там переименовали канал, переименовали блок, теперь это Insider Channel, который заменил Preview Channel, и все теперь Early Access версии с самыми последними фичами и новомодными нововведениями нужно будет скачивать оттуда. +4119.94 4129.86 "Анатолий Кулаков" Пробежимся немножко по истории, Visual Studio 2022 была зарелижена 8 ноября 2021 года, то есть как раз-таки где-то 4 года назад. +4129.86 4145.70 "Анатолий Кулаков" Интересно, да, что они соблюдают традицию абсолютно непонятных цифр, когда 22 студия релизится в 2021 году, а получается, что 26 студия у нас зарелизится скорее всего в 2025 году. +4145.70 4150.14 "Анатолий Кулаков" В общем, безумные цифры продолжают у нас работать. +4150.14 4161.70 "Анатолий Кулаков" За это время было пофикшено больше 5000 багов, около 300 фич было заимплементировано, в общем, люди якобы старались. +4161.70 4172.86 "Анатолий Кулаков" Главное свойство заявления новой версии было в том, что они не хотят каких-то резких изменений, каких-то страшных повреждений. +4172.86 4177.78 "Анатолий Кулаков" Естественно это Enterprise на IDE, поэтому они там все за стабильность. +4177.78 4184.94 "Анатолий Кулаков" Если вы ожидали в новой версии студии, что она начнет запускаться под Linux или под Mac, то нет, естественно не начнет. +4184.94 4195.86 "Анатолий Кулаков" Она по-прежнему Windows Only, написана на том же самом технологическом стеке, как была раньше, продолжает использовать 64-битные приложения для хостинга. +4195.86 4203.30 "Анатолий Кулаков" Главный процесс Visual Studio продолжает крутиться на Legacy .NET фреймворке, то есть тот, который еще большой, не Core. +4203.30 4213.10 "Анатолий Кулаков" И, соответственно, экстеншены для Visual Studio тоже необходимо писать под большой .NET фреймворк, что, конечно, грустно. +4213.10 4232.18 "Анатолий Кулаков" Но мне все-таки грустно, потому что в последнее время Visual Studio запускает очень много всяких дочерних процессов, и большинство как раз дочерних процессов, в которых выносятся различные функции, например, тестирование, может быть тяжелый рефакторинг, какие-нибудь запуски под MOS, под модулей, под компонентов. +4232.18 4241.74 "Анатолий Кулаков" Так вот, вот эти все челдовые процессы, которые запускаются, они как раз в большинстве своем написаны на .NET Core, и это хоть какой-то глоток свежего воздуха. +4241.74 4245.26 "Анатолий Кулаков" Теперь про мега-современный, супер-прекрасный дизайн. +4245.26 4251.14 "Анатолий Кулаков" Студия была переделана под новый гайдлайн, который называется Microsoft Fluent Design. +4251.14 4255.10 "Анатолий Кулаков" Звучит страшно, но на самом деле изменения в дизайне довольно минимальные. +4255.10 4267.70 "Анатолий Кулаков" Они подвигали немножко расстояние между контролами, уменьшили-увеличили ширины, сделали там какие-то еще улучшения в округлости окошек и табиков. +4267.70 4272.94 "Анатолий Кулаков" В общем, довольно мелкие такие вот изменения, которые подогнали под Microsoft Fluent Design. +4272.94 4285.74 "Анатолий Кулаков" Может быть, самая заметная и самая раздражающая во-первой функция, которую они ввели, будет актив регион стайлинг, когда подсвечивается область в UI, которая находится сейчас под фокусом. +4285.74 4292.82 "Анатолий Кулаков" То есть текущая активная область, чтобы быстрее якобы глазами находить, где у нас собственно находится фокус. +4292.82 4297.42 "Анатолий Кулаков" Может быть, будет практично полезно, может, как всегда, будет всех раздражать. +4297.42 4298.86 "Анатолий Кулаков" Посмотрим на практике. +4298.86 4310.94 "Анатолий Кулаков" Декларируется огромный набор тем, в том числе возможность сделать свои темы очень просто и экстравагантно просто. +4310.94 4322.14 "Анатолий Кулаков" Кажется, что вот такие нововведения, которые абсолютно не отражают вот эту версию, которую мы ждали 4 года. +4322.14 4324.94 "Анатолий Кулаков" То есть ничего в ней такого страшного и большого нет. +4324.94 4330.02 "Анатолий Кулаков" Я вот тоже так думал до тех пор, пока не дошел до страницы настроек. +4330.02 4335.98 "Анатолий Кулаков" Единственное, что они, конечно, смогли испортить, это кардинально переписав страницу настроек. +4335.98 4345.78 "Анатолий Кулаков" Если вы помните, настройки Visual Studio не отличались особым удобством, но они были более-менее компактные, более-менее уже все к ним привыкли. +4345.78 4347.76 "Анатолий Кулаков" Теперь же настройки полностью переписали. +4347.76 4353.10 "Анатолий Кулаков" Сейчас они визуально стали похожи где-то на настройки Visual Studio кода, если вы их видели. +4353.10 4363.02 "Анатолий Кулаков" То есть это не окошко, которое рассчитано оптимально под все флажочки и все текстбоксы, которые есть для настройки вашей студии. +4363.02 4372.78 "Анатолий Кулаков" Это список всяких настроек, которые, наверное, рассчитаны прежде всего на тачскрин экран или декларацию. +4372.78 4380.90 "Анатолий Кулаков" То есть их задача не точно показать то значение, которое пользователю необходимо настроить. +4380.90 4389.78 "Анатолий Кулаков" Их задача универсально описать абсолютно любые контроллы, которые можно просто простынью вниз показать с бесконечным скроллом и заставить пользователя во всем этом как-то ориентироваться. +4389.78 4399.62 "Анатолий Кулаков" Ну, ориентироваться, наверное, станет легче, потому что был добавлен такой глобальный фильтр, по которому вы можете поискать любые настройки, которые только есть во всем диалоге настроек. +4399.62 4406.66 "Анатолий Кулаков" В общем, на практике посмотрим, насколько с этим удобно будет пользоваться, но визуально кажется, что это ужасно. +4406.66 4410.58 "Анатолий Кулаков" Настройки хорошо, что не просто так переписали, не просто так испоганили. +4410.58 4421.50 "Анатолий Кулаков" Испоганили и вводят какие-то полезные функции, например, как фильтр по всем настройкам, а также давно же демо-функция — это сохранение всех настроек в один единственный JSON-файл. +4421.50 4435.18 "Анатолий Кулаков" И более того, не просто в JSON-файл, а этот JSON-файл можно положить непосредственно на уровень солюшена, то есть вы с каждым солюшеном можете распространять свои настройки в студии, как это немножко похоже на Editor Config, который вы распространяете. +4435.18 4449.18 "Анатолий Кулаков" Возможно, не самый частый юзкейс, опять же, но перенос настроек между студиями, между разными профилями и, может быть, между разными проектами — это довольно мощная и хорошая возможность, что, в принципе, довольно хорошо. +4449.18 4465.42 "Анатолий Кулаков" Extension методы, которые вы делали или, возможно, использовали для Visual Studio предыдущих версий, они по-прежнему продолжат работать и в новой студии, что тоже хорошо, потому что очень много плагинов, как бы, у Visual Studio предыдущей есть, оно насобирало, и они не отвалятся. +4465.42 4466.42 "Анатолий Кулаков" Это прекрасно. +4466.42 4476.94 "Анатолий Кулаков" Если же вас заинтересовали все вот эти UI-ные нововведения, которые я рассказал, есть небольшой хак, с помощью которого вы можете включить эти же нововведения в Visual Studio 2022. +4476.94 4494.90 "Анатолий Кулаков" Для этого вам нужно зайти в Options, в фичи Flags и включить там Shell Experimental Styles, флажочек, и ваша Visual Studio преобразится и немножко получит тех визуальных элементов, которые будут уже в следующей студии, поэтому, так, не переключаясь, можно попробовать. +4494.90 4514.62 "Анатолий Кулаков" Так, еще одно нововведение, касающееся искусственного интеллекта, это то, что он, естественно, тут пронизан во всей студии для любых функций, которые разработчик соберется в нее ввести, и здесь появился MCP Support на самом низком уровне. +4514.62 4531.78 "Анатолий Кулаков" Это значит, что вы можете использовать не только те модельки, которые вам предоставляет Visual Studio, то есть там не только Copilot какой-нибудь, но и подставлять любые модели, которые у вас есть, и более того, даже подставлять свои собственные модели, то есть, например, запущенные локально или запущенные на локальных ваших корпоративных серверах, что тоже добавляет гибкости. +4531.78 4545.22 "Анатолий Кулаков" Одно из интереснейших нововведений — это то, что вы теперь можете рассказать инструментам, то есть вот этим AI-агентам, которых будет много-много-много, к каким функциям, к каким областям студии у них есть доступ. +4545.22 4566.22 "Анатолий Кулаков" Например, вы можете ограничить, что какой-то агент может работать только в IDE и в дебагере, какой-то только в профайлере, а какой-то может обращаться только к Azure и GitHub, то есть такие получились секции с ограничениями доступа, что тоже можно хорошо использовать для того, чтобы каким-то образом нивелировать доступ к чувствительной информации тех агентов, которым вы не очень доверяете. +4566.22 4583.70 "Анатолий Кулаков" Пример есть интересный в статейке, который рассказывает про использование Copilot для профилирования, то есть каким образом агент может вам позволить улучшить ваш опыт с бенчмарками и профилированием. +4583.70 4590.02 "Анатолий Кулаков" Например, вы можете сказать товарищу агенту, запусти ко мне бенчмарк и прооптимизируй тот код, который он выполняет. +4590.02 4612.64 "Анатолий Кулаков" В этот самый момент у вас агент запустит бенчмарк, запустит профайлер, под профайлером посмотрит, а какой код тормозит, изменит этот код в зависимости от своих предпочтений, то есть каким-то образом прооптимизирует его, перезапустит бенчмарк, убедится, что все стало хорошо и предложит, соответственно, пользователю применить те изменения, которые он произвел. +4612.64 4624.04 "Анатолий Кулаков" Звучит в принципе прекрасно, можно зайти в агента, сказать ну-ка товарищ агент, поулучшай ко мне, прооптимизируй все приложение, перезапускай, сам проверь и убедись, что все хорошо. +4624.04 4638.76 "Анатолий Кулаков" И более того, агент делает не просто какие-то дурацкие перестановки местами переменных или изменения самых примитивных ошибок пользователя, которые только есть, изменение объектов на нормальные листы или еще что-то в этом духе. +4638.76 4644.16 "Анатолий Кулаков" Агент вполне способен понять очень сложные оптимизации, которые можно сделать. +4644.16 4648.20 "Анатолий Кулаков" Может быть, как раз таки в этом есть его не только плюс, но и минус. +4648.20 4654.56 "Анатолий Кулаков" Сейчас я вам прочитаю оптимизации, которые он сделал, например, на примере, который представлен в статье. +4654.56 4657.80 "Анатолий Кулаков" Например, он предложил сделать раскрытие цикла. +4657.80 4660.96 "Анатолий Кулаков" Ну, в принципе, может быть в каких-то ситуациях это нормально. +4660.96 4668.56 "Анатолий Кулаков" Дальше он пошел и предложил там заменить, где можно на спаны, ну, наверное, тоже еще терпимо. +4668.56 4676.94 "Анатолий Кулаков" Потом он пошел и предложил заменить этот некоторый код на unsave конструкции, что уже становится сомнительным. +4676.94 4686.22 "Анатолий Кулаков" Дальше он решил, что этого маловато и вполне можно заиспользовать simd, что, наверное, немножко усложнит чтение. +4686.22 4693.20 "Анатолий Кулаков" Представляете, что ваш код, там раскрылись у него циклы, заменились спаны, вставились unsave блоки, какие-то алгоритмы начали использовать simd. +4693.20 4701.66 "Анатолий Кулаков" Я думаю, что обычный цикл оплаты-зарплаты сотрудника вы уже больше никогда не узнаете во всех этих изменениях. +4701.66 4706.96 "Анатолий Кулаков" Поэтому просто так, конечно, его оставлять нельзя, но с другой стороны, действительно поражает, насколько этот чувак умный. +4706.96 4714.08 "Анатолий Кулаков" То есть такие низкоуровневые оптимизации делает, которые может быть раньше доступны были только jitom, а не всем людям. +4714.08 4721.32 "Анатолий Кулаков" Теперь, в принципе, каждый разработчик, каждый джун сможет вам закоммитить оптимизацию в simd. +4721.32 4725.20 "Анатолий Кулаков" Вот оно, новое светлое будущее. +4725.20 4736.56 "Анатолий Кулаков" Еще одним инструментом, функциональностью, который наградили агента, это портирование вашего приложения со старого фреймворка на новый. +4736.56 4744.32 "Анатолий Кулаков" Мы помним, что есть огромное количество разных инструментов, не только от Microsoft, которые помогают вам как раз переходить между версиями .NET с одного на другой. +4744.32 4748.96 "Анатолий Кулаков" Кажется, что морально все эти инструменты больше не нужны, что они устарели. +4748.96 4759.56 "Анатолий Кулаков" Но потому что у нас есть агенты, которые прекрасно умеют обращаться с кодом, прекрасно умеют его понимать, и не на уровне каких-то regex-ов или даже рослиновских деревьев, а на уровне семантики. +4759.56 4768.24 "Анатолий Кулаков" Поэтому, скорее всего, как раз задача переноса с одного фреймворка на другой фреймворк должна решаться как раз с этими инструментами. +4768.24 4783.24 "Анатолий Кулаков" И, кстати, заявляется, что да, действительно, Copilot теперь может очень хорошо и прекрасно переносить со старых фреймворков на любой другой, в частности на дотной десятой, вы точно так же можете переехать с помощью незаврядного искусственного интеллекта. +4783.24 4799.28 "Игорь Лабутин" Ну, в общем, когда слушал я тебя, и непонятно, хочу ли я двадцать шестую студию, вроде как какие-то интересные штуки есть, но как-то не тянет на +4 в моде мажорной версии. +4799.28 4808.76 "Анатолий Кулаков" Видишь, скорее всего, у тебя не будет выбора, если Microsoft скажет, что он тебе не даст дотной десятой без неё, то, скорее всего, ты будешь вынужден её поставить. +4808.76 4810.68 "Игорь Лабутин" Ну, тоже верно, да. +4810.68 4819.48 "Игорь Лабутин" Ну ладно, будем посмотреть, посмотрим, когда это всё доберётся до релиза, я так думаю, что в ноябре это уже, наверное, покажут полноценный финальный релиз. +4819.48 4823.24 "Анатолий Кулаков" Обязательно, вместе с фреймворком, скорее всего, запустят и новую студию. +4823.24 4826.44 "Анатолий Кулаков" Может исправить все эти косяки, все эти баги, которые сейчас народ находит. +4826.44 4835.72 "Анатолий Кулаков" И может прислушаться к каким-то замечаниям с раздражающим UI элементом, и вот это тоже немножко как-то изменит. +4835.72 4837.08 "Игорь Лабутин" Ну хорошо, ладненько. +4837.08 4844.80 "Игорь Лабутин" Так, наверное, сегодня у нас с новостями Microsoft почти всё. +4844.80 4850.68 "Игорь Лабутин" Давай мы расскажем ещё про то, что мы закончили очередной дотный труд. +4850.68 4855.64 "Игорь Лабутин" Когда я говорю "мы", я подразумеваю дотный труд. +4855.64 4869.96 "Игорь Лабутин" Мы закончили большой очередной труд по переводу уже нашей седьмой книжки, и это C# Concurrency от Нирты Бавицки про современные конкуренции в Дотнете. +4869.96 4878.76 "Анатолий Кулаков" Я напомню для тех, кто, может быть, не в курсе, что Дотнетру занимается адаптацией англоязычных книг под русский перевод. +4878.76 4883.64 "Анатолий Кулаков" То есть, по сути, там переводят, делают научную вычетку, и у нас уже вышло такое большое количество книг. +4883.64 4891.72 "Анатолий Кулаков" Сейчас мы перечислять их, наверное, не будем, их всегда можно найти в нашем чатике, там есть не только книги, но и ссылки на их покупку, и промокоды с приятной скидочкой. +4891.72 4897.00 "Анатолий Кулаков" Вот, да, появилась новая книга совсем-совсем недавно, прям горячие пирожки, только с полочки. +4897.00 4929.64 "Игорь Лабутин" Да, книжка, несмотря на то, что у нас довольно много всего меняется в Дотнете, книжка довольно полезная, книжка рассказывает и про базовые основы конкуренции, и про всякие штуки, которые есть в современном Дотнете, всякие value tasks, async и numerables, и довольно, я бы сказал, практичная и не очень длинная, то есть она всего 250 с чем-то страничек, то есть она не очень толстая, но за эти 250 с чем-то страничек вы, мне кажется, узнаете практически все, что нужно для успешной работы с конкуренцией в Дотнете. +4929.64 4934.20 "Игорь Лабутин" Она, в каком-то смысле, ну не то, что дополняет. +4934.20 4970.00 "Игорь Лабутин" Когда мы говорим о конкуренции, наверное, первым, кто приходит в голову в Дотнет мире, это, конечно, Стивен Клери, мы неоднократно обозревали его статьи, вот буквально недавно про cancellation серию статей от него рассказывали, и у него есть книжка по C# конкуренции, но она довольно старая, 6 лет назад она была выпущена, в 2019 году, она не то, чтобы потеряла свою актуальность, но там все-таки нет всяких современных вещей типа async и numerables, и frozen коллекции, и всяких прочих таких штук, которые есть сейчас в современном Дотнете и вполне могут использоваться. +4970.00 5008.72 "Игорь Лабутин" Понятно, что даже книжка, которая вышла сейчас в 2025 году, возможно, с выходом какого-нибудь 10 или 11 Дотнета тут же безнадежно устареет, но я думаю, что конкуренция как раз это вот та самая тема, где особого устаревания общих принципов точно не будет, возможно будут меняться какие-то конкретные штуки, будут приходить и уходить конкретные классы и типы коллекции, но если вам хочется разбираться, можно читать Клери, а можно читать эту книжку, она тоже более чем достойна, хорошо переведена, Дотнетруп постарался, и я думаю, вы должны получить удовольствие и полезность. +5008.72 5040.38 "Анатолий Кулаков" На хабре у нас вышла статья, в которой непосредственно участники перевода делятся своим мнением, можно почитать их отзывы, можно посмотреть, как происходит сам процесс, ну а если вас вдруг заинтересовала возможность самому поучаствовать в таких экспериментах, как переводы книг, то милости просим, опять же, все ссылки есть в статье на хабре, у нас есть чат переводчиков, и я думаю, что в ближайшее время мы посмотрим, какую бы еще книгу следующую взять в перевод, и вы непосредственно можете поучаствовать в этом решении. +5040.38 5062.96 "Игорь Лабутин" Это во-первых, а во-вторых, я бы хотел добавить, что для того, чтобы поучаствовать в наших переводах, совершенно не обязательно быть профессиональным переводчиком или знать английский на зубок или еще что-нибудь, достаточно просто вашего желания принести пользу в этой области, а мы найдем, какой частью работы вас нагрузить, так скажем. +5062.96 5070.32 "Игорь Лабутин" У нас есть много разных задачек в рамках перевода, не все из них требуют даже знания английского, в каком-то смысле, знания C# будет более чем достаточно. +5070.32 5081.60 "Анатолий Кулаков" Я бы даже сказал, пригодятся люди, которые просто знают русский, которые могут хорошо, красиво строить предложение и находить хорошие заменители, синонимы и так далее. +5081.60 5082.60 "Анатолий Кулаков" Такие люди тоже нужны. +5082.60 5083.60 "Игорь Лабутин" Да, тоже верно. +5083.60 5088.48 "Игорь Лабутин" Так, ну и у меня есть еще небольшая новость в раздел кратко о разном. +5088.48 5094.32 "Игорь Лабутин" Технически ее можно было бы, конечно, в релиз кандидат запихнуть, но это все-таки немножко отдельная штука. +5094.32 5123.44 "Игорь Лабутин" Напомню, что уже много лет, начиная с, по-моему, 3 какого-то dotnet core, а может даже с 5-го уж точно, но по-моему чуть раньше это началось, у нас есть LTS и STS релизы, да, long-term support и short-term support релизы, четные у нас LTS, вот как раз сейчас у нас будут LTS релизы, они поддерживаются 3 года, то есть по сути, как только выходит следующий LTS, у вас есть еще год, чтобы перейти на него, ну как бы это нормально. +5123.44 5134.96 "Игорь Лабутин" А есть short-term support, это нечетные релизы, и у них цикл саппорта был 18 месяцев, то есть поддерживается до следующего LTS и еще полгода, ну чтобы у вас был тоже буфер перейти. +5134.96 5222.04 "Игорь Лабутин" Но теперь у нас изменения, теперь short-term support саппортится 2 года, то есть грубо говоря у них будет саппорт истекать вместе с LTS, который был зарелизен до них, то есть какая-нибудь девятка будет поддерживаться до той же даты, что и восьмерка, почему это сделали, сделали это ради всяких разных продуктов, которые напрямую не относятся к дотнетам к релизному циклу, ну например, Aspire, то есть Aspire он релизится, понятное дело, чаще, он релизится совершенно не в те даты, когда релизится основной дотнет, и из-за этого может происходить такая штука, что Aspire к себе затаскивает какие-то кусочки, библиотек, не знаю, ну гетзависимости или еще чего-нибудь, которые новее, чем LTS, которым вы пользуетесь, и может получиться так, что в вашем продукте будут кусочки от Aspire, либо еще от чего-то, я напомню, что Aspire, даже если вы не пользуетесь Aspire вот этим даже бордом, вот этим всем, все равно там есть полезные штуки, потому что там есть, например, полезные дефолтные конфигурации для всяких там редисов, сиквелов и прочего всего, а вот получится, что вы в основной продукт, который вы хотели бы держать на LTS, затянете кусочки STS, и получится, что у вас уже не год после очередного LTS, чтобы перейти, а всего полгода. +5222.04 5237.88 "Игорь Лабутин" Это нехорошо, видимо, некоторым заказчикам это не нравилось, поэтому теперь для выравнивания вот этого всего STS немножко продлили, и теперь они прям вообще идеально выровнены с LTS-ами, и будут заканчиваться одновременно, чтобы вы могли успевать перейти на следующий LTS без проблем. +5237.88 5238.88 "Игорь Лабутин" Такие дела. +5238.88 5243.24 "Анатолий Кулаков" Да, удобная, удобная штука, в принципе, должна стать в себе пользовательной. +5243.24 5244.24 "Анатолий Кулаков" Хорошо. +5244.24 5252.80 "Анатолий Кулаков" Не знаю, насколько Microsoft было трудно это сделать или поддерживать, наверняка они больше сил будут тратить на полгода побольше, но клиентам точно намного удобнее с этим жить. +5252.80 5253.80 "Игорь Лабутин" Да, однозначно. +5253.80 5268.16 "Игорь Лабутин" Ну вот, примерно у нас такое на сегодня, не очень длинно, в основном про Microsoft, хотя все равно полтора часа почти наговорили, по моему внутреннему таймеру, по крайней мере, казалось бы, а ну это Тал постарался, я знаю. +5268.16 5283.20 "Игорь Лабутин" Так, ну мы успели обсудить DotNet 10 релиз кандидата 1, успели поговорить про Performance Improvements в DotNet 10, успели обсудить, что нас ждет в 26 Visual Studio и новая книжка C# Concurrency в правильном переводе DotNet True. +5283.20 5288.80 "Игорь Лабутин" На этом для 123 выпуска у нас больше тем нет и я думаю, что пора прощаться. +5288.80 5314.28 "Анатолий Кулаков" Всем до новых встреч, не забывайте про наши бусти, комментарии, шары или посты, рассказывайте своим друзьям, заходите, смотрите, что у нас интересного на бустях, если будете в Питере, заходите на митапы сообщества spb.net и если вы наш подписчик, то я думаю на митапах можно будет попросить наши сувенирчики, которые у нас остались после конференции, я вам их обязательно подарю. +5314.28 5318.60 "Игорь Лабутин" Мы будем очень рады всех вас видеть, со всеми пообщаться, а на сегодня пока. +5318.60 5319.60 "Игорь Лабутин" Пока! diff --git a/input/Radio/Transcriptions/RadioDotNet-124.txt b/input/Radio/Transcriptions/RadioDotNet-124.txt new file mode 100644 index 0000000..31d8db9 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-124.txt @@ -0,0 +1,488 @@ +0.00 12.46 "Анатолий Кулаков" Здравствуйте дорогие слушатели, в эфире Radio.net выпуск номер 124. +12.46 15.58 "Анатолий Кулаков" В студии ее постоянные ведущие Анатолий Кулаков +15.58 16.58 "Игорь Лабутин" и Игорь Лабутин. +16.58 17.58 "Игорь Лабутин" Всем привет! +17.58 20.84 "Анатолий Кулаков" Ну а за нашими плечами, конечно же, наши прекрасные помогаторы. +20.84 32.44 "Анатолий Кулаков" Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко, Оля болит ножка, поэтому пожелаем ей скорейшего выздоровления. +32.44 48.68 "Анатолий Кулаков" Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев, Юрий Лодейкин, Катков Михаил. +48.68 57.60 "Анатолий Кулаков" Друзья, всем большое спасибо, а если вы хотите тоже поддержать наш прекрасный подкаст, то милости просим на Boosty, у нас там есть много всего интересного. +57.60 64.80 "Игорь Лабутин" А теперь представьте, что вы с утра открываете Jiro, а там вас ждет задача научиться математически оценивать силу БК в кариде. +64.80 71.88 "Игорь Лабутин" Именно с такой задачей столкнулся недавно один из C#-программистов в Altenar, международном разработчике ПО для зарубежных беттинг-операторов. +71.88 76.24 "Игорь Лабутин" ПО компании Altenar не менее стабильны, чем их постоянная поддержка нашего подкаста. +76.24 83.92 "Игорь Лабутин" О том, как считать вероятности и силу команд, игроков для разных видов спорта и какие дотнет-библиотеки для этого подходят, ребята рассказывали весной на митапе. +83.92 88.00 "Игорь Лабутин" Найти запись доклада можно на ютубе dotnet.ru, а больше историй про компанию в их телеграме. +88.00 98.20 "Анатолий Кулаков" Что ж, у нас сегодня насобиралось много таких интересных статейчиков, но я думаю, начать мы все обязаны просто с нового Espyro. +98.20 114.32 "Игорь Лабутин" Давненько у нас не было Espyro, но команда не стоит на месте, не спит, можно сказать, и доползла, я бы сказал, до релиза 9.5, потому что кажется, что вроде они обещали раз в месяц, но что-то мне подсказывает, что мы их как-то давно, последние Espyro обозревали. +114.32 118.64 "Игорь Лабутин" Или может, мне уже кажется, ну неважно, ладно, давайте посмотрим, что такое. +118.64 124.68 "Анатолий Кулаков" Обязательно никто не мешает тебе релизить, знаешь, какие-нибудь минорные фичи, можно каждый месяц пообещать и один баг-фикс в документации релизить. +124.68 131.76 "Игорь Лабутин" Не, ну это не релиз, релиз — это когда статья на DevBlocks, там вот это всё, вот это релиз, я понимаю, а так это… +131.76 135.52 "Анатолий Кулаков" Ты же видел статьи у этого Маюя, performance improvements. +135.52 145.68 "Игорь Лабутин" А, ну так да, ладно, хорошо, нет, здесь не только performance improvements, здесь некоторое количество интересных вещей появилось, и давайте по ним по порядочку пробежимся. +145.68 177.32 "Игорь Лабутин" Во-первых, в превью режиме пока добавилась команда Espyro Update, которая позволяет автоматически проапдейтить SDK, ну версии SDK и всех ваших интеграций, это я напомню компоненты внутри Espyro, да, которые позволяют быть как-то правильно преднастроенными, либо добавлять какую-то функциональность в ваше приложение, там клиентские библиотеки, вот это всё, вот их можно теперь обновлять одной командой, Espyro Update, оно всё обновит до последних версий, всё как надо, причём можно выбирать из какого ченнела обновлять, там превью, стейбл, вот это всё. +177.32 190.80 "Игорь Лабутин" Пока сама команда в превью, но видимо на неё есть некоторые надежды, и видно, что Microsoft пытается сделать максимально простой инструмент, чтобы можно было с ним максимально просто работать. +190.80 224.04 "Игорь Лабутин" И следующая фича, это как раз проект, это называется Single File App Host, я напомню, что в типичном Espyro приложении у нас есть, ну ваш основной проект, например, App Service, и можно там сделать проект отдельный, в смысле нужно сделать проект под названием App Host, это то, где вы собственно описываете модель вашего приложения в терминологии кодом Espyro, да, то есть какие зависимости, кто от кого как зависит, где какие там connection string, и вот это всё, какие там docker-контейнеры дополнительно надо запустить, и всё такое прочее. +224.04 261.44 "Игорь Лабутин" Так вот теперь можно не делать отдельный css-proj, потому что теперь поддержана штука под названием Single File App Host, для того чтобы это сделать, сначала нужно включить фичу, с помощью command-line aspire-config-set-features.single-file-app-host-enabled пробел true, ну в общем поставить эту фичу в true, и после чего все ваши вот там команды dotnet, new, espire и прочее будут работать с одним сингл-файлом, то есть всё ваше описание espire, как бы приложение, всё что было в апхасте, оно будет лежать в одном единственном css-файлике, и его будет достаточно, чтобы всё запускать. +261.44 278.56 "Игорь Лабутин" То есть работа явно идёт в сторону как можно более лёгкой, лёгкой что ли, ну не интеграции, а лёгкого написания вот этого апхаста, чтобы как можно меньше нужно было задуматься, какой css-proj, а какой тип у него надо задать и так далее. +278.56 281.56 "Игорь Лабутин" Создали css-файлик и погнали, всё в нём делаем. +281.56 308.64 "Игорь Лабутин" Естественно, не обошлось без импрувментов в дешборда, но в этот раз они не такие большие, из интересного добавили раскраску консольных логов, то есть теперь можно выбрать и смотреть логи не только одного приложения, но и нескольких, это по-моему можно было и раньше делать, но теперь они расцвечиваются разными цветами, что зелёненький там из одного сервиса, красненький от другого сервиса, не знаю, что будет, если у вас там 20 сервисов, насколько эта радуга будет читабельна, но возможно там… +308.64 311.08 "Анатолий Кулаков" 255 цветов-то у нас есть, как минимум. +311.08 323.40 "Игорь Лабутин" Ну это да, но может быть это удобно, если нужно действительно посмотреть, а что происходило в какой-то момент в целом в продукте, в какой-то конкретный момент, просто чисто что логи на одном экране были. +323.40 327.64 "Игорь Лабутин" Иногда пригождается, но почему нет. +327.64 346.44 "Игорь Лабутин" Видимо, кто-то хотел, запилили, значит, и добавили, конечно же, новых LLM-инсайтов, то есть теперь во всяких там трейсах и прочих будут всякие иконочки, подсказочки про то, что вот тут, наверное, у вас что-то не то, вот здесь что-то не то, LLM, значит, и всякие агенты не спят и проникают в Aspire тоже. +346.44 347.44 "Игорь Лабутин" Интеграции. +347.44 358.88 "Игорь Лабутин" В интеграциях тоже есть обновление, добавили AI Hosting, можно теперь сказать add OpenAI и у вас будут что-то OpenAI-совместимое. +358.88 363.34 "Игорь Лабутин" Дальше, к чему вы там подключите, надо смотреть, там довольно развесистая интеграция. +363.34 370.26 "Игорь Лабутин" Есть Azure AI Foundry Models, ну, в общем, AI, видимо, должен быть в каждом релизе и без него никуда. +370.26 382.46 "Игорь Лабутин" Добавили интеграцию для поддержки Azure DevTunnels и для поддержки статик-файлов в YARP, YARP-интеграция уже была, но там не было поддержки deployment, ну, в смысле, раздачи статических файликов, теперь есть. +382.46 421.86 "Игорь Лабутин" И из интересных фичей, которые, правда, требуют, точнее, это не фича самого Aspire, это фича Visual Studio 2026, то, что если вы отлаживаете ваш процесс, ваш, точнее, Aspire-приложение в Studio 2026, то там будут так называемые cross-process call-stakes, то есть, если у вас есть, например, какой-нибудь ваш сервис, который по росту вызывает другой сервис, то в Visual Studio вы будете видеть это как единый call-stake, несмотря на то, что это реально network call, но студия теперь умеет это показывать как будто это в одном процессе и просто call-stakeм вы можете бегать между разными процессами, даже в рамках типа одного такого виртуального call-stake. +421.86 423.34 "Анатолий Кулаков" Ну, звучит круто. +423.34 429.66 "Игорь Лабутин" Да, звучит круто, ну, нужна студия, правда, 2026, но, может быть, это куда-нибудь еще доползет. +429.66 455.26 "Игорь Лабутин" И, в принципе, в 9.5 из ногинок все, но команда вспомнила, что она какое-то время назад, а мы это обозревали, обещала регулярные релизы раз в месяц, вот это все, и был даже выкачан некий roadmap, в котором было описано, что они планируют сделать, ну, там не было описано сроки, правда, поэтому не было понятно, за какой период они это планируют сделать, вроде как запланировано примерно на год, но кто знает, кто знает. +455.26 560.14 "Игорь Лабутин" В результате, ну, часть действительно сделана, часть в импрогрессе, часть даже не начата, в ту часть, которая не начата я даже не хочу погружаться, потому что не факт, что и начнется, а вот из того, что сейчас в импрогрессе движется потихонечку фича под названием выполнение команд в контейнерах, то есть если у вас есть докер-контейнер какой-то, он в нем запущен, то можно в нем будет выполнить команду, ну, аналог, грубо говоря, докер-экзек только средствами Испайра, дальше есть фича, которую Майкрософт как-то по, ну, скажем так, косвенной информации очень хочет, но она требует довольно большой работы, это built-in runtime acquisition, то есть чтобы, имея Испайр-приложение, оно могло само себе скачать нужный рантайм, будь то джава, питон, тут нет, там, чего угодно, и поставить на нужные приложения, на хост и запуститься, https-everywhere, в том числе по локальной разработке, то есть автоматическое получение сертификатов с правильными, там, доменными именами .local, ну, search-filtering, это в даже борде, видимо, command-line interface, то, что мы обсуждаем, каждый релиз, они действительно его потихонечку двигают, они очень хотят побольше вложиться в документацию со всякими шаблончиками и примерами, сейчас видим, особенно для разных языков, и с точки зрения разных языков, наверное, пожалуй, самая сложная фича из того, что заявлено и что уже в прогрессе, это cross-language-app-host, то есть сейчас апп-хост требует, понятно, .NET-рантайм, потому что это .NET-приложение, но если, например, вы хостите какое-нибудь питоновское приложение, то, казалось бы, ну, придется тащить .NET-рантайм, питон отдельно, в общем, они хотят с помощью ВАЗМа запихнуть как можно больше рантаймов, грубо говоря, в один апп-хост. +560.14 562.46 "Игорь Лабутин" Посмотрим, что из этого получится. +562.46 577.06 "Анатолий Кулаков" Слушай, ну идея интересная, вот использовать ВАЗМ как такой cross-платформенный, cross-языковой контейнер, она, в принципе, много где уже стреляет, много где применяется, если ее к себе спайр возьмет, то из этого может что-то интересное получиться. +577.06 601.90 "Игорь Лабутин" Да, это действительно интересно, но проблема, видимо, одна из проблем в том, что все-таки, во-первых, все рантаймы сильно разные, не все там идеально заточены под ВАЗМ, и вторая проблема, что все-таки Aspire требует заработать с окружением довольно много, ну там с Docker совсем, чтобы все это запускать, поэтому, ну вероятно, есть какие-то ограничения, я не слежу, честно говоря, что там происходит, жду, когда они это зарелизят хотя бы в каком-нибудь превью виде, тогда мы, конечно, посмотрим и разберем. +601.90 606.22 "Игорь Лабутин" MCP-сервер для Aspire сейчас в разработке, куда же без MCP. +606.22 628.34 "Игорь Лабутин" Вот, и в дипломентах, напомню, что Aspire захотел сделать нормальные дипломенты, first-class, так сказать, в Docker, Uber и так далее, это все пока в InProgress, но в том числе они хотят поддержку Environment нативно затянуть, то есть чтобы вы могли сказать, что вот это мы дипломим для проды, а это для теста, хотя, напомню, что еще год назад говорилось, что не-не-не, Aspire — это не для проды, не надо. +628.34 651.14 "Игорь Лабутин" Ну, видимо, опять же, сам Aspire не для проды, но сгенерить какой-нибудь продовый манифест с подставленными продовыми, не знаю, секретами или еще чем-то, ну почему нет, особенно если вы деплоитесь напрямую в Azure, а это, видимо, пока приоритетный сценарий, потому что Docker и Uber, как я говорю, пока нативно еще не идеально поддержаны, лучше пользоваться, вроде, пока сторонним Aspire-эйтом. +651.14 656.86 "Игорь Лабутин" Ну вот, какие-то такие у нас дела про Aspire 9.5 и про их roadmap. +656.86 665.26 "Анатолий Кулаков" Ну и может быть там Aspire до 9-го не для проды, а вот Aspire 10 мы передумали, как бы вперед будет, и можно +665.26 666.26 "Игорь Лабутин" в прод. +666.26 679.18 "Игорь Лабутин" Ну, про Aspire 10 пока непонятно, то есть если верить roadmap, который там написан, в смысле, вот тот, который я осмотрел, там не то чтобы есть какие-то супер прорывные фичи, а хочется от LTS 10, наверное, может быть и чего-нибудь интересненького. +679.18 692.22 "Игорь Лабутин" С другой стороны, может они что-то там и готовят в фоне, именно поэтому в 9.5 и, возможно, каких-нибудь последующих, сколько они еще, хотя уже не успеют больше ничего выпустить, месяц остался до релиза 10. +692.22 701.26 "Игорь Лабутин" Может что-нибудь выпустят интересненькое, ну а может просто Aspire 10 будет такой проходной, в смысле, что не будет какого-то отдельного приуроченного, как в 10. +701.26 715.18 "Анатолий Кулаков" Видишь, вроде Aspire это вот единственный проект, который удивляет внезапно при релизах, помнишь, как он сам появился, как он и релизился, ну то есть может быть там команда как раз держит в рукаве какую-то мега фичу и расскажет нам о ней попозже, когда будет основной релиз. +715.18 717.70 "Игорь Лабутин" Будем надеяться, что-нибудь интересненькое. +717.70 726.54 "Анатолий Кулаков" Ну что ж, пойдем дальше, у нас есть еще один интересный анонс, это анонс Trusted Publishing для Nuget.org. +726.54 738.02 "Анатолий Кулаков" Это Nuget выпустила интересную интеграцию и вроде бы ничего, ну такая хорошая интеграция, она кросс-языковая, кросс-тулзовая, поэтому хочется на нее посмотреть получше. +738.02 741.06 "Анатолий Кулаков" И плюс она секьюрная, а секьюрити – это всегда интересно. +741.06 746.98 "Анатолий Кулаков" Поэтому пойдем посмотрим, что же такое случилось, что такое Trusted Publishing Enhancement Security. +746.98 756.46 "Анатолий Кулаков" Итак, если кратко, то это безопасный способ взаимодействия между различными паблишинг-репозиториями или паблишинг-экшенами. +756.46 762.94 "Анатолий Кулаков" Например, как GitHub-экшен, и сторджем пакетов, например, как Nuget. +762.94 766.14 "Анатолий Кулаков" Давайте же посмотрим, что такое за взаимодействие интересное. +766.14 769.94 "Анатолий Кулаков" Как сейчас работает, например, паблиш пакетов. +769.94 775.94 "Анатолий Кулаков" Ну, для примера, здесь используются везде GitHub-экшен и Nuget, Nuget.org, который. +775.94 782.70 "Анатолий Кулаков" Вот, если вам, допустим, в GitHub-экшен захочется запаблишить пакеты в Nuget.org, что нам необходимо будет сделать? +782.70 787.06 "Анатолий Кулаков" Ну, во-первых, мы должны будем пойти на сайт Nuget, генерить там API-ключ. +787.06 789.98 "Анатолий Кулаков" Этот API-ключ будет очень большой, секретный и страшный. +789.98 797.98 "Анатолий Кулаков" Никому его, естественно, выдавать нельзя, потому что в противном случае под именем вашего пакета могут запаблишить в Nuget какого-то троина. +797.98 803.66 "Анатолий Кулаков" А если у вас много потребителей, много клиентов, то это прямой способ заразить всех и вся. +803.66 807.46 "Анатолий Кулаков" Поэтому это довольно важный ключ, довольно сильно нужно его беречь. +807.46 810.82 "Анатолий Кулаков" Поэтому мы его сохраняем в секретное хранилище для GitHub-экшенов. +810.82 815.30 "Анатолий Кулаков" И, так как это важный секретный ключ, обязательно не забываем ротировать. +815.30 820.58 "Анатолий Кулаков" То есть менять его постоянно через какое-то время или вдруг если что-то произошло, в общем, обязательно обновляем. +820.58 837.30 "Анатолий Кулаков" И вот эта вот связка, когда мы должны иметь вообще такой большой секретный ключ, доверить его GitHub-экшену, позволить не забыть его ротировать или всей остальной команде напоминать, что надо ротировать, когда вы уходите в отпуск. +837.30 840.22 "Анатолий Кулаков" В общем, это типичное место для уязвимостей. +840.22 846.54 "Анатолий Кулаков" То есть ключ может утечь, так как много человек к нему могут иметь доступ для того, чтобы ротировать. +846.54 848.82 "Анатолий Кулаков" Может через кого-то из них утечь. +848.82 855.38 "Анатолий Кулаков" В общем, схема, в принципе, надежная, она используется всегда и везде, но было бы прекрасно, если бы этого узла не было. +855.38 860.34 "Анатолий Кулаков" И вот как раз Trust Publishing протокол, он и позволяет избавиться от вот этой связки. +860.34 862.78 "Анатолий Кулаков" Что это такое? +862.78 869.66 "Анатолий Кулаков" Это прежде всего специальная договоренность, специальный протокол, который использует стандартный Open ID Connect. +869.66 873.78 "Анатолий Кулаков" Это протокол, который широко используется во всей индустрии. +873.78 885.94 "Анатолий Кулаков" И используется протокол для того, чтобы связать вместе инфраструктурного провайдера, такого, например, как GitHub Actions, и репозиторий пакетов, такого, например, как Nuget. +885.94 888.82 "Анатолий Кулаков" И чем эта штука помогает? +888.82 894.50 "Анатолий Кулаков" В общем, она заставляет GitHub Actions напрямую общаться с Nuget.org. +894.50 915.90 "Анатолий Кулаков" Благодаря этому мы можем избежать вот этого API-ключа, который долго живет и с помощью которого мы раньше вынуждены были доступаться до Nuget.org, т.е. теперь не будет больше большого секретного ключа, т.е. нет больше какой-то чувствительной информации, которую мы обязаны хранить в environment нашего Continuous Integration Агента. +915.90 920.26 "Анатолий Кулаков" Соответственно, меньше шансов, что этот ключ утечет. +920.26 923.94 "Анатолий Кулаков" Если его нет, то ему и не утекти. +923.94 933.28 "Анатолий Кулаков" Дальше у нас появляется короткоживущий ключ, который временно создается на момент работы Build-агента. +933.28 947.20 "Анатолий Кулаков" Обычно срок жизни этого ключа 1 час, т.е. вот это как раз тот ключ, который может уже утечь, но так как он создается на 1 час, кажется, что это не так страшно, как большой ключ, который обычно создавался на месяц и может быть даже годы раньше. +947.20 950.92 "Анатолий Кулаков" В общем, то, что он создается на 1 час, это уже сильно уменьшает вектор атаки. +950.92 969.28 "Анатолий Кулаков" Еще один интересный момент, то, что один ключ создается на 1 job, т.е. каждый Build-джоб в экшенах, который запускается, он получает свой собственный, именной, красивый, одноразовый ключ, с помощью которого он уже сможет эти пакеты непосредственно запаблишить в NuGet-репозиторий. +969.28 973.08 "Анатолий Кулаков" Вот, например, в NuGet-орк. +973.08 979.98 "Анатолий Кулаков" Почему я все время переговариваю, например, в NuGet-орк, например, GitLab, потому что, как я уже сказал, это такой кросс-репозиторный протокол. +979.98 984.76 "Анатолий Кулаков" Вообще его придумали питанисты и опубликовали, а потом реализовали абсолютно все. +984.76 993.88 "Анатолий Кулаков" Например, для People в Python, для RubyGames в Ruby, для NPM в JavaScript, он тоже поддерживается. +993.88 998.08 "Анатолий Кулаков" И теперь для NuGet-орка в .NET мы тоже можем им пользоваться. +998.08 999.88 "Анатолий Кулаков" А как же его настроить? +999.88 1003.40 "Анатолий Кулаков" Ну, во-первых, необходимо настроить NuGet-орк. +1003.40 1009.04 "Анатолий Кулаков" Мы должны залогиниться в NuGet-орк, зайти в менюшку Trusted Publishing, создать там специальную policy. +1009.04 1012.28 "Анатолий Кулаков" Policy – это как раз то правило, которое будет определять, о кому мы доверяем. +1012.28 1028.36 "Анатолий Кулаков" И в это правило мы должны вписать имя нашего пакета, репозиторий на GitHub, которым мы доверяем, имя workflow файла даже, которому мы доверяем, то есть мы можем разделить вот этот workflow файл может к нам публишить, вот этот не может. +1028.36 1032.60 "Анатолий Кулаков" В общем, там есть куча всяких тонких настроек, которые можно затянуть по самому не хочу. +1032.60 1035.56 "Анатолий Кулаков" И на этом, в принципе, все. +1035.56 1039.40 "Анатолий Кулаков" Вот мы policy создали, теперь нам необходимо настроить наш GitHub Actions. +1039.40 1049.88 "Анатолий Кулаков" Он тоже настроится довольно просто, там буквально нужно добавить пару пермишенов, которые говорят, иди обменивай токен у нашего пакетча-репозитория, и GitHub Actions все прекрасно понимает. +1049.88 1055.40 "Анатолий Кулаков" Как это работает под капотом, давайте разберемся уже низкоуровнево на уровне протокола, потому что это интересно. +1055.40 1073.04 "Анатолий Кулаков" Теперь, когда мы все настроили и запустили нашего билд-агента, который, по идее, должен сбилдить наш проект в репозитории и запаблишить пакет в NuGet-орк, при этом никакого API-ключа большого NuGet-орка у нас нет, у нас есть просто настроенная связь между этими двумя сервисами. +1073.04 1082.88 "Анатолий Кулаков" Итак, GitHub выпускает специальный токен, ODC токен, для джоба, который он запускает. +1082.88 1100.48 "Анатолий Кулаков" Дальше этот джоб во время логина в NuGet, то есть там есть прописан в экшенах, что надо заходить за логинцем в NuGet, джоб идет логиниться в NuGet и посылает вот этот временный маленький ODC токен NuGet. +1100.48 1119.04 "Анатолий Кулаков" Этот ODC токен - это подписанный JVT, и в нем зашито очень много полезной информации, например, какой репозиторий мы сейчас билдим, какой проект мы сейчас билдим, какой опять же workflow-файл участвует в билде, то есть вот эти все данные, все атрибуты, которые настроены в нашей полисе. +1119.04 1123.04 "Анатолий Кулаков" И, соответственно, все описание workflow. +1123.04 1126.44 "Анатолий Кулаков" В этот момент NuGet-орк валидирует этот токен. +1126.44 1140.48 "Анатолий Кулаков" Он разворачивает JVT и смотрит, но прежде всего он смотрит на сигнатуру токена, что он подписан правильным сертификатом от GitHub, и никому он доверять не будет, то есть любой токен подряд туда не придет, он будет доверять только GitHub-овским токенам. +1140.48 1149.08 "Анатолий Кулаков" И дальше смотрит, насколько все эти атрибуты из JVT токена соответствуют его Trusted Publishing Policy, который мы недавно настроили. +1149.08 1158.24 "Анатолий Кулаков" Если все хорошо, то он создает временный ключ, который обычно живет не больше одного часа, и возвращает его обратно, и обратно в этот экшен. +1158.24 1164.40 "Анатолий Кулаков" Получается в рамках в скоупе экшена у нас уже существует какой-то понятный ключ, который выписал сам NuGet-орк. +1164.40 1172.00 "Анатолий Кулаков" И поэтому workflow, который занимается билдом непосредственно, может взять этот ключ и запаблишить пакеты, которые ему нужны. +1172.00 1187.16 "Анатолий Кулаков" Соответственно, так как ключ выписывается на непродолжительное время, рекомендуется обращаться к NuGet-орку, то есть логиниться в него непосредственно перед паблишем, чтобы точно успели все залить ваши большие жирные пакеты за один час. +1187.16 1197.88 "Анатолий Кулаков" Так как я уже говорил, что это такой кросс-репозиторный формат, протокол, но сейчас он поддерживается только между NuGet-ом и GitHub-ом. +1197.88 1206.20 "Анатолий Кулаков" Соответственно, есть уже много issues, которые требуют поддержать, например, его для GitLab, чтобы GitLab тоже умел в NuGet все паблишить. +1206.20 1209.00 "Анатолий Кулаков" Я думаю, остальные толзы тоже в скором времени подтянутся. +1209.00 1217.36 "Анатолий Кулаков" Вот такой интересный security протокол, который позволил закрыть немножко, сделать наш обмен еще немножко секурнее. +1217.36 1226.28 "Игорь Лабутин" Ну да, вообще тут звучит так, что, не знаю, вот ты сейчас рассказал, кажется, что действительно какой-нибудь OpenID здесь напрашивался довольно давно. +1226.28 1228.28 "Игорь Лабутин" Чего не сделали раньше? +1228.28 1229.28 "Игорь Лабутин" Непонятно. +1229.28 1241.40 "Анатолий Кулаков" Ну да, просто, видишь, OpenID обычно использовался не для выписки таких, не для выписки короткоживущих токенов, а для короткоживущих процессов, что-то такое. +1241.40 1252.12 "Анатолий Кулаков" То есть там обычно устанавливалась какая-то тяжелая сессия, ты этой сессией получал refresh токен, с этим refresh токеном ходил целый год, обновлял, такие солидные процессы решались. +1252.12 1258.76 "Анатолий Кулаков" А вот такое, типа выпиши мне на 3 секунды, я сейчас быстренько пакеты запаблишу и все, такого почему-то было не распространено. +1258.76 1260.88 "Анатолий Кулаков" Наверное, дошли, постепенно дошли к этому. +1260.88 1265.36 "Анатолий Кулаков" Стало это, не жалко ключиков, можно их раздавать. +1265.36 1268.36 "Анатолий Кулаков" Да-да, генерить ключики уже стало не жалко. +1268.36 1283.56 "Анатолий Кулаков" Если мы так весь pipeline настроим, представляешь, там же редакторы смогут доверять репозиториям, репозиториям continuous integration, continuous deployment, и вот на такой цепочке доверия, в принципе, можно выстроить интересный процесс. +1283.56 1290.36 "Анатолий Кулаков" Опять же, что будет, если вдруг одного элемента из них взломают, получат доступ ко всему этому pipeline. +1290.36 1294.76 "Игорь Лабутин" Или даже просто разобраться, почему оно не работает, фиксим, взломают. +1294.76 1300.88 "Игорь Лабутин" А в том, что почему оно у тебя не работает, кто кому не довыдывал токена по пути, тоже будет такое. +1300.88 1307.24 "Анатолий Кулаков" Какого атрибута там с датой или с идентификатором не хватает в этом JVT токене, чтобы все остальные заработали? +1307.24 1308.72 "Игорь Лабутин" Да, будет интересно. +1308.72 1311.32 "Игорь Лабутин" Ну ладно, поглядим, поглядим, насколько это все будет. +1311.32 1314.28 "Игорь Лабутин" Ну, адаптится оно, скорее всего, конечно, будет, куда оно денется. +1314.28 1319.04 "Игорь Лабутин" Так что, наверное, просто, может быть, будут какие-то изменения, дополнения и улучшения. +1319.04 1321.08 "Игорь Лабутин" Так что тут надо глянуть. +1321.08 1322.60 "Игорь Лабутин" А мы пойдем дальше. +1322.60 1346.28 "Игорь Лабутин" И дальше у нас статья, которую, точнее, не так, автор, который пишет статьи, кажется, раз в два года или около того, а именно МАОНИ и очередная статья про Garbage Collector, если быть точным, то про Datas Dynamically Adjusting to Application Size, аббревиатура, то есть динамическое подстраивание Garbage Collector под то, как живет ваше приложение. +1346.28 1358.56 "Игорь Лабутин" Казалось бы, скажем так, внимательные слушатели нашего подкаста должны в этот момент спросить, да ладно, оно же давно включено, начиная с девятки и, в общем, все работает или не работает, ну, у кого как. +1358.56 1371.72 "Игорь Лабутин" И ответ – да, оно включено, начиная с девятки, но девятка была не LTS, поэтому, как справедливо пишет МАОНИ, кто-то увидит этот самый Датас, только получив себе десятку дотнетовую, LTS, и, возможно, будет удивлен. +1371.72 1409.44 "Игорь Лабутин" И поэтому она написала специальную статью, как с Датасом жить, потому что обычно, давайте подумаем, вспомним точнее, что такое, какие фичи Garbage Collector мы знаем в том плане, что вот за время развития дотнета, начиная с дотнет кора, ну, в Garbage Collector на самом деле менялись какие-то моменты, менялись эвристики, он там начинал лучше учитывать количество хипов, количество ядер, которые ему видно, там, в докере или не в докере, мы перешли с регионов на сегменты и вот все такое прочее. +1409.44 1420.60 "Игорь Лабутин" Но надо сказать, что все эти изменения в основном следовали философии Garbage Collector, а именно, они практически не требовали какого-либо взаимодействия с пользователем вообще. +1420.60 1426.60 "Игорь Лабутин" Ну, максимум, если вы видели какую-то регрессию в первых релизах после этой фичи, вы могли выключить временно эту фичу. +1426.60 1429.64 "Игорь Лабутин" Например, там, я не уверен, кстати, что сегменты, например, сейчас можно выключить. +1429.64 1430.64 "Игорь Лабутин" Скорее всего, уже нельзя. +1430.64 1431.64 "Игорь Лабутин" Вот. +1431.64 1452.88 "Игорь Лабутин" И дотнет в целом почти всегда развивался так, что не требуется какая-либо крутилки, какие-либо настройки со стороны пользователя, то есть пользователь только выбирает, я напомню, там Workstation у него ГЦ или серверный ГЦ, раньше можно было еще выбрать concurrent, не concurrent, сейчас, по-моему, мне кажется, какие-то варианты уже отпали. +1452.88 1457.12 "Игорь Лабутин" Ну, в общем-то и все, больше вы ничего не настраиваете. +1457.12 1467.64 "Игорь Лабутин" При этом, иногда все-таки изменения требуют каких-то изменений кода, не впрямую для настройки ГЦ, но могут задеть довольно неожиданный сценарий. +1467.64 1491.56 "Игорь Лабутин" Например, я, кстати, этого не знал, относительно недавно был изменен подход к тому, как делается тримминг, то есть некоторые, ну такая, а-ля компактинг, компактинг, в общем, то, что называется UOH, да, это User Object Heap, то есть это Large Object Heap и Pinned Object Heap, двух этих хипов. +1491.56 1521.96 "Игорь Лабутин" В какой-то момент он назывался, использовал так называемый бюджет, то есть это некоторый рассчитанный объем, который допустил, в рамках которого не нужно будет вызывать garbage collector, грубо говоря, то есть то, что называлось budget-based, он, соответственно, считал, когда нужно триммить, в зависимости от того, насколько большой этот самый бюджет посчитался, в зависимости от объема памяти, паттерна использования, вот этого всего. +1521.96 1553.12 "Игорь Лабутин" В какой-то момент это было заменено на то, что они называют H-based, то есть по факту, на самом деле, то, сколько сборок мусора пережил тот или иной объект, и это возымело некоторый интересный эффект, наверное, все видели паттерн, что если мы, допустим, в каких-то бичмарках, да, хотим узнать точный размер памяти, которое приложение занимает, нужно было сказать gccollect, потом gcwaitfor, как там, finalizers, по-моему, или что-то такое, и потом снова gccollect, два раза, короче, gccollect вызвать. +1553.12 1557.16 "Игорь Лабутин" Это нам гарантировало, что будет точная full сборка. +1557.16 1575.84 "Игорь Лабутин" Так вот, после того, как сказали H-based, учитывая, что дефолтное значение H – это 2, теперь нужно три раза gccollect вызвать, и это такое, ну, как бы, количество кода, которое написано с двумя gccollect-ами, оно велико, и прочно сидит в памяти, напиши два раза gccollect, и все гарантировано, теперь три раза надо писать. +1575.84 1586.48 "Игорь Лабутин" То есть бывают изменения, которые требуют, конечно, таких случаев, но это все-таки, ну, нишевая штука, в обычном продакшн коде gccollect руками, ну, не вызываешь, как правило, особенно два или три раза. +1586.48 1595.16 "Игорь Лабутин" С DATAS все не так, значит, для DATAS это как раз тот кейс, когда его можно и нужно тюнить, потому что он может не подойти к вашему ворклоуду. +1595.16 1620.68 "Игорь Лабутин" Для начала давайте разберемся, ну, давайте так, есть два сценария, где он может, может подойти, для чего он был исходно предназначен, во-первых, он предназначен для ворклоудов с неожиданными пиками по нагрузке, а потом, естественно, ослабление этой нагрузки, при этом у вас некоторые есть ограничения по памяти, либо если у вас небольшое приложение, но вам зачем-то нужен сервер gc. +1620.68 1627.68 "Игорь Лабутин" И поэтому давайте вспомним, что вообще такое сервер gc и почему DATAS может помочь. +1627.68 1630.76 "Игорь Лабутин" Что делает сервер gc? +1630.76 1635.92 "Игорь Лабутин" Ну, во-первых, сервер gc вам создат столько куч, сколько у вас ядер. +1635.92 1652.00 "Игорь Лабутин" И для того, чтобы разные gc потоки не боролись за одну единственную кучу на разных порцах, на разных ядрах, и чтобы разные ядра не упирались в одни и те же локи, сколько у вас ядер, столько у вас будет кучи и столько у вас будет потоков сборки мусора. +1652.00 1658.56 "Игорь Лабутин" Понятно, что у них есть некоторые внутренние синхронизации, потому что ссылки могут, естественно, друг на друга из куч быть. +1658.56 1663.88 "Игорь Лабутин" Но в целом, каждая куча относительно независима и может обрабатываться практически независимо своим потоком. +1663.88 1674.44 "Игорь Лабутин" Но за счёт этого у вас получается, что если вы запускаете ваше небольшое дотнет-приложение на каком-нибудь восьмиядерном процессоре, шестнадцатиядерном, вы генерируете шестнадцать куч. +1674.44 1678.88 "Игорь Лабутин" Даже если в пике у вас там потребление, не знаю, 2 гига памяти, но при этом у вас будет шестнадцать куч. +1678.88 1679.88 "Игорь Лабутин" Как бы вроде оверкил. +1679.88 1689.76 "Игорь Лабутин" Поэтому как раз DATAS призван помочь этому, и он пытается сократить количество используемых куч и таким образом сократить количество памяти. +1689.76 1698.00 "Игорь Лабутин" С другой стороны, если мы говорим про сервер ГЦ, надо вспомнить, что есть и Workstation ГЦ. +1698.00 1700.76 "Игорь Лабутин" Возникает естественный вопрос, а что делать, если у меня Workstation ГЦ. +1700.76 1704.00 "Игорь Лабутин" И тут ответ в том, почему он у вас. +1704.00 1717.84 "Игорь Лабутин" Если у вас он, потому что он вам натурально нужен, то есть, например, он больше оптимизирован на отзывчивость, и поэтому в доступных приложениях его часто используют, то DATAS вам, скорее всего, не нужен. +1717.84 1718.84 "Игорь Лабутин" Он не для этого. +1718.84 1732.76 "Игорь Лабутин" А вот если вы используете Workstation ГЦ, потому что в вашем небольшом приложении сервер ГЦ генерил шестнадцать куч на шестнадцатиядерном процессе, и сжирал кучу памяти, то вот здесь DATAS как раз, скорее всего, поможет, и это прям точный кейс для его применения. +1732.76 1735.04 "Игорь Лабутин" Как вообще работает чудо-технология? +1735.04 1745.68 "Игорь Лабутин" Напомню, мы много раз обсуждали, но, как мало не пишется, в последний раз все поменялось, короче, heuristics поменялись, метрики поменялись, но в целом идея осталась примерно тем же самым. +1745.68 1748.20 "Игорь Лабутин" Значит, в чем идея? +1748.20 1783.88 "Игорь Лабутин" Идея заключается в том, что у вас в определенный момент времени в памяти живет ваше приложение и занимают живые объекты какое-то количество места, при этом реальный объем managed памяти, который используется возможный, больше, потому что есть фрагментация, есть какой-то бюджет на будущее, локейт, который уже заранее преодолоцирован и так далее, и задача DATAS держать реальный объем используемой памяти максимально близким к этому самому, у них это называется live data size, то есть максимально близким к минимально необходимому приложению в данный момент времени, то есть то, сколько оно занимает прямо сейчас. +1783.88 1820.60 "Игорь Лабутин" И здесь есть некоторые, ну, garbage collector, естественно, знает точный размер всех объектов, которые у него хранятся, и в принципе, зная этот размер, он может посчитать тот самый баджет для нулевого поколения, в рамках которого нужно оставаться, чтобы с учетом чистоты сборок мусора попытаться не сильно выбиваться за вот этот спрогнозируемый объем, а с помощью сегментов это сделать попроще, нежели чем с помощью регионов, потому что в регионах, напомню, там был один регион по 128 мегабайт и так далее, а то и больше. +1820.60 1836.92 "Игорь Лабутин" При этом дальше делается следующее, помимо того, что мы можем оценить, сколько памяти надо, это будет некая верхняя оценка, с помощью такой верхней оценки мы можем прикинуть, в какой размер памяти приложение точно влезет. +1836.92 1852.68 "Игорь Лабутин" А возможно, оно влезет и в меньший объем, но если его впихивать в максимально маленький объем, то понятно, что garbage collector должен работать постоянно, чтобы как только появляется какая-то свободная память и неиспользуемый объект, он точно тут же должен обратно возвращаться в систему. +1852.68 1861.12 "Игорь Лабутин" Это тоже плохой сценарий, потому что garbage collector будет тратить здесь на время работы CPU, вместо того, чтобы ваше приложение работало. +1861.12 1867.80 "Игорь Лабутин" Поэтому заводится метрика под названием target throughput cost percentage, которая называется, блин, аббревиатурой TCP. +1867.80 1876.12 "Игорь Лабутин" Я эту статью сначала начал читать не с самого начала, и слово TCP меня очень смущало, пока я не понял, что это аббревиатура, не имеющая отношения к сетевым протоколам. +1876.12 1879.08 "Анатолий Кулаков" Ну как TCP участвует в garbage collector? +1879.08 1880.08 "Игорь Лабутин" Да, вообще никак. +1880.08 1886.12 "Игорь Лабутин" Я пару абзацев прочитал и понял, что зря я пропустил вступление, и надо начать читать со вступления. +1886.12 1898.28 "Игорь Лабутин" Там эти все аббревиатуры, значит throughput cost percentage, то есть некоторый процент цены вот этой пропускной способности, грубо говоря, или не знаю, как-то так. +1898.28 1900.64 "Игорь Лабутин" Смысл этой метрики в следующем. +1900.64 1915.84 "Игорь Лабутин" Это по сути штука, которую можно примерно оценить как процент, то, что мы знаем по метрике процент pause time в NGC, есть такая метрика стандартная, то есть сколько процентов жрет garbage collector. +1915.84 1920.36 "Игорь Лабутин" По дефолту, когда работает датас, это число принимается равно двум. +1920.36 1944.76 "Игорь Лабутин" То есть, грубо говоря, приложение работает, ну если очень грубо, следующим образом, оно как-то считает, в какой объем памяти ваше приложение влезет 100% по некоторым таким очень высокоуровневым эвристикам, дальше пытается понять, насколько можно его ужать, но так, чтобы время работы ГЦ не превысило 2% от общего времени ЦПУ. +1944.76 1957.66 "Игорь Лабутин" Вот, и если оно превысит, то понятно, как бы это плохо, и тогда памяти будет использоваться чуть побольше, и если мы будем укладываться, то памяти будет использоваться поменьше. +1957.66 1987.24 "Игорь Лабутин" Все хорошо, при этом этот TCP можно редактировать через конфиг, то есть можно поставить, например, 1%, тогда garbage collector будет более агрессивно работать, чтобы, ой, наоборот, garbage collector будет менее агрессивно работать, чтобы уложиться в этот 1%, но при этом тогда вы начнете использовать чуть больше памяти, или наоборот, поставить побольше TCP, тогда garbage collector можно будет работать подольше, память приложения будет кушать поменьше, но непонятно зачем, возможно, ну, может и есть такие сценарии. +1987.24 2001.68 "Игорь Лабутин" При этом есть ряд сценариев, где датас точно не применим и его нужно 100% выключать, значит, это можно сделать через конфиг, называется GC Dynamic Adaptation Mode, можно выключить. +2001.68 2010.04 "Игорь Лабутин" Один из сценариев довольно неочевидный, на первый взгляд, но очевидный, если хорошо подумать, заключается вот в чем. +2010.04 2019.88 "Игорь Лабутин" Это, конечно, здорово, что ваше приложение начнет использовать меньше памяти, это круто, значит, вот это все, но вопрос, есть ли вам куда деть эту лишнюю память, в которую освободиться. +2019.88 2030.64 "Игорь Лабутин" Как мы видели, да, такое все-таки, поддержание небольшого количества памяти в приложении, ну, требует довольно более активной работы garbage collector по сравнению со стандартным режимом. +2030.64 2052.64 "Игорь Лабутин" И поэтому, если вы знаете, что вашу эту лишнюю память вы все равно никуда не используете, потому что, например, вы выделили ее точно под это приложение, и все, и оно никому другому выделено не будет, или у вас просто приложение крутится на выделенном серваке, и тоже эта память никуда больше никому не нужна, то нафиг вам датас не сдался, используйте, как используете сейчас, выключайте датас просто и все. +2052.64 2104.08 "Игорь Лабутин" Дальше, если вам критичен стартап перформанс, то есть, если вам важно, как быстро запускается ваше приложение, датас нужно выключать, потому что датас всегда начинает с хипа в количестве одна штука, независимо от количества ядер, и дальше только если он видит, что одного хипа мало, что нужно побольше, он начинает потихонечку их добавлять, динамически, именно поэтому датас, динамическая адаптация, эти хипы могут создаваться, убиваться, и естественно на стартапе, если вам нужно быстро стартовать и вам сразу нужна новая память, с одним хипом это может занять какое-то время, пока хипов добавится так, что вы будете оптимально работать с нужным количеством памяти, поэтому тоже измеряйте с и без, и принимайте решение нужно или не нужно. +2104.08 2123.80 "Игорь Лабутин" Дальше, если, как мы выяснили, мы позволяем Garbage Collector по дефолту работать в пределах 2%, возможно это повлияет на ваш throughput как-то негативно, тоже измеряйте, если вам вообще никак нельзя терять никаких долей процента в вашем throughput, выключаем датас и не трогаем это. +2123.80 2158.00 "Игорь Лабутин" Ну и также, если ваш паттерн использования приложения в основном работает с сборками 2-го поколения, как правило это происходит, когда вы создаете много больших объектов, например у вас обрабатываются какие-то большие массивы данных, и вы все время создаете объекты, которые попадают в large opposite heap, от датаса толку не будет, потому что датас в основном работает все-таки за счет частоты сборок 0-го и 1-го поколения, если будут частые сборки 2-го поколения, смысла от них не будет, потому что они гораздо более дорогие, тоже скорее всего придется выключить. +2158.00 2188.60 "Игорь Лабутин" В целом у датаса есть некоторое количество настроек, которые можно потюнить, в статье приводятся два примера конкретных прям кастомеров, ну без имен, понятное дело, у которых Маони проводила вот такую настройку, можно посмотреть там с графиками, деталями, выкладками, как там garbage collector, там большие таблички этих, ну суть по виду похожа на перфюшный, я их раньше пока в перфю видел, как это все выводится, наверное сейчас не перфю уже, но неважно. +2188.60 2233.72 "Игорь Лабутин" Смысл в том, что пересказывать это голосом сложно, но можно посмотреть, как чего можно потюнить, и для датаса добавили некоторое количество специальных ивентов, можно через gc.dynamic events получить некоторую информацию о внутренней работе и о тех самых метриках, на основе которых датас принимает решение, куда подвинуть хип, увеличить, уменьшить и так далее, но вряд ли вам это будет нужно как-то в вашей работе, смотреть нужно больше на метрики именно самого приложения, то есть от включения датаса у вас, не знаю, упало использование памяти, но при этом упало и там рпс, который вы можете обрабатывать, ну тут смотрите, что вам важнее, или наоборот, у вас там поднялось почему-то использование памяти, потому что не знаю почему. +2233.72 2244.98 "Игорь Лабутин" С workstation gc переключились на датас, надеясь, что он сможет уменьшить, но не помогло, и все равно сервер gc даже с датас кушает больше, чем с workstation, переключайтесь обратно. +2244.98 2272.84 "Игорь Лабутин" Вот какая-то такая история, то есть я в принципе видел разные истории в интернете, кому-то датас сильно помог, кому-то датас скорее помешал и его выключали, но интересно, что это некоторый, ну да, шаг в сторону того, чтобы сделать крутилку в garbage коллекторе, которая довольно нетривиальна, так скажем, не просто выбор а или б, а такой выбор, к которому нужно подходить осознанно и с метриками, с перформансом вашего продукта. +2272.84 2277.92 "Анатолий Кулаков" Да и мне кажется, будет как обычно, пойдут на stackoverflow и скопируют нужную настройку. +2277.92 2292.48 "Игорь Лабутин" Да вот, ну, это как знаешь, вот про джао так рассказывают, да, если вам нужно запустить джао приложение, найдите значит какую-нибудь волшебную командную строчку из 30 разных флажков и с ней запустите, а вось будет работать. +2292.48 2293.48 "Игорь Лабутин" Ну, по факту не так, да? +2293.48 2294.48 "Игорь Лабутин" Да. +2294.48 2308.76 "Игорь Лабутин" По факту так не работает, нормально они работают и без 30 строчек, в смысле без 30 флажков, у нас вон один флажок и все нормально работает, вот, но да, наверно конечно кто-то будет, кто будет слепо копировать. +2308.76 2321.68 "Игорь Лабутин" К счастью, там не просто command line, там нужно все-таки через конфиг либо через код делать, ну короче, не так это все, ну хотя блин, тоже csproj или ваб-конфиг каком-нибудь указываешь и все, все работает. +2321.68 2324.16 "Анатолий Кулаков" Да, скопируют тебе csproj, какая разница. +2324.16 2325.16 "Игорь Лабутин" Ну да. +2325.16 2341.64 "Игорь Лабутин" Ну в общем, посмотрим, возможно после десятки действительно побольше народу попробуют, поглядим, какие будут отзывы, какие будут корректировки в дотнете, наверняка будут какие-то корректировки в рантайме, хотя они уже год по сути впроди, так что все, что хотели, могли уже и откорректировать. +2342.64 2350.80 "Анатолий Кулаков" Ну и вообще копироваться с ткв-флоп больше не модно, теперь модно спрашивать у разных ии-агентов, поэтому давайте поговорим про ии-агентов. +2350.80 2363.64 "Анатолий Кулаков" У нас тут есть хорошая статичка, которая называется, даже не называется, а сообщает нам о том, что Microsoft выпустила новый фреймворк, который называется Microsoft-агент-фреймворк. +2363.64 2385.16 "Анатолий Кулаков" Знаешь, если вот смотреть на всякие дотнеты и C# и мы с тобой все время жалуемся, что там мало каких-то нововведений, что люди работают, мало оптимизируют, то вот если глянуть на Aspire и на какие-нибудь ии-тулзы, то вот там кажется, что все сотрудники как раз много работают и вообще мне кажется, их туда всех перевели, потому что клепают постоянно какие-нибудь новые библиотеки. +2385.16 2390.68 "Анатолий Кулаков" И вот она как раз, из таких библиотек, фреймворков у нас теперь новый Microsoft-агент-фреймворк. +2390.68 2393.88 "Анатолий Кулаков" Давайте посмотрим, что это за чудо-юдо и с чем его едят. +2393.88 2396.92 "Анатолий Кулаков" Итак, прежде всего, какую проблему-то мы решаем. +2396.92 2405.84 "Анатолий Кулаков" А проблема следующая, что в наше время сейчас всем хочется писать и агенты и писать их довольно сейчас непросто. +2405.84 2422.20 "Анатолий Кулаков" Вам необходимо связывать там несколько моделей в кучу, чтоб вы могли переключаться между разными моделями, устраивать какой-то обмен между этими различными агентами, устраивать их оркестрацию, потом думать как их правильно захостить, замониторить, в общем все это требует нетривиальных усилий. +2422.20 2428.04 "Анатолий Кулаков" Поэтому чтобы создать свой собственного агента, допустим, нужно сильно постараться. +2428.04 2432.12 "Анатолий Кулаков" И Microsoft это не нравится, говорит, что это такое, зачем надо стараться. +2432.12 2437.28 "Анатолий Кулаков" У нас есть, например, Web API, консольные аппликейшены, которые создаются просто в один клик. +2437.28 2442.68 "Анатолий Кулаков" Вот все агенты должны также точно создаваться, просто в один клик, как обычное консольное приложение. +2442.68 2445.60 "Анатолий Кулаков" Ну, сказано, сделано, давайте планировать. +2445.60 2451.36 "Анатолий Кулаков" И напланировали следующую штуку, что у нас теперь есть и две фундаментальные концепции. +2451.36 2456.16 "Анатолий Кулаков" Это агенты и рабочие процессы, workflows. +2456.16 2457.80 "Анатолий Кулаков" Разберемся с ними по одному. +2457.80 2465.92 "Анатолий Кулаков" Итак, агенты - это специальные системы, которые объединяют в себе рассуждения, контекст и инструменты для достижения целей. +2465.92 2471.50 "Анатолий Кулаков" Такое замысловатое определение, которое разделило наши агенты еще на три составляющих. +2471.50 2473.44 "Анатолий Кулаков" Рассуждения. +2473.44 2484.44 "Анатолий Кулаков" Рассуждения - это специальные процессы, которые призваны принимать решения, и обычно сейчас они базируются на LLM-ках. +2484.44 2492.32 "Анатолий Кулаков" Но, в принципе, в будущем их можно заменить на что-то другое, на какую-то другую технику, которая, возможно, придет на смену. +2492.32 2501.80 "Анатолий Кулаков" В общем, поэтому рассуждения - это важная часть, которая как раз-таки должна определять, а что делать со следующим компонентом, с контекстом. +2501.80 2508.16 "Анатолий Кулаков" Контекст - это какие-то внешние данные или какое-то внешнее состояние, которым не обладает сама LLM-ка. +2508.16 2523.56 "Анатолий Кулаков" Например, ваш интерпрайз данных, которые хранятся у вас в компании, или какой-нибудь Wiki, Knowledge Base ваш, или вообще обычная история общения, в которой вы в чате, допустим, общаетесь. +2523.56 2533.20 "Анатолий Кулаков" То есть любые какие-то внешние данные, которые помогают LLM-ке вникнуть в суть контекста и помочь ответить более четко, более близко к запрашиваемой команде. +2533.20 2537.58 "Анатолий Кулаков" И третий компонент, который участвует в агентах - это инструменты. +2537.58 2545.40 "Анатолий Кулаков" Инструменты помогают расширить систему, они сами не принимают никаких решений, они тупо выполняют какую-то задачу. +2545.40 2552.00 "Анатолий Кулаков" При этом инструмент может как выполнять конкретную задачу, так и собирать данные для контекста. +2552.00 2560.76 "Анатолий Кулаков" Допустим, вы можете сделать какие-то запросы в вашу базу данных и собрать там дополнительные сведения для того, чтобы выполнить следующую команду. +2560.76 2566.00 "Анатолий Кулаков" Это можно сделать, например, через модель Context Protocol. +2566.00 2573.26 "Анатолий Кулаков" Так вот, а агенты - это как раз штука, которая объединяет в себе три вот этих сущностей - рассуждения, контекст и инструменты. +2573.26 2576.84 "Анатолий Кулаков" И вот это принято называть в Майкрософте агентами. +2576.84 2582.90 "Анатолий Кулаков" Вы можете в интернете столкнуться с другими определениями, которые противоречат или какие-то частично пересекаются с этим. +2582.90 2585.82 "Анатолий Кулаков" Но у нас агенты - это вот. +2585.82 2590.90 "Анатолий Кулаков" Второй большой компонент глобальный, кроме агентов, это рабочие процессы - Workflows. +2590.90 2606.82 "Анатолий Кулаков" Workflows призваны структурировать какой-то сложный обмен между различными агентами и скоординировать агентов и в том числе людей, может быть, каких-то интерактивных, для того, чтобы достигать каких-то конечных целей. +2606.82 2614.02 "Анатолий Кулаков" То есть, Workflows - это такое объединение всех этих агентов, инструментов во что-то одно, цельное и большое. +2614.02 2619.86 "Анатолий Кулаков" Ну, например, представьте, если вы захотели сделать веб-сайт и в этот веб-сайт хотите добавить какую-то фичу. +2619.86 2629.22 "Анатолий Кулаков" Вам необходимо будет собрать какие-то требования к этой фичи, как-то ее задизайнить, придумать архитектуру, реализовать, протестировать и задеплойить. +2629.22 2637.50 "Анатолий Кулаков" И, в принципе, все эти таски, все эти мелкие шаги, они могут внутри еще разбиваться на кучу подтасков. +2637.50 2640.26 "Анатолий Кулаков" То есть, что такое разработать, реализовать. +2640.26 2645.02 "Анатолий Кулаков" Это пойти в такие-то компоненты, обновить какие-то библиотеки и так далее. +2645.02 2657.34 "Анатолий Кулаков" И плюс, каждый этот шаг, он проразумевает, что внутри могут быть различные фазы, то есть нельзя каким-то образом их объединить во что-то одно и глобальное. +2657.34 2660.34 "Анатолий Кулаков" Также мы через этот workflow можем прыгать туда-сюда. +2660.34 2666.74 "Анатолий Кулаков" Например, если на этапе тестирования у нас найдены баги, то мы должны вернуться на этап реализации и эти баги там пофиксить. +2666.74 2680.34 "Анатолий Кулаков" И вот как раз workflow отвечает за то, чтобы объединить все эти шаги, объединить все эти подтаски в этих шагах и объединить их в различные фазы в каждом из подшагов. +2680.34 2686.34 "Анатолий Кулаков" И он позволяет обеспечить успех полной реализации этой фичи. +2686.34 2697.94 "Анатолий Кулаков" То есть, от планирования до оркестрации, общения между различными агентами и реализовать непосредственно сам паблиш, по паблиш этой фичи на продакшен уже. +2697.94 2705.22 "Анатолий Кулаков" Таким образом, workflow отвечает за какую-то предсказуемую последовательность шагов или предсказуемый результат, а агенты наоборот. +2705.22 2710.22 "Анатолий Кулаков" Агенты пытаются внести какую-то динамическую сумятицу, подстраиваясь под текущие реалии. +2710.22 2720.26 "Анатолий Кулаков" Таким образом, они должны быть умными, автономными и каким-то образом расшатывать процессы в разные стороны для того, чтобы подстраиваться под все, что происходит вокруг. +2720.26 2732.94 "Анатолий Кулаков" И все эти части очень сильно размыты, потому что, например, агенты могут вызывать инструменты, инструменты могут вызывать агенты. +2732.94 2743.16 "Анатолий Кулаков" Workflow вполне может вызывать агентов и инструментов, и даже может другие workflow вызываться из workflow. +2743.16 2747.10 "Анатолий Кулаков" Поэтому каких-то четких делений, кто кем управляет, его не существует. +2747.10 2751.74 "Анатолий Кулаков" Все могут управлять всеми в зависимости от той задачи, которая решается. +2751.74 2754.42 "Анатолий Кулаков" Ну, с теоретической базой мы вроде разобрались. +2754.42 2757.38 "Анатолий Кулаков" Теперь давайте все-таки придем к нашему анонсу. +2757.38 2759.18 "Анатолий Кулаков" Лансирован Microsoft Agent Framework. +2759.18 2765.46 "Анатолий Кулаков" Это на самом деле набор библиотек, который уменьшает сложность для разработки агентов. +2765.46 2778.70 "Анатолий Кулаков" Он подходит вам как для написания обычного чат-ботика элементарного в 10 строчек, так и для оркестрации различных сложных нескольких агентов и объединения их в сложный workflow. +2778.70 2796.06 "Анатолий Кулаков" Этот фреймворк предоставляет набор различных библиотек, которые вам позволяют сделать агентов, позволяют удобно оркестрировать, удобно хостить этих агентов и workflow, и мониторить их, соответственно, работу уже в продакшене. +2796.06 2805.42 "Анатолий Кулаков" Ничего там сильно нового не изобретено, просто Microsoft взял все свои наработки, которые у него сейчас есть по AI и объединил их вот в этот фреймворк. +2805.42 2817.46 "Анатолий Кулаков" В частности, там используется Semantic Kernel для оркестрации, библиотека Autogen, которая нужна для того, чтобы несколько агентов могли общаться друг с другом. +2817.46 2835.42 "Анатолий Кулаков" Microsoft Extension AI, который мы недавно уже обсуждали в нашем подкасте, он необходим для того, чтобы собирать различные блоки, из которых потом создается цельное приложение. +2835.42 2863.12 "Анатолий Кулаков" Для того, чтобы воспользоваться этим фреймворком, вам необходима 9-я или больше, создается это в виде обычных консоль-приложений, но так же просто, как обычная консоль-приложения, просто вам нужно поставить еще один пакетик, который называется Microsoft Agent AI, и дальше мы пишем своего агентика, в принципе, мы много раз уже обсуждали, как писать агенты, там создается iChat Client, подключается моделька, и, в принципе, все, вперед, можно чатиться. +2863.12 2898.10 "Анатолий Кулаков" Дальше фреймворк вносит базовую абстракцию, которая называется AI Agent, это специально унифицированный интерфейс для построения агентов, он там в качестве параметра принимает уже настроенный iChat Client и кучу опций, соответственно, он может работать с любым iChat Client, а iChat Client это хорошая абстракция над любой моделью, то есть, по сути, AI Agent может работать со всеми моделями, которые там существуют, не только какие-то ажуровские, гугловские, опен и айсные, но и локальные там, ламы и прочие модельки. +2898.10 2909.82 "Анатолий Кулаков" Дальше мы, если представить какой-нибудь сценарий из реального мира, допустим, мы хотим написать какую-то статью. +2909.82 2929.58 "Анатолий Кулаков" Соответственно, вам для написания статьи нужен какой-то писатель, который придумает вам содержимое, вам нужен какой-то редактор, который отредактирует ошибки и исправит общее восприятие текста, и вам нужен фактчекер, который проверит, что все факты, которые в статье обозначены, они настоящие. +2929.58 2938.38 "Анатолий Кулаков" И может быть, вам нужен еще и паблишер, который все это непосредственно запаблишит, то есть у вас уже появляется таких вот 3-4 агента, которые будут участвовать в написании статьи. +2938.38 2945.22 "Анатолий Кулаков" И вот с помощью Агент Фреймворка вы легко можете вот такую оркестрацию с помощью Агента реализовать. +2945.22 2957.46 "Анатолий Кулаков" Прежде всего, вам нужно для того, чтобы перейти от уровня агентов, которые вы уже научились там создавать, на уровне Workflow вам нужно установить пакет Microsoft Workflows, тоже новый хороший, и дальше создать Workflow. +2957.46 2966.98 "Анатолий Кулаков" Workflow создается довольно просто, это Workflow Builder, вызывается Build Sequence и передается ему те агенты, которые вы как раз-таки создали. +2966.98 2977.10 "Анатолий Кулаков" Мы можем создать агента Writer, который пишет статью, можем создать агента Editor, который статью проверяет, и засунуть их непосредственно в Sequence вот этого Workflow. +2977.10 2986.02 "Анатолий Кулаков" А дальше этот Workflow может предоставить интерфейс IE-агент, и с ним можно общаться как с обычным агентом, то есть как с обычным чат-клиентом по сути. +2986.02 2992.50 "Анатолий Кулаков" Можете его просить что-то сделать, и он будет в зависимости от настроек, от того контекста, как вы его настроили, выдавать вам результат. +2992.50 3011.66 "Анатолий Кулаков" То есть в нашем случае, если мы попросили Workflow нам сделать результат, он возьмет Writer, Writer нам напишет статью, эта статья по цепочке передастся в Editor, Editor ее отредактирует, проверит, и так дальше можно по цепочке выдать ее до факт-чекера и до паблишера. +3011.66 3022.34 "Анатолий Кулаков" У нас получается такой сложный Workflow, который состоит из кучи мелких агентов, то есть у нас есть Workflow, как я уже сказал, внутри Workflow у нас IE-агенты, и каждый агент настроен чат-клиентом. +3022.34 3039.94 "Анатолий Кулаков" То есть мы такую сложную систему, как за паблишингом статьи, разбили на, декомпозировали на такие маленькие простые блоки, каждый из которых довольно примитивный, настраивается просто, подключается просто, но вместе, когда мы их объединяем в какую-то композицию, в какой-то рабочий процесс, мы можем решать уже сложные какие-то проблемы. +3039.94 3050.02 "Анатолий Кулаков" Я упомянул в коде, что мы построили Sequence Workflow, это не единственный Workflow, который можно строить, кроме Sequence. +3050.02 3056.66 "Анатолий Кулаков" Sequence, понятно, это когда у вас результаты из предыдущего агента передается следующему агенту, и так по цепочке они друг друга вызывают. +3056.66 3061.74 "Анатолий Кулаков" Существует еще Concurrent Workflow, это когда несколько агентов работают параллельно. +3061.74 3081.06 "Анатолий Кулаков" Hand-off Workflow, это когда взаимосвязь между агентами зависит от того, какой контекст у нас получился и какие выходные данные там предыдущий агент выдал, в общем, какое-то динамическое такое связывание в зависимости от того, что у нас на выходах получится. +3081.06 3086.98 "Анатолий Кулаков" И Group Chat, это когда агенты сами с собой договариваются, кто из них кому что отдаст, тоже какое-то там безумие. +3086.98 3092.30 "Анатолий Кулаков" В общем, интересно бы посмотреть, да, как они там договариваются. +3092.30 3096.54 "Анатолий Кулаков" Также фреймворк поддерживает такое понятие как Tool, как инструменты. +3096.54 3112.60 "Анатолий Кулаков" Это настраиваться в Chat Options, в C# инструменты выражены обычным делегатом, то есть вы объявляете какую-то функцию, ее реализовываете и можете специальными атрибутами типа Description настроить ее в описание для того, чтобы агенты лучше поняли, что это за функция. +3112.60 3117.44 "Анатолий Кулаков" Дальше вы ее указываете в Chat Options и все, после этого агент может ее использовать. +3117.44 3125.24 "Анатолий Кулаков" Кроме инструментов поддерживается куча стандартных библиотек протоколов с соглашением, например, как я уже упоминал, модель Context Protocol MCP. +3125.24 3132.42 "Анатолий Кулаков" Он позволяет нам строить, например, MCP сервера и обмениваться данными между различными MCP клиентами по такому протоколу. +3132.42 3145.52 "Анатолий Кулаков" Например, вы можете реализовать MCP сервер для вашей базы данных, для вашей вики, для каких-то системных инструментов, которые каким-то образом будут настраивать или твердить вашу систему и все это подключить к вашему workflow. +3145.52 3149.68 "Анатолий Кулаков" Также используется Agent-to-Agent протокол для коммуникации между агентами. +3149.68 3162.96 "Анатолий Кулаков" OpenAPI интеграции – здесь OpenAPI во всех агентах используется довольно плотно для того, чтобы как раз делать вызовы различных процедур на сторонние сервисы. +3162.96 3171.68 "Анатолий Кулаков" И вы можете вызывать, допустим, какие-то хостед-инструменты, которые непосредственно выполняют команды на операционной системе, на которой вы хоститесь. +3171.68 3172.92 "Анатолий Кулаков" Кстати, про хостинг. +3172.92 3188.40 "Анатолий Кулаков" Для того, чтобы красиво и хорошо настроить хостинг, существует отдельный пакет, называется Microsoft Agent.AI.Hosting, и он позволяет вам получить стандартные какие-то ожидания, настройки, которые мы все любим в наших повседневных проектах. +3188.40 3189.40 "Анатолий Кулаков" Например, конфигурацию. +3189.40 3192.56 "Анатолий Кулаков" У нас есть стандартный .NET-овский способ конфигурации – iConfiguration. +3192.56 3196.60 "Анатолий Кулаков" Вот он тоже сюда прекрасно помещается, подключается. +3196.60 3201.32 "Анатолий Кулаков" Опять же, специальный Dependency Injection расширения для того, чтобы хорошо агента врегистрировать. +3201.32 3205.68 "Анатолий Кулаков" Поддержка middlewary в ASP.NET, которая позволяет вам добавить аутентификацию к вашим агентам. +3205.68 3208.60 "Анатолий Кулаков" И rate-limiting, например. +3208.60 3212.12 "Анатолий Кулаков" В общем, все остатки стандартные инструменты, которые все мы знакомы. +3212.12 3213.84 "Анатолий Кулаков" И это прекрасно. +3213.84 3217.52 "Анатолий Кулаков" Отдельно стоит выделить это интеграция с OpenTelemetry. +3217.52 3225.20 "Анатолий Кулаков" OpenTelemetry захватывает такие прикольные вещи, как flow-общение между агентами. +3225.20 3231.16 "Анатолий Кулаков" То есть она сможет вам визуализировать, какие сообщения ходят между какими агентами. +3231.16 3234.84 "Анатолий Кулаков" Дальше можно посмотреть на статистику использования моделей. +3234.84 3242.04 "Анатолий Кулаков" Сколько токенов используется, какая модель была выбрана для решения той или иной задачи и сколько это стоит. +3242.04 3246.12 "Анатолий Кулаков" Тоже это интересно, прозрачные метрики, которые не всегда очевидны. +3246.12 3252.48 "Анатолий Кулаков" А видеть их хочется всегда, потому что именно они выливаются напрямую в ваши деньги и в ваш бюджет. +3252.48 3259.24 "Анатолий Кулаков" И performance-метрики, то есть они мониторят за сколько агент вам ответил, какой throw-put у каждого агента. +3259.24 3260.52 "Анатолий Кулаков" В общем, все это тоже очень интересно. +3260.52 3266.36 "Анатолий Кулаков" Ну и, естественно, трекинг всяких ошибок, которые позволяют быстро диагностировать, что там у вас происходит. +3266.36 3274.24 "Анатолий Кулаков" Все это в OpenTelemetry, то есть легко экспортируется в Grafana, в Prometheus, куда угодно и, естественно, в Aspire. +3274.24 3279.04 "Анатолий Кулаков" В Aspire тоже появляются красивые графики, красивые distributed трейсинги, в общем, логи. +3279.04 3281.56 "Анатолий Кулаков" Это там выглядит довольно прекрасно. +3281.56 3289.76 "Анатолий Кулаков" А также этот фреймворк наш прекрасный, он хорошо интегрирован с Microsoft Extension AI Evaluations. +3289.76 3298.04 "Анатолий Кулаков" Это еще одна библиотека для аишки, которая призвана обеспечить правильное и красивое тестирование. +3298.04 3308.00 "Анатолий Кулаков" В общем, как тестировать всякие аишные агенты, мне раньше вообще в голову не приходило, потому что там же абсолютно все недетерминированно. +3308.00 3321.96 "Анатолий Кулаков" Оказывается, есть специальная библиотека, которая позволяет вам настроить автоматизированное тестирование, тестирование качества, регрессионное тестирование, которое позволит не выпустить на продакшн какой-то workflow, какой-то рабочий процесс, если вдруг он как-то сломался или неправильно работает. +3321.96 3325.68 "Анатолий Кулаков" В общем, для всего этого есть интересные подходы, интересные инструменты. +3325.68 3333.56 "Анатолий Кулаков" Я открыл ее, хотел вам немножко про нее рассказать, но там столько интересной математики и статистики, что, наверное, стоит как бы в отдельную тему вынести. +3333.56 3340.08 "Анатолий Кулаков" В общем, библиотека для тестирования есть, и она такая довольно неочевидная и довольно прикольная. +3340.08 3355.16 "Анатолий Кулаков" Ну что ж, вот такой Microsoft Agent Framework новый нас ждет, если вдруг кто-то из вас разрабатывает какие-то чат-клиенты, MCP-сервера, интеграции, тулзы, то, наверное, ему в помощь такой прекрасный инструмент. +3355.16 3378.16 "Игорь Лабутин" С таким фреймворком мне только непонятно, ну как, мне тоже непонятно, всегда есть опасение, что все-таки фреймворк, ну, обычно, да, называют некоторое, ну, в каком-то смысле навязывание, да, и попытку загнать тебя в некоторый заранее придуманный процесс, да, то есть заранее придуманный шаблон. +3378.16 3395.04 "Игорь Лабутин" Насколько вот интересно он окажется, ну, что ли, подстраиваемым под нужды пользователей, не получится ли так, что с ним как-то неудобно выражаются какие-то ваши воркфлоу или какие-то ваши задачи, которые вам нужно решить для или с помощью ИИ? +3395.04 3399.08 "Анатолий Кулаков" Видишь, надо разбирать конкретные примеры, потому что не очень понятно. +3399.08 3402.08 "Анатолий Кулаков" Помнишь, есть, был такой фреймворк, как он назывался Workflow Foundation? +3402.08 3404.48 "Анатолий Кулаков" Да, конечно, Windows Workflow Foundation. +3404.48 3407.96 "Анатолий Кулаков" Да-да-да, попрошу вас, Windows Workflow Foundation. +3407.96 3424.40 "Анатолий Кулаков" Ну, так вот, довольно сильно на него похож, он не такой как бы громоздкий и страшный, пока более такой гибкий, лайтовый, хипстеровский, но смысл тот же самый, вот есть какие-то блоки, ты их настраиваешь, соединяешь в правильные цепочки и запускаешь, и оно как-то работает. +3424.40 3429.84 "Анатолий Кулаков" Подзагонял ли тебе в рамке Windows Workflow Foundation какие-то, которые ты не мог с помощью него реализовать? +3429.84 3448.96 "Игорь Лабутин" Я пользовался WWF только для каких-то очень простых штук, там хватало, но тут возникает вопрос, не будет ли проще эти простые штуки на чем-нибудь тоже, ну, непонятно, в общем, да, мне не хватает здесь практики, чтобы так сходу оценить, насколько эта штука полезна, поглядим. +3448.96 3455.04 "Игорь Лабутин" Будут еще статьи про использование этого фреймворка, значит, узнаем, что его используют. +3455.04 3458.76 "Игорь Лабутин" Не будет статьи, значит, никто не использует, у нас все, простая метрика. +3458.76 3463.60 "Анатолий Кулаков" Да-да, если новости появляются, мы про них рассказываем, фреймворк жив. +3463.60 3473.20 "Анатолий Кулаков" Здесь тоже, видишь, получаются такие вот маленькие композитные блоки, которые сами по себе довольно простые, поэтому их легко описывать, легко понимать, а потом из них чего-то собирается. +3473.20 3485.48 "Анатолий Кулаков" Просто в отличие от Workflow Foundation, где было все довольно детерминистично и предсказуемо, вот здесь, в моделях, оно с каждым запуском может выдать тебе разный результат. +3485.48 3491.80 "Анатолий Кулаков" Именно поэтому меня как бы очень заинтересовал именно фреймворк тестирования, как всю эту штуку будут тестировать. +3491.80 3492.80 "Анатолий Кулаков" Ну посмотрим, посмотрим, да. +3492.80 3493.80 "Игорь Лабутин" Посмотрим, да. +3493.80 3494.80 "Игорь Лабутин" Будет интересно. +3494.80 3495.80 "Игорь Лабутин" Будем действительно ждать статей. +3495.80 3499.80 "Игорь Лабутин" Это, конечно, с одной стороны ирония, с другой стороны действительно так. +3499.80 3502.80 "Игорь Лабутин" Если статей по какой-то технологии нет, значит, может, ей никто не пользуется. +3502.80 3507.80 "Игорь Лабутин" Когда мы последний раз Maui обозревали в нашем подкасте? +3507.80 3508.80 "Игорь Лабутин" Очень давно. +3508.80 3512.80 "Игорь Лабутин" Наверное, там какие-нибудь еще performance improvements произошли с тех пор. +3512.80 3514.80 "Игорь Лабутин" Ладно, давай пойдем дальше. +3514.80 3556.80 "Игорь Лабутин" Мы сегодня прям богаты на статьи про internals, потому что у нас есть статья, она на самом деле не статья, это, хотя нет, почему, это статья на ресурсе learn.microsoft.com, то есть в официальной документации Microsoft, и если не знать, то может показаться, что это просто очередная статья, но если знать правильные источники, то не бесполезно будет узнать, что автор этой статьи тот самый Егор Богатов, это разработчик из команды GTA, который написал большую развестию статью на тему того, как правильно программировать в unsafe, то есть с использованием unsafe кода. +3556.80 3667.80 "Игорь Лабутин" Понятно, что большинству разработчиков, наверное, это не нужно, но если вы испытываете какие-то performance проблемы или вам нужно какой-нибудь нативный интероп с какой-нибудь нативной библиотекой или еще что-нибудь в таком духе, там арифметика указателей, то, вероятно, эту статью точно хотелось, в смысле не хотелось бы рекомендуется прочитать, потому что там собран опыт примерно 26 пунктов, ну в смысле не примерно, а точно 26 пунктов, вероятно, на основе расследования каких-то проблем, которые возникали у заказчиков, куда команда dotnet подключалась и что-то выясняла, так что, вероятно, этот опыт все-таки не просто так из воздуха придуман, а мы попробуем, ну не погружаясь сильно уже в детали, потому что тут есть большое количество примеров кода, статья написана в стиле, значит, как обычно для каждого пункта написано do и don't, что рекомендуется делать и что крайне не рекомендуется делать, по некоторым попробуем немножко пробежаться, но сначала сообразим, а что вообще такое unsafe code, зачем это нужно и почему с ним столько проблем. В целом C# и dotnet, да, это язык платформы безопасный в точке зрения memory, то есть если вы пишете на стандартном C# и не используете каких-то, ну скажем так, того самого unsafe кода, то есть это есть ряд ключевых слов, которые к этому приводят, то есть там тот же fixed, да, и использование указателей, либо есть у нас специальный класс unsafe, в котором есть набор методов, которые вы можете использовать, вот до тех пор, пока вы туда не пошли, у вас все достаточно safe, безопасно, то есть dotnet гарантирует, что несмотря на всякие сборщики мусора, которые могут, напомню, перемещать объекты, еще что-то, все ваши ссылки на ваши объекты будут живы, все будет хорошо, причем даже будут живы те ссылки, которые вы можете получить, например, на середину массива. +3667.80 3796.80 "Игорь Лабутин" Напомню, у нас сейчас есть такая возможность, с помощью там каких-нибудь рефов, да, вы можете написать там ref int a = ray от 5, да, и это будет ссылка на пятый элемент массива, так вот эта ссылка, даже если массив подвинут, в процессе сборки мусора ссылка тоже будет подвинута, все будет корректно, все будет хорошо, но стоит вам вступить в область unsafe, а то все становится не очень здорово. Значит, и проблема с unsafe кодом заключается в том, что он очень плохо взаимодействует с garbage collector. Garbage collector - это такая штука, которая собирает память, и для того, чтобы делать это эффективно, у нее есть ряд некоторых особенностей работы, которые нужно знать. Во-первых, garbage collector может прервать ваш код, ну, в общем, предполагайте, что он может это сделать в любом месте кода, после любой инструкции, там, в середине ифа, условно говоря, в середине выполнения любой функции, то есть не обязательно это делать по границам методов или еще где-то, может произойти где угодно. Garbage collector может двигать объекты как угодно, где угодно, даже в large object heap'е есть специальные режимы, когда garbage collector, можно его позвать и сказать закомпактив мне large object heap, тогда даже там объекты будут двигаться и нельзя рассчитывать на то, что там они не подвинуты. И garbage collector знает абсолютно точно, если мешать ему работать, когда какой объект жив, когда какой объект не жив. У нас используется, соответственно, garbage collector, который основан на обходе дерева ссылок, то есть есть ряд объектов, которые называются рутами, это, как правило, stack, это, как правило, статические переменные, и от них можно проследить, жив ли каждый конкретный объект. И если мы не мешаем gc работать как он работает, то все будет хорошо, но как только мы начинаем работать с нативными указателями, еще что-нибудь, может пойти что-то не так, особенно возникают проблемы, когда объект был в gc, но он потерялся, то есть gc считает, что объект есть, на него, например, есть какие-то ссылки, но по факту в этом месте объекта уже нет, или там лежит что-то другое, и понятно, что в этом случае логика обхода ссылок может сломаться и может пройти все что угодно и не по плану. +3796.80 3821.80 "Игорь Лабутин" И основная проблема со всеми этими багами в том, что они очень трудно уловимы, в смысле, что они практически не повторяемы в контролируемом окружении, они то есть, то нет, потому что они зависят от некоторых динамических характеристик того, как работает garbage collector, а он же смотрит и на размер памяти, и на то, как там у вас внутри вашего приложения изменяются эти самые памяти, как часто происходят сборки мусора, сколько при этом объектов остается живо, сколько не живо. +3821.80 3832.80 "Игорь Лабутин" Все эти метрики влияют на то, как часто вызывается garbage collector, и поэтому предсказать или стабильно повторить проблемы с багами вот такими, которые вокруг unsafe кода, довольно сложно. +3832.80 3840.80 "Игорь Лабутин" Особенно, если это доступ к какой-нибудь другой памяти, и мы еще и зависим от того, что в этой ячейке памяти будет располагаться. +3840.80 3841.80 "Игорь Лабутин" Вот. +3841.80 3847.80 "Игорь Лабутин" Давайте немножко попробуем пробежаться по различным кусочкам. +3847.80 3849.80 "Игорь Лабутин" Я так, выборочно про разные расскажу. +3849.80 3853.80 "Игорь Лабутин" Ну, понятно, что managed указатели. +3853.80 3860.80 "Игорь Лабутин" Тут все понятно, все легко и так далее. +3860.80 3883.80 "Игорь Лабутин" Как только вы вызываете unsafe.spointer, все как бы надо быть очень внимательным, потому что вы получили pointer, про который gc знать не знает, gc может объект, если вы уберете обычную ссылку на этот объект, gc его соберет, а pointer у вас останется жить и будет показывать в какое-то рандомное место, возможно, там будет тоже новый объект в этом месте. +3883.80 3892.80 "Игорь Лабутин" Короче, не надо так делать, если вам что-то очень нужно использовать gc handle, fixed scope, в общем, стандартные не unsafe кусочки. +3892.80 3907.80 "Игорь Лабутин" Понятно, что с fixed scope важно знать, нельзя все то, что вы зафиксили, а напомню, fixed как using, то есть в рамках этого fixed блока у вас указатель гарантирован, а gc гарантированно не подвинет тот объект, на который вы зафиксили ссылку. +3907.80 3917.80 "Игорь Лабутин" Вот не надо этот указатель передавать наружу в fixed блока, технически это сделать можете, но так делать не надо, конечно же. +3917.80 3926.80 "Игорь Лабутин" Ну, естественно, всякие рекомендации типа не надо завязываться на какую-то внутреннюю реализацию runtime и библиотек, это все понятно. +3926.80 3928.80 "Игорь Лабутин" А вот дальше интересный момент. +3928.80 3941.80 "Игорь Лабутин" Как я сказал, пока вы работаете с managed указателями, у вас все хорошо, но на самом деле может быть и, скажем так, не очень хорошо именно с managed указателями. +3941.80 3957.80 "Игорь Лабутин" То есть если вы делаете, например, какой-нибудь fixed блок с unmanaged указателем, то есть вы получили unmanaged указатель через fixed блок, делаете с ним какую-то арифметику, и только потом, после какой-нибудь хитрой арифметики вы его разаминовываете и все с ним будет хорошо, то все замечательно. +3957.80 3971.80 "Игорь Лабутин" А вот если вы решаете, нет, fixed блок это не круто, я больше буду делать все через ref указатели, то есть это managed указатели, с помощью метода unsave add можно делать арифметику на указателях. +3971.80 4034.80 "Игорь Лабутин" Так вот, несмотря на то, что, казалось бы, вы не используете конструкции типа int*, вот те самые плюсовые указатели, вы остаетесь в синтексе c#, ref, int, вот это все, но как только вы сделали указательную арифметику на таком unmanaged указателе, это будет вообще непонятно что, потому что может объект подвинут между этими вызовами двумя, unsave add может быть, gc как-то еще что-то решит куда-то переместить, собрать мусор и так далее, и этот указатель может стать совершенно невалидным, несмотря на то, что вы его вроде как получили валидным c# способом, поэтому лучше, если вам нужна арифметика указателей, используем fixed блок и обязательно работаем с запиненными объектами. Так, что у нас еще интересно? Да, вот, object lifetime, мне кажется, это даже на собеседовании иногда спрашивают такие немножко дурацкие вопросы, но тем не менее, это все, что касается finalizers, gc.keepalive и прочих вызовов. +4034.80 4085.80 "Игорь Лабутин" Ну, в общем, совет тут такой, не надейтесь, что вы четко понимаете, сколько будет жить объект, то есть, ну, это самая вопроса собеседования, что this всегда живой, он всегда указывает на разумный объект, даже если вы внутри instance метода, this к концу этого метода может стать невалидным и указывать непонятно куда. Ну, то есть, конечно, если вы пишете managed код, то там все будет хорошо, но если вы как-то this в unmanaged перевели и ждете, что до конца жизни объекта, до конца хотя бы исполнения методом будет правильный, нет, не надо. Если все надо, то как бы используем gc.keepalive, он нормально гарантированно будет удостоверяться, что этот объект жив до того места, где вызван gc.keepalive, после него тоже непонятно. +4085.80 4120.80 "Игорь Лабутин" Так, ну, unsaved bound checks, это все неинтересно, unaligned memory access, это все уже совсем такое специфичное, null manager, null manager pointers, мы все боремся за null safety, но, тем не менее, у нас есть возможность создать null-овый managed pointer, то есть мы можем написать ref object obj, присвоить ref unsaved.nullref от object, и вы получите ref, который на самом деле null был, точнее не null, а null. +4120.80 4140.80 "Игорь Лабутин" В общем, не надо, рекомендация одна, не надо так делать, если вам надо, используйте какой-нибудь null object pattern, типа как-то, у нас re-empty есть или что-то в таком духе, list-empty, потому что, в общем, в общем не надо, тут даже нет ни одного do, в рекомендациях одни сплошные don't. +4140.80 4154.80 "Игорь Лабутин" Stack-a-lock, stack-a-lock это, наверное, штука, которую, может быть, вы встретите, даже если вы не сильно увлекаетесь unsaved, может казаться, ну, мне там нужен маленький массивчик на 3-4 элемента, я его за stack-a-lock, чтобы, значит, в heap не лезть. +4154.80 4202.80 "Игорь Лабутин" Здесь несколько рекомендаций, рекомендация первая, всегда результат stack-a-lock запихивайте в span, потому что это, во-первых, будет гарантировать вам проверки выхода за границы массивов, во-вторых, будет гарантировано, убережет вас от того, что эта ссылка куда-то утечет, непонятно куда, вот, и в целом, вообще говоря, можно даже не пытаться что-то пооптимизировать на stack-a-lock, прежде чем вы не доказали, что это действительно надо, потому что, напоминаю, современный JIT старается понимать, что для небольших массивов их можно сразу локировать на стеке, и, может быть, он сам это за вас сделает, если надо, вот, если сможет точнее. +4202.80 4234.80 "Игорь Лабутин" Понятное дело, не надо дизайнить API в стиле, значит, в C-стиле, когда вы придаёте указатель длину, лучше всякие спаны memory использовать, или даже массивы, тоже одни сплошные don't, не надо мутировать строки in place, это можно делать, в принципе, есть такая возможность в C#, но делать лучше так не надо, потому что всё-таки довольно большая часть C# идут на это, предполагая, что строки не мутабельны, и если вы это начнёте делать, может быть там всё что угодно. +4234.80 4267.80 "Игорь Лабутин" Ну и в конце, на самом деле, таких вот прям детальных рекомендаций здесь 21, а остальные они про такие общие рекомендации, то есть типа, если вы используете interop, то, если вам нужно использовать interop, то есть подавать какую-нибудь библиотечку, лучше всего использовать какие-нибудь генераторы контрактов, которые сгенерируют вам правильную C#-обёртку, и вам не нужно будет упражняться в правильной магии, весь маршалинг будет производиться с помощью вот этих вот сгенерированных обёрток, это гораздо лучше. +4267.80 4278.80 "Игорь Лабутин" Memory safety и thread safety — это абсолютно несвязные вещи, то есть ваш код может быть memory safe, но абсолютно нет thread safe, и наоборот, он может быть абсолютно thread safe, но может быть не memory safe. +4278.80 4285.80 "Игорь Лабутин" Помните про это и не путайте эти два понятия, нужно проверять и то, и другое. +4285.80 4310.80 "Игорь Лабутин" Если вы впрямую используете SIMD, векторизацию и так далее, нужно ещё более внимательно смотреть, потому что там есть довольно много, ну, довольно сложных требований с точки зрения гарантии атомарности, с точки зрения невыровненности и bound-чеков, которых в некоторых опишках просто нет, и поэтому надо на это смотреть внимательно. +4310.80 4342.80 "Игорь Лабутин" И последний совет про warning компилятора, про то, что в целом, вообще говоря, C#-компилятор, как только он касается unsafe, далеко не всегда способен нормально показать warning, поэтому если warning показан, если вы видите warning про то, что вот тут, короче, что-то кажется не то, если это хоть как-то относится к unsafe-коду, точно бегите и пытайтесь найти точную причину, потому что, скорее всего, это значит, что там есть ошибка, и она где-нибудь вам дострельнёт в гораздо менее контролируемом окружении, нежели чем warning компилятора. +4342.80 4353.80 "Игорь Лабутин" Но даже если warning-ов нет, и ваш код компилируется без ошибок и без warning-ов, не надейтесь, что он правильный, если там есть unsafe, скорее всего, он неправильный, и лучше бы переписать это без unsafe-а. +4353.80 4355.80 "Игорь Лабутин" Вот такая вот история. +4355.80 4368.80 "Игорь Лабутин" Я бы рекомендовал почитать статью, если вы используете unsafe, хотя бы просто чтобы освежить в памяти, что можно, что нельзя делать, и какие конструкции сейчас в современном дотнете рекомендуются для тех или иных операций. +4368.80 4371.80 "Анатолий Кулаков" Интересно, на собеседованиях вообще про unsafe спрашивают? +4371.80 4373.80 "Игорь Лабутин" Ну, надеюсь, что нет. +4373.80 4384.80 "Игорь Лабутин" Вот, только если конкретно, ну, я бы спрашивал, если бы мне это было нужно в работе, ну, в смысле, если я понимал, что у нас в проекте unsafe зачем-то используется, ну, может быть, я бы спрашивал. +4384.80 4390.80 "Игорь Лабутин" Хотя, хотя, предполагаю, что, может быть, этому проще научить, если уж есть такая нужда внутри проекта. +4390.80 4395.80 "Анатолий Кулаков" Ну, смотри, про garbage collector всех спрашивают, а в принципе в работе он вообще никому не нужен. +4395.80 4400.80 "Игорь Лабутин" Вот теперь будет нужен, смотри, как конфигурить датас на нашем продукте. +4400.80 4403.80 "Игорь Лабутин" Если только, да, если только так. +4403.80 4413.80 "Игорь Лабутин" Вот какие преимущества и недостатки, там, garbage collector в 10 версии по сравнению с 8 версией, да, о чём регион отличается от сегментов, зачем знать не надо, не знаю, ну, в общем. +4413.80 4419.80 "Игорь Лабутин" Ну, понятно, что всегда есть какие-то вопросы, которые задают просто потому, что задают. +4419.80 4427.80 "Игорь Лабутин" В целом, ну, я уже когда-то говорил, да, это немножко off-topic, что в целом задавать-то можно любые вопросы, смотря просто, что вы ждёте в ответ. +4427.80 4434.80 "Игорь Лабутин" Если вы ждёте формальный ответ с принципом правильно-неправильно, это не надо так делать. +4434.80 4439.80 "Игорь Лабутин" А если затравка-то какой-нибудь беседы, ну, почему нет? +4439.80 4440.80 "Анатолий Кулаков" Почему нет? +4440.80 4444.80 "Анатолий Кулаков" Ну, да, вот там много-много пунктов для затравки. +4444.80 4445.80 "Анатолий Кулаков" Пожалуйста. +4445.80 4447.80 "Игорь Лабутин" Это да, это да. +4447.80 4453.80 "Игорь Лабутин" На этом у нас, наверное, основная серия статей закончилась на сегодня, но у нас есть немножечко кратко о разном. +4453.80 4455.80 "Анатолий Кулаков" Да, давай пробежимся по нескольким пунктам. +4455.80 4457.80 "Анатолий Кулаков" Я здесь добавил пару выпусков. +4457.80 4461.80 "Анатолий Кулаков" Во-первых, хочется вам порекомендовать подлодку 4.2.6. +4461.80 4464.80 "Анатолий Кулаков" Тема Мнемоника «Запомнить всё». +4464.80 4465.80 "Анатолий Кулаков" Довольно интересный выпуск. +4465.80 4474.80 "Анатолий Кулаков" В гости приходил чемпион по запоминаниям всего и рассказывал, в принципе, как вообще развить память, какие для этого есть техники, есть школы. +4474.80 4477.80 "Анатолий Кулаков" Приводил примеры интересных ассоциативных техник. +4477.80 4482.80 "Анатолий Кулаков" И вообще, зачем нужно в повседневной жизни такое странное увлечение, как запоминание? +4482.80 4487.80 "Анатолий Кулаков" Оказывается, это не только про память, это ещё и про креативность, про насмотренность, про любознательность. +4487.80 4490.80 "Анатолий Кулаков" В общем, всё это в выпуске раскрывается. +4490.80 4499.80 "Анатолий Кулаков" И довольно познавательный выпуск, опять же, если вы просто интересуетесь окружающим миром, какие люди существуют, что они делают и зачем они это делают. +4499.80 4502.80 "Анатолий Кулаков" В общем, очень интересно. +4502.80 4508.80 "Анатолий Кулаков" А дальше в DotNet Rocks приходил Дастин Кэмпбелл и рассказывал про C# 14. +4508.80 4512.80 "Анатолий Кулаков" Дастин – это Principal Software Architect в DotNet Tooling. +4512.80 4517.80 "Анатолий Кулаков" Наверное, для C# 14 он ближе всех из нас. +4517.80 4537.80 "Анатолий Кулаков" Ничего такого откровенно нового не рассказал, но если вдруг вам интересно, как там работает вся вот эта команда, вся кухня, что ожидается в C# 14, как вообще выбираются фичи для того, чтобы войти в мажорный релиз, как делаются такие длинноиграющие фичи, которые несколько лет разрабатываются. +4537.80 4544.80 "Анатолий Кулаков" Он рассказывал, например, про Extension Members, как они дизайнились, почему их не внедрили сразу, какие проблемы при внедрении сейчас. +4544.80 4551.80 "Анатолий Кулаков" В общем, те темы, которые мы, в принципе, покрываем хорошо в нашем подкасте, там уже можно посмотреть от первого источника. +4551.80 4555.80 "Анатолий Кулаков" Поэтому, если вам интересно, то можно послушать. +4555.80 4560.80 "Игорь Лабутин" Мне кажется, я помню этот выпуск, я его уже довольно давно слушал, но да, выпуски прикольные. +4560.80 4562.80 "Игорь Лабутин" Оба на самом деле. +4562.80 4565.80 "Игорь Лабутин" И довольно давно это про мневотехнику. +4565.80 4568.80 "Игорь Лабутин" Наверное, немножко иронично говорить "кажется". +4568.80 4571.80 "Игорь Лабутин" Не помню, когда я слушал про выпуск про мневотехнику. +4571.80 4574.80 "Игорь Лабутин" Да, кажется, я забыл, когда слышал выпуск про память. +4574.80 4577.80 "Игорь Лабутин" Да, ну забавно, да. +4577.80 4582.80 "Игорь Лабутин" И с моей стороны я хотел бы рассказать, точнее, упомянуть про такую штуку. +4582.80 4602.80 "Игорь Лабутин" Мы, наверное, не знаю, полгода назад было или около того, рассказывали про новую идею от Microsoft, про то, что давайте запилим мега, больше, наверное, даже чем полгода назад, мега, короче, библиотеку, не знаю, фреймворк, еще что-нибудь внутри S/Pennet Core для поддержки различных event-based, так скажем, коммуникаций. +4602.80 4605.80 "Игорь Лабутин" У них это называлось Eventing Framework. +4605.80 4614.80 "Игорь Лабутин" И мы обсуждали, что там было большое количество обсуждений, насколько это помрет от этого какой-нибудь mass transit или что-нибудь в таком духе, проще библиотеки. +4614.80 4619.80 "Игорь Лабутин" В общем, обсуждений было много, mass transit с тех пор стал платным, ну, по-моему, для всех, да? +4619.80 4622.80 "Игорь Лабутин" Что-то там были какие-то изменения в лицензии? +4622.80 4624.80 "Анатолий Кулаков" В принципе, для всех. +4624.80 4642.80 "Игорь Лабутин" Да, в общем, короче, были там изменения лицензии, вот это все, и в итоге вот недавно Microsoft написала в этой иши, что типа, не, мы что-то подумали, посмотрели на реакцию комьюнити, решили, что не будем это все делать, не будет Eventing Framework от Microsoft, иши закрыта, короче, может быть, когда-нибудь, но не сейчас, точка. +4642.80 4650.80 "Игорь Лабутин" Вот, короче, не будет у нас мега Eventing Framework от Microsoft, продолжаем жить на mass transit или чем вы там еще пользуетесь. +4650.80 4668.80 "Анатолий Кулаков" Ну, это довольно-таки грустно, в общем, с моей стороны, и странно, как они смотрели на реакции комьюнити, потому что комьюнити полностью поддержала их Eventing Framework, то есть там почти в 10 раз больше желающих того, чтобы они этот Eventing Framework сделали, чем тех, кто хочет, чтобы они его не сделали. +4668.80 4680.80 "Анатолий Кулаков" Ну и плюс на эту новость тоже заагрелись таким образом, что людям не понравилось, что они отказались от идеи Eventing Framework, как раз больше проголосовало за то, чтобы он был, поэтому странно они слушают. +4680.80 4699.80 "Игорь Лабутин" Ну, это все-таки аудитория GitHub'а, то есть они же все-таки есть еще какие-нибудь там First Party Customers, в общем, много кто где, они опрашивают, так что все-таки аудитория GitHub'а, наверное, ну, она, конечно, репрезентативна, с одной стороны, это программисты, с другой стороны, может быть, и не прям идеально. +4699.80 4701.80 "Игорь Лабутин" Ну, поглядим, поглядим. +4701.80 4715.80 "Анатолий Кулаков" Ну, как раз First Party Customers здесь, мне кажется, комментарии, которые были, они вполне отражают First Party Customers, которые говорят, чуваки, типа, я люблю Microsoft за то, что у них вообще есть фреймворки абсолютно на все свои. +4715.80 4725.80 "Анатолий Кулаков" Эти фреймворки как бы под открытыми лицензиями, они поддерживаются большой компанией, у них, ну, и крутецкое на рынке, на рынке самое лучшее качество, как бы вот за это мы любим .NET. +4725.80 4735.80 "Анатолий Кулаков" А вот посмотрите на тех, кого вы не хотели убивать, то же самое Mastranzit, End Service Bus платный, Mastranzit платный, еще там кто-то начинает как бы коммерческую бабки грести. +4735.80 4742.80 "Анатолий Кулаков" Вот с такими фреймворками мы связываться не хотим, нам нужна вот хорошая микрософтовская open-source. +4742.80 4753.80 "Анатолий Кулаков" И вы вот отказались от хорошего микрософтовского open-source фреймворка в пользу непонятно кого, тех, кто жаловался, что им там не дадали какую-то коммерческую лицензию. +4753.80 4754.80 "Игорь Лабутин" В общем, все это грустно. +4754.80 4768.80 "Игорь Лабутин" С одной стороны, да, с другой стороны, ты так, конечно, говоришь, что, типа, отказались от хорошего микрософтовского фреймворка, как правильно написали в одном из, короче, комментов к этой ишли после того, как там Microsoft написал, что мы не будем делать Eventing Framework. +4768.80 4774.80 "Игорь Лабутин" Но написал, ну, может быть, наконец-таки найдутся ресурсы по фиксии System Command Line. +4774.80 4782.80 "Игорь Лабутин" Поэтому про хороший фреймворк, вот System Command Line от Microsoft, да, это, типа, главный фреймворк, который для парсинга Command Line ругают все. +4782.80 4785.80 "Игорь Лабутин" Вот, поэтому, что бы там получилось, тоже непонятно. +4785.80 4789.80 "Игорь Лабутин" Может быть, получился бы второй System Command Line и пользоваться было бы невозможно. +4789.80 4795.80 "Анатолий Кулаков" Я думаю, не найдут, видишь, у них все ресурсы уходят на Espire, и поэтому не найдут. +4795.80 4796.80 "Анатолий Кулаков" Не найдут, да. +4796.80 4799.80 "Игорь Лабутин" В общем, вот такие дела. +4799.80 4801.80 "Игорь Лабутин" Это был 124-й выпуск. +4801.80 4807.80 "Игорь Лабутин" Мы обсудили Espire 9.5, то, что вышло, и какие-то небольшие апдейты к Roadmap. +4807.80 4817.80 "Игорь Лабутин" Мы обсудили Trusted Publishing для NuGet, так, что бы у вас были не ключи, которые вы можете закомитить в GitHub случайно, а короткоживущие ключи. +4817.80 4829.80 "Игорь Лабутин" Мы обсудили Dotnet 10 Garbage Collector, так, что там теперь уже в LTS будет дата, с которой, ну, с девятки работает, и которой можно и нужно настраивать, и иногда выключать, если вам он мешает. +4829.80 4835.80 "Игорь Лабутин" Обсудили Microsoft Agent Framework, новый фреймворк от Microsoft для всякого, и около него. +4835.80 4842.80 "Игорь Лабутин" И Unsafe Code Best Practices, как писать unsafe-ный код, если вам это зачем-то надо, но лучше бы вам это было не надо. +4842.80 4844.80 "Игорь Лабутин" Ну, и на этом на сегодня все. +4844.80 4846.80 "Анатолий Кулаков" Да, всем до новых встреч. +4846.80 4852.80 "Анатолий Кулаков" Обязательно на Shorty репостите, но никто нам и лайки не ставил на всяких площадках для прослушивания подкастов. +4852.80 4856.80 "Анатолий Кулаков" В общем, это все надо делать регулярно, поэтому не забывайте. +4856.80 4861.80 "Анатолий Кулаков" Особенно распространяйте нас, рекомендуйте друзьям, которые вдруг почему-то не слышали про подкаст. +4861.80 4863.80 "Анатолий Кулаков" Может, им тоже зайдет. +4863.80 4865.80 "Анатолий Кулаков" Ну, и до новых встреч. Пока. +4865.80 4867.80 "Игорь Лабутин" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-125.txt b/input/Radio/Transcriptions/RadioDotNet-125.txt new file mode 100644 index 0000000..00c1450 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-125.txt @@ -0,0 +1,645 @@ +0.00 11.02 "Анатолий Кулаков" Приветствую, дорогие слушатели, в эфире Радио.нет выпуск номер 125. +11.02 14.34 "Анатолий Кулаков" В студию постоянный ведущий Анатолий Кулаков и Игорь +14.34 15.34 "Игорь Лабутин" Лабутин. +15.34 16.34 "Анатолий Кулаков" Всем привет. +16.34 21.66 "Анатолий Кулаков" А за нашими спинами доблестные помогаторы, среди которых, кстати, можете оказаться и вы. +21.66 46.02 "Анатолий Кулаков" Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Владислав, Шевченко Антон, Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев, Юрий Лодейкин, Катков Михаил, Михаил Королев. +46.02 48.40 "Анатолий Кулаков" Спасибо всем друзьям, кто нас поддерживает. +48.40 54.54 "Анатолий Кулаков" Не забывайте, что нас еще поддерживает куча народу, просто они пожелали остаться неизвестными. +54.54 60.66 "Анатолий Кулаков" Поэтому заходите еще, присоединяйтесь к доблестной толпе наших помогаторов, за что мы вам будем очень-очень благодарны. +60.66 68.98 "Игорь Лабутин" А теперь минутка интересных фактов для тех, кто возможно сейчас следит за спортивными футбольными матчами или другими соревнованиями. +68.98 84.62 "Игорь Лабутин" Представьте, что одна команда забила гол в этот момент, данные со стадиона проходят через десятки различных систем, получают информацию с кучей различных датчиков и все это должно очень быстро оказаться в виде нового какого-то коэффициента или вероятности в интерфейсе пользователя. +84.62 108.14 "Игорь Лабутин" И это не просто факт того, что команда забила гол, это на самом деле сложенная работа огромного количества и людей, и каких-то автоматизированных систем, и все это нужно каким-то правильным образом обработать, чтобы быстро-быстро, без каких-либо задержек, передать в центральное какое-то место и потом дальше распространить на пользователей. +108.14 121.18 "Игорь Лабутин" Для того, чтобы все это происходило максимально быстро на десятках видов спорта и на сотнях спортивных соревнований, которые проходят, возможно, одновременно, ребята из .NET команды Altenar пишут много своих продуктов, интегрируют много чужих решений в свою платформу. +121.18 124.14 "Игорь Лабутин" И именно об этом они нам рассказывали на конференции .NEXT. +124.14 125.58 "Игорь Лабутин" И в общем-то было довольно прикольно. +125.58 141.58 "Анатолий Кулаков" Ну что ж, у нас все ближе и ближе микрософтовская конференция, все ближе и ближе новый релиз нового .NET, нового C#, новых каких-то интересных наших тулов, и релиз кандидаты летят как пирожки. +141.58 145.34 "Анатолий Кулаков" И нас тут застал релиз кандидат второй уже .NET десятого. +145.34 147.26 "Игорь Лабутин" Да, это стандартная схема. +147.26 150.78 "Игорь Лабутин" У Microsoft два релиз-кандидата, RC1 и RC2. +150.78 158.74 "Игорь Лабутин" Сейчас речь пойдет о RC2, и в отличие от прошлых лет, мне кажется, что в прошлые годы в RC2 были какие-то существенные довольно большие иногда изменения. +158.74 161.78 "Игорь Лабутин" Сейчас в RC2 на самом деле практически нет изменений. +161.78 166.58 "Игорь Лабутин" В основном это какие-то улучшения качества, фиксы багов и так далее. +166.58 169.46 "Игорь Лабутин" Но, тем не менее, есть чуть-чуть о чем рассказать. +169.46 188.22 "Игорь Лабутин" В основном это касается SDK, и, наверное, это правильно, потому что чем ближе к релизу, тем больше мы волнуемся за тулинг, ну или тем больше полируется на самом деле тулинг и как-то все сводится к какой-то единой штуке, единому виду, единому подходу. +188.22 197.98 "Игорь Лабутин" Значит, во-первых, можно теперь использовать .NET MS-билдовые таски с .NET фреймворковым MS-билдом. +197.98 201.78 "Игорь Лабутин" Казалось бы, зачем? +201.78 205.74 "Игорь Лабутин" Мы же про .NET фреймворк уже давно забыли, но нет. +205.74 207.66 "Игорь Лабутин" На самом деле история в следующем. +207.66 214.02 "Игорь Лабутин" Командный тул .NET, который вот мы из Command Line используем, он использует MS-билд, который поставляется с SDK. +214.02 221.82 "Игорь Лабутин" То есть, если вы ставите какой-нибудь там десятый .NET SDK, с вами у вас будет MS-билд, который поставляется вместе с десятым .NET SDK. +221.82 227.06 "Игорь Лабутин" Visual Studio использует тот MS-билд, который устанавливается вместе с ней. +227.06 242.82 "Игорь Лабутин" А поскольку Visual Studio и MS-билд, соответственно, все еще это приложение на .NET фреймворке, ну и, соответственно, и MS-билд получается .NET фреймворковый, в то время как .NET C-лайдный MS-билд - это обычное приложение, новое современное. +242.82 261.90 "Игорь Лабутин" И проблема в том, что если вы пишете кастомные MS-билд таски, возможно, вы этого не делаете сильно часто и в каждом продукте, но тем не менее, я, например, когда-то давно писал для нашего продукта кастомные MS-билдовые таски, и получается, что есть проблема. +261.90 266.30 "Игорь Лабутин" Вам нужно, на самом деле, писать два вида тасков, потому что они не совсем совместимы. +266.30 278.10 "Игорь Лабутин" Вы не можете один и тот же таск использовать в MS-билде и в фреймворковом приложении, потому что там могут быть разные зависимости, это два разных фреймворка по сути. +278.10 292.42 "Игорь Лабутин" Но начиная с десятки .NET и Visual Studio 2026, она сможет использовать, несмотря на то, что она все еще на .NET фреймворке, она сможет использовать таски для MS-билда, которые собраны под обычный .NET, наш новый современный. +292.42 301.98 "Игорь Лабутин" И для того, чтобы это сделать, нам нужно указать в теге, когда вы загружаете тасочку, написать "Runtime = net". +301.98 317.26 "Игорь Лабутин" Ну и TaskFactory, это TaskHostFactory, это означает, что ваша таска, на самом деле, будет запускаться не in-process, она будет запускаться out-of-process, ну а если out-of-process, то понятное дело, что можно запустить под любого Runtime, на самом деле, ровно так они это и сделали. +317.26 332.02 "Игорь Лабутин" И это упрощает существенную жизнь разработчикам тасок, потому что теперь можно писать только обычные нормальные готовые MS-билдовые таски под современный .NET, а в .NET фреймворке как-нибудь само. +332.02 340.38 "Игорь Лабутин" Заработает, но понятно, что только если это 26-ая студия, ну и новый соответствующий MS-билд, который с ней и поставляется. +340.38 357.14 "Игорь Лабутин" Вот, это единственное изменение в SDK, которое, по крайней мере, стало достойным упоминаниям в Release Notes, также внезапно, после долгого умолчания, появилось чуть-чуть Release Notes на EF Core, там не так много изменений, но тем не менее. +357.14 359.18 "Игорь Лабутин" Они, кстати, могут быть довольно важны. +359.18 378.98 "Игорь Лабутин" Во-первых, сложные типы, то, что они называют комплекс-тайпами, то есть, по сути, это просто типы, которые вложены в другие типы, они умеют мапиться в JSON теперь, хотя мне казалось, что, по-моему, и раньше могли, где-то мы в каком-то превью что-то такое обсуждали, но, возможно, что-то доделали. +378.98 413.18 "Игорь Лабутин" Вторая штука, это интересно, если вы используете метод, например, from_sql_row, это иногда нужно, если вы не можете, например, выразить какой-то запрос средствами LinkU, или не то что не можете, а EF Core не может, например, оттранслировать его в нормальный SQL, и почему-то часть запроса выполняет на клиенте, то вы можете написать, естественно, самый обыкновенный SQL в текстном с трочкой, и вызвать функцию from_sql_row, и тогда он выполнит запрос прям вот как он есть. +413.18 433.66 "Игорь Лабутин" Так вот, теперь есть аналайзер, который, если он видит вызов функции from_sql_row, и внутри этой функции в аргументах видит какую-то конкретинацию строк, он тут же будет ругаться и говорить, ай-яй-яй, string concatenation, это там потенциальные всякие security баги, вот это все, sql injection, и все такое прочее. +433.66 439.78 "Игорь Лабутин" Что будет, если вы объявите переменную перед, в нее сконкретинируете, потом передадите from_sql_row? +439.78 446.98 "Игорь Лабутин" Не знаю, подозреваю, что он все-таки не настолько умный, но, по крайней мере, в каких-то простых случаях может быть, сможет спасти. +446.98 535.10 "Игорь Лабутин" Ну и, наверное, вот это вот самое, ну не то чтобы breaking change, но тем не менее, когда-то давно каждая миграция EF Cora выполнялась в отдельной транзакции или даже она была неявной транзакцией, я вот что-то не помню, я особо не пользовался миграциями EF Cora, потом, начиная с какой-то версии, все миграции запихнули в единую транзакцию, она ... этому было какое-то объяснение, но оказалось, что на самом деле все не так хорошо и некоторые операции не могут быть выполнены в одной транзакции, понятно, что в миграциях это обычно всякие добавления колонок, там переименования, ну, в общем, всякие не data modification, а data definition операции DDL, и вот они плохо себя чувствуют, когда они выполняются в рамках одной большой транзакции, не всегда результат одной операции виден в рамках этой же транзакции, поэтому теперь, начиная с нового EF Cora, каждая миграция будет выполняться в своей транзакции опять, опять откладываемся на поведение, которое было, по-моему, в шестерке, с семерки мне кажется, они единую транзакцию сделали, ну там да, в длинной дискуссии на предмет того, что ну да, тут ошиблись, ну и так хорошо, и так плохо, в общем, живите теперь с этим, такие дела. +535.10 597.46 "Игорь Лабутин" И последний кусочек, который попал в анонс релиз кандидата 2, это внезапно Maui, и это нет, это не как обычно там фикс багов и так далее, они добавили, ну там какие-то специфические штуки, типа поддержки разрешения работы с микрофонами на винде, улучшения в XAML Source Genie, но наверное самое интересное это то, что .NET, который работает сейчас на Android в рамках Maui, теперь в экспериментальном режиме будет работать на Core CLR вместо Mono, я напомню, что вот эти все мобильные варианты Maui, они все наследники Xamarin.Forms и работали на Mono, по сути своей, ну не то что наследники, но в общем, как-то inspired, да, имя, но вот первая экспериментальная попытка выкинуть Mono и заиспользовать Core CLR, посмотрим, что будет, это все пока экспериментал, насколько быстро эти эксперименты внутри Maui будут происходить, я пока не знаю, но поглядим, насколько это быстро будет. +597.46 611.86 "Анатолий Кулаков" Дерзко как-то, дерзко, особенно для второго релиз-кандидата, ну то есть это такая мега-фича, которая, я бы сказал, за последние 5 лет Maui вообще оправдывает его существование, смысл вообще его существования, а не раз так беспалево во втором релиз-кандидате ее выкатили. +611.86 617.18 "Игорь Лабутин" Ну слушай, она экспериментал, я думаю, что она будет экспериментал всю десятку, и хорошо, если в 11-м будет в нормальном +617.18 618.18 "Анатолий Кулаков" виде. +618.18 623.42 "Анатолий Кулаков" Ну ладно, посмотрим, подождем, не отвалится ли там что-нибудь по ходу. +623.42 630.86 "Игорь Лабутин" Ну в общем-то и все, а больше в релиз-кандидате ничего нет, понятно, что там есть куча bug-фиксов, какие-то довольно важные, но они все довольно нишевые. +630.86 652.94 "Анатолий Кулаков" У меня как раз есть интересная статья, которая почему-то нигде я в интернете не вижу, что все по ней хайпали, а статья очень, это же не статья, а тема, тема очень важная, это новый Command Line интерфейс для .NET, стандартный, микрософтовский, нативный, который System Command Line, что может быть нативнее. +652.94 686.94 "Игорь Лабутин" Мне кажется, он не такой новый, мне кажется, историю про то, как Microsoft пыталась переделать System Command Line, мы рассказывали, ладно, не переделать, а про то, что с Command Line у Microsoft все плохо, и поэтому там кто-то какой-то очень крутой чувак, или кто-то приходил в команду System Command Line, чтобы там все настроить, а, подожди, этот самый Ньютон Кинг же к ним приходил, чтобы все сделать правильно, вот, видимо, все, они наконец-таки доделали. +686.94 704.06 "Анатолий Кулаков" Вот как раз самое интересное, что да, они доделали долго и тяжко, но наконец-то они доделали, и вот этого шума нет, потому что, мне кажется, это big deal вообще может быть даже важнее всех нововведений, которые мы там ждали в библиотеках, в СДК, в C#, в синтексисе. +704.06 707.26 "Игорь Лабутин" Может, потому что фигня получилась, поэтому нет +707.26 708.26 "Анатолий Кулаков" вайпа. +708.26 713.30 "Анатолий Кулаков" Нет, нет, получилось довольно хорошенько, давай по порядку наших, слушайте, не заводить заблуждение. +713.30 715.34 "Анатолий Кулаков" Итак, в чем проблема-то, собственно? +715.34 728.26 "Анатолий Кулаков" Проблема в том, что наш .NET фреймворк, если взять его вместе с SPNet, если взять его вместе с Entity Framework, то Microsoft покрывает практически 99% всех надобностей, которые есть у современного разработчика. +728.26 738.42 "Анатолий Кулаков" И все бы хорошо, но не покрыто Microsoft уже многие десятилетия, если брать весь .NET, такая важная штука, как парсинг командной строки. +738.42 743.94 "Анатолий Кулаков" Вроде бы мелочь, но если начать задумываться, то это один огромный большой домен. +743.94 750.90 "Анатолий Кулаков" То есть вам не просто нужно посмотреть, кто в массиве аргументов у вас под индексом 1 лежит, кто под индексом 2 лежит. +750.90 751.90 "Анатолий Кулаков" Это все чушь. +751.90 764.06 "Анатолий Кулаков" Вам нужно на самом деле разобрать какие-то сложные команды с какими-то сложными аргументами, сконвертировать их типы, проверить на диапазон значений, посмотреть, что там какая-то команда идет следом за другой командой. +764.06 772.34 "Анатолий Кулаков" В общем, если начать разбираться, то это довольно такой, не то чтобы мега-сложный, но вполне отдельный и вполне непростой фреймворк получается. +772.34 774.22 "Анатолий Кулаков" Такой командлайн фреймворк. +774.22 782.26 "Анатолий Кулаков" И вот почему-то Microsoft никогда не обращал на него внимания, несмотря на то, что у Microsoft уже довольно много всяких командлайновых тулзов. +782.26 787.62 "Анатолий Кулаков" И вот все начало меняться совсем недавно относительно всего .NET. +787.62 789.22 "Анатолий Кулаков" Как мы жили до этого? +789.22 790.90 "Анатолий Кулаков" До этого мы жили довольно-таки плохо. +790.90 792.22 "Анатолий Кулаков" Ну, как плохо? +792.22 793.22 "Анатолий Кулаков" Без решения Microsoft. +793.22 795.94 "Анатолий Кулаков" Конечно, были классные другие библиотеки, сторонние. +795.94 810.10 "Анатолий Кулаков" Из них хотелось бы выделить… Ну, в общем, основные библиотеки они все были на уровне какого-то не концептуального решения этой проблемы, а вот переноса каких-нибудь плюсовых бестпрактисов на C#. +810.10 820.02 "Анатолий Кулаков" То есть вот мы берем параметры, там третий и четвертый параметр у нас парсится, приводится к каким-то типам, мы его помечаем какими-то методами. +820.02 831.06 "Анатолий Кулаков" В общем, если вы когда-то писали свой парсер аргументов, командной строки, то, скорее всего, он был такой какой-то примитивный, который опирался как раз на те строчки, которые нам приходят в массиве. +831.06 837.42 "Анатолий Кулаков" Этот подход нехороший, у него много багов, он ни разу не упрощает жизнь, а только усложняет ее. +837.42 845.66 "Анатолий Кулаков" И вот, насколько я помню, первое такое нововведение, первый такой свежий взгляд, который внес в нашу индустрию, это был Mono. +845.66 854.66 "Анатолий Кулаков" У Mono был Command-Line-Parser, обалденная библиотека, которая, наверное, самая популярная была из всех Command-Line-Parsers, и которую потом начали копировать. +854.66 856.22 "Анатолий Кулаков" В чем был свежий взгляд? +856.22 861.62 "Анатолий Кулаков" Свежий взгляд как раз был в том, что командную строку не надо воспринимать как массив строк. +861.62 871.34 "Анатолий Кулаков" Вот командная строка вместе со своими аргументами вполне из себя представляет отдельный синтаксис, который можно десериализовать, как положено в C#, в какой-то объект. +871.34 876.34 "Анатолий Кулаков" В общем, то, что мы десериализуем джессоны в DTO-шках, уже никого давно не смущает. +876.34 886.26 "Анатолий Кулаков" А то, что мы в такую же DTO-шку можем десериализовать командные аргументы, аргументные командные строки, вот на тот момент это было мега нововведение. +886.26 891.66 "Анатолий Кулаков" Сейчас понятно, эта идея уже много где разрослась, много где реализована, этим никого не удивишь. +891.66 893.62 "Анатолий Кулаков" Но тогда это был прям взрыв мозга. +893.62 903.22 "Анатолий Кулаков" И вот это был тот свежий взгляд, тот новый подход, который и вдохнул какую-то свежую мысль в партии командных строк. +903.22 912.46 "Анатолий Кулаков" И вот именно эту идею забрал к себе Microsoft, докрутил ее и начал что-то с ней делать. +912.46 920.66 "Анатолий Кулаков" Даже не Microsoft, первые реализации вот этой идеи на основании .NET Core были сделаны сотрудниками Microsoft в нерабочее время. +920.66 924.50 "Анатолий Кулаков" То есть как open-source проект они начали пилить. +924.50 933.14 "Анатолий Кулаков" Люди понимали, что они пишут много команд-лайновых тулзов и им не хватает чего-то, самого главного, интерфейса для взаимодействия с командной строкой. +933.14 941.02 "Анатолий Кулаков" И в 2020 году вышел первый пэкэдж, то есть это 5 лет уже прошло. +941.02 945.98 "Анатолий Кулаков" И за эти 5 лет у нас не было ни одного стабильного релиза. +945.98 950.30 "Анатолий Кулаков" То есть все там выпускались беты, альфы, 0.39, в общем какие-то такие. +950.30 962.18 "Анатолий Кулаков" Но несмотря на то, что не было ни одного стабильного релиза, пакет набрал 60 миллионов скачиваний, в общем, за все версии за эти 5 лет, что довольно-таки немало. +962.18 971.06 "Анатолий Кулаков" То есть люди не гнушались скачивать беты безрелизные, использовать их, ну потому что было удобно, потому что было хорошо. +971.06 978.70 "Анатолий Кулаков" И был хоть какой-то шанс, что рано или поздно вот этот поддерживаемый пакет наконец-то зарелизится и будет поддерживаться самой Microsoft. +978.70 991.86 "Анатолий Кулаков" Вот, на самом деле здесь много интересных концепций Microsoft принял, но без каких-то вау-эффектов, то есть то, что мы ожидали, как оно должно быть сделано хорошо, вот то они и сделали. +991.86 1020.38 "Анатолий Кулаков" То есть он там, при этом он говорит, что как бы не хочет опять замещать комьюнити, давить на комьюнити и убивать все остальные библиотеки, поэтому он постарался сделать такие замещаемые компоненты, он выделил отдельно какой-то парсер, который могут переузывать, допустим, другие библиотеки, отдельный рендер для страницы, там, хелпа, чтобы мог кто-угодно там сформировать свою страницу хелпа, в общем, такой расширяемую модель сделал. +1020.38 1054.90 "Анатолий Кулаков" За все это время там уже было тысячу pull-requests, уже какие-то сотни авторов, и более того, они привлекали автора Spectre Console, это, наверное, одна из самых популярных библиотек для работы с консолью, она прежде всего популярна в том, что реализует очень красивую консоль, то есть у нее там поддержка true-color прямо в консоли, сглаживание анти-алиязинг шрифтов, рисование псевдографики, использование эмоджи, юникода, то есть если не видели, просто зайдите там на главный спектр консоли и посмотрите, как нормальная консоль должна выглядеть, это уже красиво. +1054.90 1064.14 "Анатолий Кулаков" Ну и плюс этот автор реализовал у себя тоже подмножество классиков библиотек, которые как раз и служили для того, чтобы парсить аргументы командной строки. +1064.14 1074.74 "Анатолий Кулаков" Вот Microsoft пригласили автора, он им там тоже помогал, советовал, репортил баги, в общем, в плотной связке с комьюнити была рождена эта библиотека. +1074.74 1078.10 "Анатолий Кулаков" Вот такая вот история у нас получилась. +1078.10 1079.46 "Анатолий Кулаков" Что же на сегодняшний день? +1079.46 1119.90 "Анатолий Кулаков" На сегодняшний день у нас пока есть релиз «Кандидат», все мы ждем стабильную версию с дотнет 10 в ноябре 2025 года, и за это время, вот я уже сказал, там огромные 60 миллионов скачиваний, вот эта библиотека в бета-версии с какими-то там разными 0 какими-то версиями, в бета-статусе используется такими инструментами, как сам dotnet CLI, PowerShell, PowerToys, Semantic Kernel, Roslyn, MonoGames, Orleans, UnaPlatform, Azure SDK, ну то есть весь Microsoft, у кого есть там командные строчки, он ее использует в релизных тулзах, несмотря на то, что сама библиотека бета. +1119.90 1133.54 "Анатолий Кулаков" Ну и за пределами Microsoft, конечно, более мелкие проекты тоже ее сильно-сильно используют, поэтому авторитет у нее до релиза уже какой-то подтвержден, уже в продакшене обкатано и кажется, что уже как бы все довольны. +1133.54 1138.18 "Анатолий Кулаков" Давайте же посмотрим, с самого начала, зачем же нам нужна разработчикам эта прекрасная библиотека? +1138.18 1158.98 "Анатолий Кулаков" Ну, как вы, наверное, поняли, для того, чтобы писать код самого приложения, а не заниматься парсингом командных строк, не заниматься форматированием страниц этой Help-странички со списком всех команд, не задумываться о том, какая команда за какой идет, какие типы они поддерживаются, вот обо всем этом не думать. +1158.98 1169.34 "Анатолий Кулаков" А также эта библиотека была написана с учетом тестирования, то есть вы можете тестировать свой код независимо от самой функции парсинга. +1169.34 1182.94 "Анатолий Кулаков" Из еще прекрасных преимуществ это AOT-компетибл, то есть можно ее триммить, можно использовать в АОТе, можно оптимизировать, уже напишется с учетом новых стандартов и новых веяний. +1182.94 1191.30 "Анатолий Кулаков" Поддержка код комплишена, об этом еще подробнее поговорим, и респонс файлов тоже раскроем. +1191.30 1208.02 "Анатолий Кулаков" У нее также есть поддержка подкоманд, например, dotnet-run, то есть dotnet – это сама команда, а run – это как раз подкоманда, или git-commit, или git-branch, то, что вы в повседневной жизни не могли видеть, это все подкоманды, и она поддерживает бесконечную вложенность подкоманд. +1208.02 1217.54 "Анатолий Кулаков" Поддержка alias-ов, псевдонимов, то есть вместо git-commit вы можете использовать git-ci, допустим, и ci можно объявить как alias к этой командной строке. +1217.54 1220.14 "Анатолий Кулаков" Вместо git-branch – там git-br, и так далее. +1220.14 1224.34 "Анатолий Кулаков" Ну, или вместо help, точно так же, команду можно объявить –h. +1224.34 1236.90 "Анатолий Кулаков" Также эта библиотечка из коробки поддерживает завершение консоли, то есть если вдруг у вас в терминале кто-то нажал Ctrl+C, или в Linux послал sigint или sigterm, то консоль завершается. +1236.90 1238.54 "Анатолий Кулаков" То есть процесс прерывается, и консоль завершается. +1238.54 1246.10 "Анатолий Кулаков" Так вот, эта прелесть поддерживает перехват всех этих событий прямо из коробки и реализует их в виде привычного прекрасного консолейшн-токена. +1246.10 1255.14 "Анатолий Кулаков" То есть можно запросить специальный консолейшн-токен, который будет прерываться от системных команд терминейки процесса, что тоже очень удобно. +1255.14 1268.14 "Анатолий Кулаков" Итак, чтобы завязать в вашем приложении эту прекрасную штуку, вам нужно установить новый пакет, который называется mcmonline, ну как новый, 5 лет вчала все его пакетику, и прописать следующий код. +1268.14 1281.82 "Анатолий Кулаков" То есть, как я уже говорил, все наши аргументные командные строки мы упаковываем в виде какой-то DTOшки, и эта DTOшка просто-напросто децерализуется из аргументных командной строки. +1281.82 1282.82 "Анатолий Кулаков" Вот. +1282.82 1288.42 "Анатолий Кулаков" Для того, чтобы описывать вот такие вот аргументы, есть специальный класс, который называется option. +1288.42 1300.14 "Анатолий Кулаков" Здесь, наверное, не очень удобно, потому что у нас есть options от t, который подразумевает именно настройку из конфигурационных файлов, переменных среды окружения и так далее. +1300.14 1302.06 "Анатолий Кулаков" Вот здесь может быть небольшая путаница. +1302.06 1305.02 "Анатолий Кулаков" В общем, здесь не options, здесь option от t. +1305.02 1307.82 "Анатолий Кулаков" В общем, нужно уже как-то в голове разделять. +1307.82 1309.58 "Анатолий Кулаков" Два разных option у нас появляется. +1309.58 1310.58 "Анатолий Кулаков" Ну, не критично. +1310.58 1314.70 "Анатолий Кулаков" По идее, там, где они пересекаются, они, наверное, нигде не пересекаются. +1314.70 1315.70 "Анатолий Кулаков" Ну, так вот. +1315.70 1323.10 "Анатолий Кулаков" Давайте, для примера, представим себе, вот мы хотим считать какое-то имя файла из командной строки нашего консольного приложения. +1323.10 1324.82 "Анатолий Кулаков" Что бы мы могли сделать? +1324.82 1328.46 "Анатолий Кулаков" Здесь объявляется класс option от FileInfo. +1328.46 1337.26 "Анатолий Кулаков" Очень важно заметить, что это не option от строки, которая представляет собой путь к файлу, а option именно от FileInfo. +1337.26 1349.30 "Анатолий Кулаков" Если вы никогда не пользовались стандартными классами файловой системы, то FileInfo – это как раз стандартное описание в C#, как раз стандартное описание файла, которое лежит на диске. +1349.30 1353.98 "Анатолий Кулаков" Так вот, мы можем options сразу десериализовать в строго типизированный FileInfo. +1353.98 1384.14 "Анатолий Кулаков" Для того, чтобы это сделать, мы указываем в конструкторе, с помощью какой команды мы будем это делать, с помощью какой команды пользователь будет указывать этот путь, в нашем случае это файл, и эти options принимают несколько необязательных полей, например, description, в котором мы можем записать описание того аргумента, который пользователь должен нам передать, по такому счету человеческое читание, которое выведется в хелпе, если вдруг пользователь захочет посмотреть страничку с помощью. +1384.14 1396.30 "Анатолий Кулаков" Мы можем здесь указать флажок, обязательный этот реквизит или необязательный, мы можем выставить какое-то значение по умолчанию, и много других разных вспомогательных параметров, которые, в принципе, не суть важны. +1396.30 1404.90 "Анатолий Кулаков" Вот самый банальный, самый базовый, который всем нужны – это обязательно description, обязательность и какое-то значение по умолчанию, чтобы тоже там удобно нигде не проверять. +1404.90 1417.22 "Анатолий Кулаков" Вот и все, дальше этот option мы засовываем в специальный root command, в специальный классик, и у этого root command вызываем метод parse, и этому методу parse передаем наш массив с аргументами, массивы строчек. +1417.22 1426.58 "Анатолий Кулаков" Все, вот вам готовый парсер, который децерализует те options, которые вы попросили, из аргументов. +1426.58 1429.18 "Анатолий Кулаков" Дальше нам возвращается результат, который называется parsed result. +1429.18 1432.22 "Анатолий Кулаков" В этом parsed result содержится две основные секции. +1432.22 1437.38 "Анатолий Кулаков" Во-первых, это errors, то есть это список ошибок, которые у вас могли возникнуть при парсинге. +1437.38 1445.32 "Анатолий Кулаков" У каждого списка, у каждой этой ошибки там есть свойство message, которое вы можете вывести на консоль и показать пользователю, а что, собственно, прошло не так. +1445.32 1451.34 "Анатолий Кулаков" И если ошибок 0, то значит децерализация прошла успешно. +1451.34 1458.22 "Анатолий Кулаков" Соответственно, мы можем попросить у этого parsed result все те параметры, которые мы ему туда забросили. +1458.22 1467.22 "Анатолий Кулаков" Например, мы можем попросить наш file options, и он нам вернет непосредственно уже файл инфа, заполненным правильным путем. +1467.22 1473.22 "Анатолий Кулаков" Дальше этот файл инфа мы можем использовать на своем осмотрении, например, прочитать содержимое всего этого файла. +1473.22 1483.70 "Анатолий Кулаков" Вот так в строго типизированном виде, в объектно-ориентированном подходе должен выглядеть нормальный децерализатор командной строки. +1483.70 1486.54 "Анатолий Кулаков" То есть должна выглядеть вообще работа с командной строкой. +1486.54 1490.58 "Анатолий Кулаков" И тогда мы получаем хорошую заполненную DTO-шку. +1490.58 1499.98 "Анатолий Кулаков" Кроме хорошей заполненной DTO-шки, из коробки вот этот run command, который мы сформировали, он поддерживает операцию help. +1499.98 1519.02 "Анатолий Кулаков" То есть если пользователь укажет к вашему приложению - - help, это все прекрасно отработается, и в ответ ему выведется красивая помощь, в которой будут расписаны все команды, которые поддерживают приложение, человеческое читабельное описание к этим командам, ну и плюс какие-то вспомогательные опции. +1519.02 1523.38 "Анатолий Кулаков" Дальше из коробки поддерживается - - version, то есть посмотреть версию приложения. +1523.38 1532.50 "Анатолий Кулаков" Также из коробки поддерживается IntelliSense, то есть подсказки для вашей командной утилиты, об этом мы подробнее попозже поговорим. +1532.50 1535.70 "Анатолий Кулаков" И, естественно, поддерживается красивый вывод ошибок. +1535.70 1547.26 "Анатолий Кулаков" Если пользователь указал какой-то лабутень, который никак не подходит к тем параметрам, которые вы задали, ему сформируется красивый отчет и покажется, что не так, куда не смогли прибинтить, как не смогли сконвертировать тип, это все расскажется. +1547.26 1551.18 "Анатолий Кулаков" Вот, и это прекрасно. +1551.18 1552.34 "Анатолий Кулаков" Дальше к синтаксису. +1552.34 1561.90 "Анатолий Кулаков" Опять же у нас есть несколько платформ, так как .NET кросс-платформенный, ему необходимо поддержать работу с командной строкой на разных операционных системах. +1561.90 1569.66 "Анатолий Кулаков" И основное отличие в разных операционных системах это в том, что у них по-разному указываются какие-то параметры, какие-то опции, какие-то аргументы. +1569.66 1574.18 "Анатолий Кулаков" Не то чтобы слишком по-разному, но разница есть. +1574.18 1582.88 "Анатолий Кулаков" Например, в POSIX-системах, считайте, Linux, принято передавать опции через два минуса. +1582.88 1586.34 "Анатолий Кулаков" Минус-минус help, минус-минус version, вот это вот все. +1586.34 1590.40 "Анатолий Кулаков" В Windows принято передавать аргументы через обратный слэш. +1590.40 1594.14 "Анатолий Кулаков" То есть, слэш help, слэш version и так далее. +1594.14 1601.62 "Анатолий Кулаков" И прелесть этой библиотеки в том, что она поддерживает оба этих варианта. +1601.62 1607.02 "Анатолий Кулаков" То есть, вы можете обращаться как так, так и сяк к нашей утилитке. +1607.02 1613.34 "Анатолий Кулаков" Она поймет, что вы хотели, независимо от того, на какой платформе вы сейчас сидите, и покажет вам то, что нужно. +1613.34 1617.02 "Анатолий Кулаков" Еще есть отличие в том, как аргументы разделяются от их значений. +1617.02 1635.42 "Анатолий Кулаков" Например, если вам нужно задать аргумент verbosity, который может, например, иметь значение detailed или normal, то есть тот уровень логирования, который ваша утилита должна из себя выпускать, то вы можете задать это, опять же, на разных операционных системах через разные делимитеры. +1635.42 1648.52 "Анатолий Кулаков" Например, вы можете написать verbosity пробел normal, или verbosity равно normal, или verbosity deadweight очень normal, а в POSIX-системах задекларировано, что вы можете написать с сокращенным результатом. +1648.52 1652.56 "Анатолий Кулаков" Минус в, и вообще не отступая ничего, сразу написать normal. +1652.56 1654.88 "Анатолий Кулаков" То есть, получается, минус в normal. +1654.88 1659.04 "Анатолий Кулаков" Это тоже надо типа поддержать, потому что POSIX так хочет. +1659.04 1673.12 "Анатолий Кулаков" Вот наша прекрасная библиотека проподдерживает все эти разделители между параметрами и значениями, и вам, соответственно, больше не нужно думать, на какой операционной системе вы работаете или с каким синтаксисом пользователь привык работать. +1673.12 1674.56 "Анатолий Кулаков" Оно поймет все. +1674.56 1676.16 "Анатолий Кулаков" Итак, респонс-файлы. +1676.16 1677.28 "Анатолий Кулаков" Прикольная штука. +1677.28 1681.96 "Анатолий Кулаков" Еще со времен DOS-а она поддерживается, по крайней мере, в винде. +1681.96 1683.84 "Анатолий Кулаков" Я что-то со времен DOS-а в Linux не помню. +1683.84 1686.24 "Анатолий Кулаков" Я думаю, что в Linux точно так же. +1686.24 1691.72 "Анатолий Кулаков" Респонс-файлы – это файлы, в которых записаны все аргументы командной строки. +1691.72 1692.72 "Анатолий Кулаков" Нет, не все. +1692.72 1693.72 "Анатолий Кулаков" Просто какие-то аргументы командной строки. +1693.72 1697.24 "Анатолий Кулаков" Там может быть и какая-то часть, или просто все. +1697.24 1701.16 "Анатолий Кулаков" И эти аргументы, то есть даже этот файл, вы можете указать к любой утилите. +1701.16 1705.68 "Анатолий Кулаков" Например, вы можете написать .NET, поставить собаку и указать имя файла. +1705.68 1710.80 "Анатолий Кулаков" И .NET запустится и возьмет все аргументы командной строки прямо из этого файла. +1710.80 1723.52 "Анатолий Кулаков" Очень удобная штука, особенно когда вы много автоматизируете что-то, или запускаете какой-нибудь MSBuild вручную, когда какой-нибудь MSBuild.exe там был, и вручную ему нужно было передавать огромное количество аргументов. +1723.52 1726.60 "Анатолий Кулаков" Писать это все ручками или в одной строке неудобно. +1726.60 1733.24 "Анатолий Кулаков" А вот в файле в каком-то очень удобно, потому что файл поддерживает несколько строк. +1733.24 1737.44 "Анатолий Кулаков" То есть вы можете разбить каждый аргумент на отдельной строке, и он становится читабельным и красивым. +1737.44 1741.64 "Анатолий Кулаков" Более того, там есть символ решетки, который подразумевает, что это комментарий. +1741.64 1746.00 "Анатолий Кулаков" То есть вы можете откомментировать каждую строчку, каждый аргумент, написать почему так, а не сяк. +1746.00 1754.84 "Анатолий Кулаков" Более того, вы можете указать собаку в этом файле и сослаться на другой файл, на другой респонс файл, который будет точно так же включен в этот файл. +1754.84 1757.84 "Анатолий Кулаков" То есть там получается прям язык программирования. +1757.84 1761.44 "Анатолий Кулаков" Вместе с инклудами, комментариями, разбиениями на строчке. +1761.44 1764.00 "Анатолий Кулаков" Короче, очень удобно для больших файлов. +1764.00 1771.54 "Анатолий Кулаков" Если вы ни разу не сталкивались, то обратите внимание, возможно в каких-то утилитах командной строки вам будет это удобно. +1771.54 1778.92 "Анатолий Кулаков" Ну так вот, как раз этот пакет, эта библиотечка наша из коробки поддерживает респонс файлы, что прекрасно. +1778.92 1782.60 "Анатолий Кулаков" Респонс файлы вам в основном будут нужны для двух основных случаев. +1782.60 1785.80 "Анатолий Кулаков" Это когда вы не влазите в лимит терминала. +1785.80 1790.36 "Анатолий Кулаков" То есть могут быть такие огромные командные строки, которые в некоторых терминалах даже не помещаются. +1790.36 1792.04 "Анатолий Кулаков" То есть терминал не может этого переварить. +1792.04 1797.04 "Анатолий Кулаков" Например, очень часто там досовские терминалы старые, они больше 250 символов переварить не могли. +1797.04 1806.84 "Анатолий Кулаков" А если вы хотите скомпилировать какой-нибудь плюсовый проект, указав ему при этом все исходники, все аутпоты, все строчки директивы компилятора и оптимизации, то обычно вы обломаетесь. +1806.84 1808.96 "Анатолий Кулаков" Респонс файлы как раз решает эту проблему. +1808.96 1816.32 "Анатолий Кулаков" И также второй сценарий, когда респонс файлы вам будут полезны, это когда вы не хотите повторять одни и те же аргументы много-много раз. +1816.32 1825.68 "Анатолий Кулаков" Допустим, у вас их много и вы там постоянно опять же компилируете напрямую свои файлики и указываете там полный список файлов вместе с ключами оптимизации. +1825.68 1830.08 "Анатолий Кулаков" Зачем вам каждый раз их указывать, когда вы понимаете, что компиляция все время будет одна и та же. +1830.08 1836.72 "Анатолий Кулаков" Легче всего это вынести в какой-нибудь респонс файл и запускать этот респонс файл периодически, когда вам нужно. +1836.72 1850.56 "Анатолий Кулаков" Так, для того, чтобы запустить респонс файл, напомню, что вам нужно просто поставить собаку и указать имя файла, в котором лежат аргументы – .NET, собака, респонс, обычно точка RSP. +1850.56 1859.64 "Анатолий Кулаков" РСП – это такая договоренность, к которой могут лежать аргументы, но, естественно, extension необязательный, можете указать любой, какой вам больше нравится. +1859.64 1869.16 "Анатолий Кулаков" То есть крутых таких стандартных фишек, как вы видите, очень много, которые от утилиты командной строки люди ожидают. +1869.16 1885.80 "Анатолий Кулаков" И если вы, допустим, писали свой собственный парсинг арксов в приложении, то почти 100% никаких респонс файлов вы там не поддерживали и никаких там различных синтаксисов для аргументов и их параметров вы там не поддерживали. +1885.80 1897.24 "Анатолий Кулаков" В общем, библиотека покрывает хорошие нужды тех разработчиков, тех пользователей, которые уже привыкли к какому-то стандартному поведению. +1897.24 1905.16 "Анатолий Кулаков" Но также она добавляет парочку новых интересных вещей, которые я вообще не встречал ни в каком стандартном поведении. +1905.16 1907.56 "Анатолий Кулаков" Это так называемые директивы. +1907.56 1917.78 "Анатолий Кулаков" Директивы - это некая функциональность, которая относится ко всему, ко всей командной строке, не к какому-то конкретному приложению. +1917.78 1920.20 "Анатолий Кулаков" Звучит мутно, поэтому давайте посмотрим на примерах. +1920.20 1926.52 "Анатолий Кулаков" У командлайна, у этой библиотеки встроены две стандартные директивы. +1926.52 1927.52 "Анатолий Кулаков" Диаграмм и саджест. +1927.52 1934.96 "Анатолий Кулаков" Директива "диаграмм" нужна для того, чтобы показать, каким образом парсер заинтерпретировал ваши командные аргументы. +1934.96 1946.12 "Анатолий Кулаков" То есть, командных аргументов может быть много, они там есть флажочки, есть подкоманды, есть какие-то опции, есть команды, есть аргументы, в общем, много всяких перепутанных. +1946.12 1949.24 "Анатолий Кулаков" И то, как они распарсятся, в принципе, важно. +1949.24 1955.64 "Анатолий Кулаков" Это, по сути, значит, как ваш дистерилизатор по сути их заинтерпретирует, как он засунет их в эту DTO. +1955.64 1968.56 "Анатолий Кулаков" Поэтому, указав специальную директиву "диаграмм", вы не получите запуск приложения, вы получите дамп того, как парсер распарсил все аргументы, которые вы передали после "диаграмма". +1968.56 1979.04 "Анатолий Кулаков" Чтобы указать эту директиву, вам нужно выполнить вашу команду, например, dotnet, и сразу же в квадратных скобках указать слово "диаграмм". +1979.04 1983.20 "Анатолий Кулаков" И только после этих квадратных скобок, после слова "диаграмм" указывать все остальное. +1983.20 1986.92 "Анатолий Кулаков" То есть, директива идет перед всеми другими подкомандами. +1986.92 1989.52 "Анатолий Кулаков" Сразу, непосредственно после самого экзешника. +1989.52 1991.84 "Анатолий Кулаков" Вот такое чудо-слово. +1991.84 1996.76 "Анатолий Кулаков" Вторая встроенная директива, которая есть из коробки - это директива "саджест". +1996.76 2006.20 "Анатолий Кулаков" Директива "саджест" нужна для того, чтобы подсказать, а какие аргументы там есть у вашей командной строки без их точного введения. +2006.20 2011.52 "Анатолий Кулаков" Ну, например, вы можете по части команды посмотреть, а какие команды вообще можно было бы передать. +2011.52 2023.84 "Анатолий Кулаков" Если вы сделаете dotnet в квадратных скобках "саджест" и напишете слово "build", то вам от этой команды вернется список из тех команд, которые можно выполнить. +2023.84 2026.08 "Анатолий Кулаков" Например, "build", "buildserver" или "msbuild". +2026.08 2032.56 "Анатолий Кулаков" То есть, он делает "contains" по той части слова, которую вы передали. +2032.56 2033.56 "Анатолий Кулаков" И вываливает вам список всех команд. +2033.56 2037.96 "Анатолий Кулаков" Тоже очень полезная директива. +2037.96 2041.84 "Анатолий Кулаков" Разумеется, директивы можно писать и свои, но вот эти две стандартные как бы есть из коробки. +2041.84 2047.04 "Анатолий Кулаков" Так, теперь пройдемся немножко по нашему парсеру. +2047.04 2055.44 "Анатолий Кулаков" Парсер из коробки поддерживает все стандартные типы, все примитивы, разумеется, которые вы ожидали бы. +2055.44 2063.76 "Анатолий Кулаков" Bool, Int, DateTime, GuiD, Enum, естественно, тоже, и, может быть, парочку тех, которых вы не ожидали. +2063.76 2076.88 "Анатолий Кулаков" Например, "file.info", "directory.info" я там не ожидал увидеть, но, наверное, если задуматься, то чаще всего в командных строках задаются как раз-таки пути к файлам разные или пути к директориям, над которыми нужно производить какие-то операции. +2076.88 2083.72 "Анатолий Кулаков" Поэтому разумным как раз Microsoft было включить эти директивы прямо из коробки, чтобы они поддерживались. +2083.72 2091.36 "Анатолий Кулаков" Также все Array и все листы от указанных типов тоже поддерживаются. +2091.36 2095.12 "Анатолий Кулаков" Вы можете сделать кастомную валидацию типов. +2095.12 2100.64 "Анатолий Кулаков" Для этого вам нужно добавить вот к этой команде "options", которую мы там выше с вами создавали. +2100.64 2108.44 "Анатолий Кулаков" У нее есть свойство "validators", и в этот "validators" вы можете запихнуть любой делегат, который провалидирует дополнительно те аргументы, которые у вас получились. +2108.44 2116.76 "Анатолий Кулаков" Например, вы там можете указать какое-то минимальное или максимальное значение, или какой-то промежуток даты и времени, через который он не должен выходить. +2116.76 2123.56 "Анатолий Кулаков" Или можно, например, указать, чтобы файл, который был передан в аргументах командной строки, обязательно существовал на диске. +2123.56 2126.00 "Анатолий Кулаков" В общем, это все делается с помощью таких вот "validators". +2126.00 2127.64 "Анатолий Кулаков" Их можно засунуть сколько угодно. +2127.64 2132.00 "Анатолий Кулаков" Также есть поддержка кастомных парсеров. +2132.00 2144.64 "Анатолий Кулаков" То есть, если вам тех типов, которые поддерживает Микрософт из коробки, мало, а вам их по-любому будет мало, потому что вы захотите какие-то кастомные сложные типы туда засовывать, какие-то свои, может быть, объекты. +2144.64 2147.20 "Анатолий Кулаков" В общем, тоже это делается довольно просто. +2147.20 2153.56 "Анатолий Кулаков" У "options" есть "custom parser", это делегат, который принимает специальный "parsed result". +2153.56 2162.48 "Анатолий Кулаков" В этом "parsed result" есть уже распаршенные токены, то есть, по сути, своеобразное примитивное синтаксическое дерево тех аргументов, которые вам передали. +2162.48 2167.92 "Анатолий Кулаков" И этот "custom parser" должен вернуть тот объект, который он распарсил из этих токенов. +2167.92 2172.56 "Анатолий Кулаков" В общем, тоже добавляются парсеры легко и непринужденно. +2172.56 2185.36 "Анатолий Кулаков" Еще одна интересная фишка, которая, в принципе, есть у всех современных ".NET", не ".NET", а "Command Line" утилит – это "tab completion", то есть, завершение автоматическое тот команды. +2185.36 2192.84 "Анатолий Кулаков" То есть, интеллисенс такой своеобразный, мы привыкли к интеллисенсу в наших EDEs, а вот в "Command Line" в принципе не очень привыкли. +2192.84 2211.56 "Анатолий Кулаков" Но фишка заключается в том, что очень многие современные оболочки "Command Line" и очень многие современные команды, утилиты, экзешники, утилиты "Command Line", то есть, они поддерживают вот такие вот завершения команд, то есть, они могут вам советовать, а как бы вы могли эту команду продолжить. +2211.56 2218.52 "Анатолий Кулаков" Так вот, из коробки, опять же, "tab completion" для этой библиотеки, если вы ее используете, прекрасно поддерживается. +2218.52 2225.44 "Анатолий Кулаков" Он вычисляется из каких-то статических значений, которые в этих опциях могли быть указаны, например, из "enum". +2225.44 2233.72 "Анатолий Кулаков" Если вы задали "enum" в качестве аргумента, то, естественно, Runtime может "enum" распарсить, посмотреть его значения и вполне выдать "suggestion" по этому "enum". +2233.72 2250.36 "Анатолий Кулаков" Ну и, естественно, вы можете сделать свой кастомный "tab completion" в Runtime, то есть, есть специальный делегат, на который вы подписываетесь, он вам присылает, что пользователь хотел бы увидеть, и вы можете выдать любую подсказку, какую только посчитаете нужную. +2250.36 2256.48 "Анатолий Кулаков" Для того, чтобы поддержать "tab completion" у каждого шела, у каждой оболочки командной строки есть свои правила. +2256.48 2263.80 "Анатолий Кулаков" Например, если вы там пользуетесь PowerShell, ZShell, Bash, то вам необходимо настроить там специальные хуки. +2263.80 2266.60 "Анатолий Кулаков" Если вам интересно, в документации все это описано. +2266.60 2275.32 "Анатолий Кулаков" Проблема заключается в том, что, в общем, если мы берем, например, Bash, он не знает, каким образом получить вот эти "suggestions" из утилиты командной строки. +2275.32 2278.20 "Анатолий Кулаков" То есть, какого-то стандартного способа не существует. +2278.20 2283.92 "Анатолий Кулаков" Поэтому каждая утилита, она предоставляет какие-то свои собственные флаги, свои собственные хуки. +2283.92 2295.40 "Анатолий Кулаков" И вы должны рассказать, товарищ Баш, вот возьми вот эту утилиту, которая называется .NET, у нее мы "suggestions" получаем вот так, теперь возьми утилиту, которая называется .GIT, у нее мы "suggestions" получаем вот так. +2295.40 2297.04 "Анатолий Кулаков" И вот это все нам нужно рассказывать. +2297.04 2301.32 "Анатолий Кулаков" Не очень удобно, но, к сожалению, пока другого способа не существует. +2301.32 2308.00 "Анатолий Кулаков" Есть пока тенденции, о них я вам расскажу в следующих выпусках, но стандарта на данный момент нет. +2308.00 2325.68 "Анатолий Кулаков" Поэтому если вы вдруг используете нашу любимую Command Line библиотеку, то она поддерживает все эти "suggestions", но их нужно соответственно регистрировать в ваших шеллах, вот таким образом, если вы хотите поддержку этих "suggestions". +2325.68 2326.68 "Анатолий Кулаков" Есть другой способ. +2326.68 2335.48 "Анатолий Кулаков" Можно установить утилиту .NET Suggest, это Global Tool, небезызвестный, который делает чудесную магию. +2335.48 2367.80 "Анатолий Кулаков" Так как Global Tool знает, что вы используете систему Command Line, то он регистрирует в шелле специальный хук, который позволяет для всех утилит, которые у вас есть, и если все ваши утилиты поддерживают систему Command Line, он позволяет единообразным способом вычислять "suggest", потому что мы с вами уже выяснили, что "suggest" у всех приложений, которые используют систему Command Line, получается одним прекрасным образом, с помощью директивы "suggest". +2367.80 2387.68 "Анатолий Кулаков" Поэтому зная этот факт, зная набор тех утилит, которые установлены у вас и которые используют систему Command Line, вот эта прекрасная утилитка, она просто-напросто регистрирует один-единственный скрипт в вашем шелле, и этот скрипт позволяет вам получать "suggest" абсолютно для всех .NET библиотек, которые используют систему Command Line. +2387.68 2397.28 "Анатолий Кулаков" В общем, вот этот тоже замороч, немножко мы решили, потому что внутри .NET, грубо говоря, мы стандартизировали тот способ, каким образом мы можем получать подсказки. +2397.28 2403.60 "Анатолий Кулаков" Поэтому мы получили такой своеобразный стандарт интеллисенса для всех .NET утилит, что тоже прекрасно. +2403.60 2421.52 "Анатолий Кулаков" Итак, ну, кажется, что вот эта библиотека, которая у нас зарелизится уже буквально на днях, заборит все существующие, опять же, альтернативы, которые есть, потому что она прямо из коробки хороша, и она уже испробована в продакшене давным-давно. +2421.52 2428.36 "Анатолий Кулаков" Но, может быть, найдутся какие-то другие библиотеки, которые могут добавить какую-то дополнительную функциональность. +2428.36 2437.48 "Анатолий Кулаков" Например, есть библиотеки, которые более оптимальны и более красиво позволяют вам настраивать вот эти опшнсы с помощью атрибутов, еще чего-то, но это все мелочи. +2437.48 2443.28 "Анатолий Кулаков" Наверное, из альтернатив хотелось бы отметить консоль App Framework. +2443.28 2452.12 "Анатолий Кулаков" Это библиотека от компании C-Sharp, нет, C-Sharp, наверное, читается. +2452.12 2467.40 "Анатолий Кулаков" Это известный Yashifumi Kawai, автор MemoryPack, MessagePack и многих других хай-перформанс библиотек, мы очень часто его упоминаем в наших подкастах, потому что автор действительно просто бешеный. +2467.40 2474.72 "Анатолий Кулаков" Он очень круто пишет библиотечки, очень круто их поддерживает и очень много их пишет, то есть у него производительность какая-то неимоверная. +2474.72 2482.48 "Анатолий Кулаков" Вот почему, мне кажется, что это единственный человек, который пишет достойные альтернативы микрософтовским вариантам. +2482.48 2485.36 "Анатолий Кулаков" Как он описывает консоль App Framework вот этот свой? +2485.36 2508.28 "Анатолий Кулаков" Это точно так же библиотека для парсинга коммальной строки, но как вы, скорее всего, ожидали, построена она полностью на различных спанах, мемориях, Zero Dependency, Zero Overhead, Zero Reflection, Zero Location, естественно, аут совместимая и самое прекрасное, что она поддерживается с помощью C-Sharp Source Генераторов. +2508.28 2524.44 "Анатолий Кулаков" То есть вам не нужно в рантайме, рефлекшеном собирать какие-то там атрибутики, запустить какие-то делегатики, все это Source Генератор вам нагенерирует и оптимальный парсер на спанах быстренько пройдется по всем вашим аргументам. +2524.44 2540.52 "Анатолий Кулаков" Судя по бичмаркам, эта библиотека рвет просто на несколько порядков все ближайших конкурентов, ну потому что все ближайшие конкуренты работают через рефлекшен, как вы понимаете, это как драться с C-Sharp Генератором против рефлекшенов. +2540.52 2546.96 "Анатолий Кулаков" Там где-то 0 сражается с 20000 наносекунд, что-то такое получается. +2546.96 2556.24 "Анатолий Кулаков" Поэтому, может быть, если вам нужно прям очень миллиардное количество аргументов парсить, очень часто, очень много, очень быстро, возможно, вам стоит взглянуть на эту библиотеку. +2556.24 2565.48 "Анатолий Кулаков" Если же у вас стандартная библиотечка, то, скорее всего, все вот эти оптимизации, все эти подуги, они того не стоят и микрософтовский стандарт, как обычно, всех заборит, всех зарулит. +2565.48 2580.76 "Анатолий Кулаков" В общем, такая прекрасная библиотека, не знаю, почему про нее молчат твиттеры, почему не выходят статьи одна за другой, в общем, я достал ее просто из гитхаба, из стандартной документации, и мне кажется, что это довольно бигдил. +2580.76 2589.04 "Анатолий Кулаков" В общем, тем более в наш век возвращения консолей, возвращения текстовых интерфейсов, мы получаем хороший командлайн парсер, так что будем ждать релиза. +2589.04 2604.92 "Игорь Лабутин" Ну, из того, что я слышал, что он действительно хороший, но он какой-то… Давай так, я читал отдельные отзывы, что он ну супер навороченный, слишком навороченный, и знаешь как это? +2604.92 2612.28 "Игорь Лабутин" Tool должен позволять делать основные вещи просто, да, и позволять делать сложные вещи, возможно, сложно. +2612.28 2615.52 "Игорь Лабутин" А эта штука позволяет делать любые вещи, но всегда сложно. +2615.52 2636.44 "Игорь Лабутин" Может быть, поэтому такие отзывы, типа он какой-то очень переусложненный, ну, как ты сам видел, да, всякие там и… Короче, и так, и эдак можно аргументы, и директивы вот эти вот, и completion туда же, в общем, все вместе, может быть, создает впечатление, ну, довольно сложного порога входа, так скажем. +2636.44 2645.88 "Анатолий Кулаков" Ну, ты же видишь, ты же это все получаешь из коробки, то есть в коде ты это никак не настраиваешь и нигде это не видишь, то есть нет никакого порога входа, ты подключил и все, и все это прямо из коробки у тебя +2645.88 2646.88 "Игорь Лабутин" есть. +2646.88 2668.72 "Игорь Лабутин" Не, ну подожди, тебе же все равно нужно задефайнить все эти команды, подкоманды, аргументы, типы, и вот насколько я вижу, по крайней мере по примерам, синтакси, ну, он позволяет все это сделать, но я помню, что вот какую-то библиотечку я использовал до этого, она очень попроще гораздо выглядит с точки зрения конфигурации в коде. +2668.72 2677.96 "Игорь Лабутин" Она не поддерживает, конечно, много чего, но зато и конфигурация проще, но вопрос, нужна ли поддержка всего вот этого огромного количества функций большинству приложений, непонятно. +2677.96 2690.36 "Анатолий Кулаков" Да, может быть, вот упростить есть куда, то есть я бы не сказал, что она очень сложная, то есть вполне читабельная, вполне юзабельная, но есть примеры, куда можно упростить, да. +2690.36 2710.20 "Анатолий Кулаков" И существуют уже обертки от этой библиотеки, которая позволяет вот синтакси сделать максимально простым, может быть, как раз эти обертки в самом начале и будут жить, но мне кажется, они продержатся недолго, буквально, я думаю, пару лет и там допилят абсолютно все, чтобы это было очень лаконично, очень прекрасно, в общем, как pull-реквесты обычных пользователей любят. +2710.20 2728.16 "Анатолий Кулаков" То есть это же все в GitHub, это же все open-source, поэтому приходят люди, contribute, упрощают синтаксис, делают так, чтобы общаться с ним было легче, до первого релиза самая главная задача была поддержать как можно больше тех ожиданий, которые пользователи уже привыкли на разных платформах иметь. +2728.16 2735.20 "Анатолий Кулаков" А вот эти удобства, они очень легко допиливаются, там для них остался буквально полшага, не сказать, что там очень далеко. +2735.20 2744.88 "Игорь Лабутин" Ну посмотрим-посмотрим, поглядим, может найдутся какие-то отзывы, статьи и так далее, пока действительно не находилось. +2744.88 2775.60 "Игорь Лабутин" Давайте дальше, дальше у нас есть довольно интересная статья, которая редко следует на этот мир, потому что это статья про CVE, они же утечки, которые приводят, точнее, проблемы, которые приводят к уязвимостям и утечкам, так скажем, vulnerabilities and exposures, и ну мало ли каких CVE, Microsoft каждый, что у нас там, вторник, патч тьюздай у них или не помню, какой-то один из дней у них. +2775.60 2776.60 "Игорь Лабутин" Типа да, каждую неделю. +2776.60 2969.28 "Игорь Лабутин" Каждую неделю выходят патчи, этих там CVE закрывают вероятно ни одну и ни две, но здесь она была особенная, потому что на каждой CVE получают некоторую оценку, насколько она важная, от нуля до десяти, так вот эта получила оценку 9.9, это наивысшая оценка, когда-либо получена какой-либо CVE в Microsoft мире, для Дотонета по крайней мере, ну и даже если не для Дотонета, 9.9, вообще говоря, очень высокая оценка, и надо бы разобраться, что это такое, а это проблема в S/Panel 8, и она заключается в том, что S/Panel Core современных версий, ну и не только современных, мы про это поговорим, он на самом деле довольно-таки неправильно интерпретировал, ну как не неправильно, неконсистентно интерпретировал некоторые что-то по запросы, так что можно было подсунуть S/Panel Core выполнить два запроса вместо одного, вы так хитро посылали запрос, что S/Panel Core считал, что вы послали два запроса, и это позволяло обходить некоторые, так скажем, заградительные барьеры, которые, возможно, выстроены перед вашим приложением, называется это все Request Smuggling, оно же скрытие, оно же контрабанда, ну я буду называть это скрытием, штука позволяет как раз-таки специальным образом сформулировав запрос скрыть в один запрос внутри другого, и само по себе это не то, что уязвимость, ну скажите, в чем проблема, так как S/Panel Core предназначили выполнение запросов, поэтому, ну, получит два запроса, выполнит два запроса, что мешало бы его послать, и так, но проблема в том, что у вас, возможно, есть какие-то меры предотвращения каких-то неверных запросов, чтобы они не приходили даже в ваше приложение, а здесь получается, что он дойдет до вашего приложения, такой запрос, ну и там понятно, что из-за того, что вы получаете неожиданно для себя запрос, могут быть всякие разные интересные последствия, типа там логина или чтение данных другого пользователя, какие-нибудь внутренние вызовы можно сделать, которые, вообще говоря, обычно нельзя делать, ну и так далее, как это все работает, значит, как я сказал, само S/Panel Core, он вообще говоря, ну, предназначен для того, чтобы выполнять запросы, поэтому казалось бы, какая разница, сколько запросов вы ему послали, но проблема возникает в том случае, если вы перед вашим приложением используете какой-нибудь прокси, а как правило, он есть, это либо балансер, либо еще что-нибудь, ну т.е. какой-нибудь Nginx, либо кто-нибудь стоит обычно перед вашим приложением, либо распределяет запросы, либо делает какие-то дополнительные проверки, либо, например, предназначен для того, чтобы скрыть часть каких-нибудь endpoints, т.е. допустим, вы публикуете какие-то внутренние endpoints, которые вы не хотите выставлять наружу в интернет, и они видны только в вашей внутренней сети, а через Nginx они запрещены, и Nginx не пустит их к вашему приложению, или, например, так закрываете какой-нибудь, не знаю, там специальные endpoints, которые там для метрика или еще для чего-нибудь, которые тоже не хочется выставлять наружу в интернет. +2969.28 2978.64 "Игорь Лабутин" Нормальный способ, почему нет, но получается, что запрос, который приходит к вашему приложению, проходит через два сервера. +2978.64 2989.12 "Игорь Лабутин" Один сервер – это ваш Nginx, там proxy-сервер, reverse-прокси, application gateway, как хотите, называйте, он может выполнять разные роли, а второй – это ваше S/4HANA приложение. +2989.12 3010.84 "Игорь Лабутин" И вот если некоторые специальным образом сконструированные запросы чуть-чуть по-разному обрабатываются этими двумя видами серверов, а, как правило, это два разных типа, вида, вообще иногда технологии, то может случиться так, что первый сервер, соответственно, считает это одним запросом, а ваше приложение это будет считать двумя запросами. +3010.84 3017.52 "Игорь Лабутин" Ну как, звучит довольно-таки странно, поэтому давайте разбираться. +3017.52 3022.16 "Игорь Лабутин" Значит, что происходит прямо на примере? +3022.16 3041.96 "Игорь Лабутин" То есть на примере мы берем и, например, закидываем какой-нибудь пост-запрос, у которого должно быть боди, понятное дело, и если у вас есть боди в запросе, то мы, например, можем, ну, должны указать ему контент-ленгт, чтобы сервер, вообще говоря, знал, сколько там этого боди читать. +3041.96 3048.40 "Игорь Лабутин" И, вообще говоря, вы можете указать два контент-ленгта подряд, два заголовка контент-ленгта. +3048.40 3054.12 "Игорь Лабутин" И вот тут возникнет вопрос, какой заголовок сервер будет брать, первый или последний. +3054.12 3085.56 "Игорь Лабутин" И если вдруг так получается, что у вас, ваше приложение и прокси-сервер используют разный подход к этому, то есть, например, прокси-сервер берет последний заголовок, а ваше приложение берет первый заголовок, то вы можете сделать следующую конструкцию, вы делаете пост-запрос, в качестве первого заголовка контент-ленгта вы указываете, допустим, ну вот у меня в примере, который в статье, указываете 9, дальше вы указываете контент-ленгт больше, там 200 с лишним байт, после чего начинается боди, как будто бы первого запроса. +3085.56 3103.38 "Игорь Лабутин" Там написано, ну вот в примере просто this=that, то есть какой-то боди, неважно, это ровно 9 символов, а дальше продолжается текст без каких-либо переносов строк, вы там снова пишите post/ там какой-нибудь vulnerable endpoint, ну в общем, самый обыкновенный пост-запрос. +3103.38 3129.64 "Игорь Лабутин" Если прокси-сервер смотрит на последний заголовок контент-ленгт, он вот весь этот this=that, post, vulnerable endpoint считает единым боди и просто перенаправляет его в ваше приложение, а ваше приложение смотрит на первый контент-ленгт, смотрит, ага, оно 9, читает его как this=that, дочитывает до конца, дальше смотрит, что там еще осталось в буфере, там написано post/ отлично, следующий запрос давай выполнять как второй запрос. +3129.64 3144.68 "Игорь Лабутин" Таким образом получается, что вы внутри одного запроса скрыли другой и к нему не применялись никакие правила, которые, возможно, ваш прокси-сервер Nginx должен применить, например, не пустить какой-либо URL к вашему приложению. +3144.68 3176.64 "Игорь Лабутин" Вот это такой довольно простой пример, он не совсем относится к этой текущей CVE, но он довольно характерно и легко показывает, как оно работает, но возникает вопрос, а верно ли, что все эти уязвимости появляются только если у вас есть прокси перед вашим сервером, который как-то по-другому интерпретирует http протокол или запросы? +3176.64 3212.52 "Игорь Лабутин" На самом деле не обязательно, на самом деле, если вы напрямую используете body, то есть если вы, например, читаете его через http-request-body или http-request-body-reader, то в принципе вы тоже в каком-то смысле, может быть, подвержены такой атаке и как-то не очень аккуратно прочитать body, потому что читать-то вы его должны в соответствии с тем, что указано в заголовке content-length, например, и тогда возникает та же проблема, как вы его будете интерпретировать, как первый, короткий или как последний, длинный, в общем возникает вопрос, много вопросов к тому, насколько это безопасно. +3212.52 3310.00 "Игорь Лабутин" Но давайте вернемся, собственно, к этому CVE, который получил оценку 9.9, это не совсем про content-length, это про другой немножко заголовок, называется transfer-encoding, вы наверняка видели эту штуку, transfer-encoding-chunked, это специальный такой заголовок, который говорит следующее, мы не знаем, то есть клиент, когда посылает такой запрос, он понятия не имеет, сколько займет body, может 5 байт, может 20 мегабайт, мы не знаем, но мы знаем, что есть разные кусочки и мы посылаем кусочками, передавая размер каждого кусочка, вот, то есть мы сериализуем какой-то наш payload в буфер, засылаем его на сервер, передавая размер этого кусочка, потом снова сериализуем буфер, снова передаем, и так мы это делаем до тех пор, пока мы не пошлем специальный запрос, в котором будет написано, что посылается 0 байт, это будет означать все, мы точно все передали, поскольку протокол TPM, он у нас текстовый, версии 1.0.1.1, то надо же как-то все эти чанки отделять друг от друга, соответственно, там делается простая конструкция, то есть каждый чанк это заголовок и body, заголовок это 16-ти ричный размер чанка в байтах, потом backslash r, backslash n, перевод строки и возврат каретки, и после этого chunk body, нужное количество байт, потом снова перевод строки, backslash r, backslash n, ну и дальше продолжается. +3310.00 3315.96 "Игорь Лабутин" Как только мы послали пустой чанк, соответственно, все, мы обозначаем, что это конец реквеста, замечательно. +3315.96 3340.96 "Игорь Лабутин" Дальше, в какой-то момент разработчики стендарта http 1.1 протокола решили, а наверное вдруг мы в середине посылки вот этих вот чанков решим, что нам нужно передать какие-нибудь метаданные, которые к body не относятся, но отлично, у нас же есть заголовок каждого чанка, давайте мы в заголовок попытаемся передавать метаданные. +3340.96 3346.24 "Игорь Лабутин" Это называется chunk extensions, и это позволяет передать любые данные внутри этого заголовка. +3346.24 3368.60 "Игорь Лабутин" Делается это так, что мы после длины, напоминаю, это просто 16-ти ричное число, ставим точку с запятой и любые key-value пары пишем туда, типа там k=value, k это точка с запятой, k=value, вот это все, пока мы не доберемся до перевода строки, потом так же начинается body нужного размера указанного. +3368.60 3391.84 "Игорь Лабутин" И проблема с этими экстендженами заключается в том, что в стандарт они конечно вошли, но по факту их никто никогда никак не использует, клиенты их практически никогда не шлют, сервера всегда их игнорируют, и возникает вопрос, а с чего бы они тогда были бы проблемой в дотнете? +3391.84 3410.36 "Игорь Лабутин" Проблема возникает в том, именно как дотнет их игнорирует, то есть короче придумали стандарт, все решили, что стандарт стандартом, но мы эту штуку использовать не будем, насколько я понял, статью сейчас нет ни одного практического примера, где бы эти чанки использовались, но все сервера вынуждены написать код, который будет их игнорировать, и вот в этом коде и есть ошибка. +3410.36 3416.16 "Игорь Лабутин" Значит, как это все работает? +3416.16 3447.08 "Игорь Лабутин" Смотрите, поскольку мы на сервере считаем, что ничего делать не надо с чанком, нам нужно просто по сути пропустить эту штуку, то есть мы прочитали длину 16-тиличную, тут вопросов нет, дальше мы прочитали точку с запятой, поняли, что ага, у нас есть некоторый экстенджер в этом заголовке, который нужно пропустить, ну отлично, значит нам нужно найти конец строки, те самые \r\n, и все, мы его пропустили. +3447.08 3448.08 "Игорь Лабутин" Как делал EsperantCore? +3448.08 3636.60 "Игорь Лабутин" EsperantCore говорил, ну окей, если мы нашли точку с запятой в заголовке чанка, то мы будем искать \r, а потом проверим, что после \r есть символ \n, ну \r\n, отлично, пропустили все, что между ними, все замечательно, и большинство серверов, собственно, так и делают, но вопрос, как они это делают, происходит это примерно следующим образом, значит, согласно RFC, в котором даже написано, как это по сути нужно делать, как искать конец строки, нельзя использовать только \r или только \r как валидный конец строки, нужно именно пару, и эти символы нигде не разрешены больше в заголовках, то есть, по хорошему, если вы как сервер, как автор сервера, находите заголовок чанка, в котором написано, что там длина, точка с запятой, какой-то текст \n, например, и дальше снова какой-то текст, то это вообще говоря невалидный запрос, на него нужно ответить все плохо, но большинство серверов, или, так скажем, большинство кода в интернете написано примерно следующим образом, когда речь заходит о протоколе HTTP, сервера должны быть, поскольку протокол текстовый, максимально, ну как сказать, лояльными и гибкими к тому, что приходит, поэтому довольно много серверов считают, что \n, обычный, это в общем-то вполне достаточно для завершения заголовка, ну и тогда понятно, что происходит, то есть мы формируем очень специальный реквест, в котором делаем в чанк-хедере длину его, точка с запятой, дальше некоторый спецтекст, где будет \n, и дальше снова какой-то текст, и дальше \r, \n, ну и в общем все как обычно, в итоге, если, соответственно, мы прервемся на \n и посчитаем, что хедер закончился, то весь остальной текст будет воспринят как body, и если мы правильно подберем содержимое этого body так, чтобы количество этих \r\n было таково, что нам будет казаться, что весь остальной body это просто набор чанков нужной длины, внутри которых зашит запрос, то, ну, будет и окей, вот, а если мы, если при этом наш какой-нибудь прокси-сервер вот этот вот \n или еще что-то пропустит как валидный, то, соответственно, до sp.net.core долетит полноценный запрос, который sp.net.core распарсит как будто два разных запроса, потому что чанки правильно расположатся из-за того, что он интерпретирует \n по-другому, и в итоге выполнит. +3636.60 3660.04 "Игорь Лабутин" Забавный факт состоит в том, что такой же CVE был в питоне, в net, это джавский сервер, и там питоновский получился, соответственно, средний уровень, а в net это вообще сказали, да, low, проблема, когда-нибудь может быть пофиксили, не помню, пофиксили или нет, но Microsoft что-то очень забеспокоился и получилось 9.9, суперhigh, суперважно. +3660.04 3663.80 "Игорь Лабутин" В джаве и в питоне более расслабленно к этому относятся. +3663.80 3664.80 "Игорь Лабутин" Как пофиксили? +3664.80 3701.36 "Игорь Лабутин" Пофиксили, на самом деле, довольно просто, значит, мы теперь в sp.net.core не ищем отдельно \r и проверяем отдельно \n, проверяем, и теперь делается ровно так, как должно быть по rfc, значит, если строчка, вот этот вот chunk header не заканчивается на строка \r\n, то Kestrel просто кинет прямо kestrel-b-cdp-request-exception и вернет 400 со словами "все плохо, нельзя такой запрос предпринимать" и даже не будет пытаться распарсить что там дальше внутри. +3701.36 3729.68 "Игорь Лабутин" Единственный способ это для себя исправить и закрыть это cve, это проапгрейдиться, cve при этом есть во всех версиях net, просто во всех, и в фреймворке, и в старых спнетах, и так далее, вот, проапгрейдить, ну, как это, фикс будет выпущен только для поддерживаемых спнет-корп, это если вы живете на каком-нибудь стареньком, то все плохо для вас. +3729.68 3742.40 "Игорь Лабутин" Дальше вы можете сказать, ну окей, давайте мы поставим перед нашим приложением какую-нибудь проксю, которая будет внимательно и правильно парсить такие заголовки, и, значит, сама будет отвечать 400, если все плохо. +3742.40 3769.64 "Игорь Лабутин" Проблема в том, что таких проксей, по мнению, по крайней мере, андрюк лока практически нет, единственный, про кого ему известно, что он точно сказал, что мы пропатчились это azureappservices, то есть если вы живете в ажуре, нормально все, но, например, is прекрасно пропускает такие запросы и не может быть использован как прокся, которая вам, или, ну, реверс прокси, да, который вас защитит от такой штуки. +3769.64 3796.52 "Игорь Лабутин" Хорошая новость заключается в том, что это только для HTTP 1.0 и 1.1, HTTP 2.0 и 3.0 — это уже бинарные протоколы, там такого и проблемы нету, и поэтому, если вы можете переключиться на HTTP 2.0 или HTTP 3.0, хотя если вы можете на HTTP 3.0, наверное, вы бы не сидели на старых версиях, это нормальный способ с этим поработать и защититься от этой ЦВИ. +3796.52 3815.00 "Игорь Лабутин" Вот примерно такая история, мне кажется, ну, технические все эти детали про то, как там заголовки, кто куда, можно посмотреть в статье, там красивые картинки, которые как раз показывают, как интерпретируются боди цветами, какие части боди оказываются хедерами, какие части боди оказываются, действительно, боди ученков. +3815.00 3839.48 "Игорь Лабутин" У Андрю Лока, как обычно, все в красивых цветах картинках и все понятно, вот, но мне здесь кажется интересным тот факт, что есть кусочек стандарта, который никто не использует, но все обязаны писать код, который игнорируют, экстенджен, который придумали в этом стандарте, и в коде, который игнорирует экстенджен, который никто не использует, находятся ошибки, которые приводят к уязвимости. +3839.48 3840.48 "Игорь Лабутин" Мне кажется, это прикольно. +3840.48 3848.40 "Анатолий Кулаков" Да, да, необычно, по-моему, секьюрити баги так и находятся в каких-нибудь неподдержанных библиотеках, ненужных заголовках, в каких-нибудь версиях. +3848.40 3860.52 "Анатолий Кулаков" Вспомни, вот, самый громкий джавовский баг, когда в лог-фонете нашли в каком-то экстенджене, что он может выполнять код просто из-за того, что логи пишут с определенными флажками. +3860.52 3867.68 "Анатолий Кулаков" Никто его там никогда не использовал, никто никому не нужен, чтобы логи умели выполнять код, но зато все были подвержены этой уязвимости. +3867.68 3870.80 "Игорь Лабутин" Да нет, я думаю, что наверняка использовали, просто никто это не думал. +3870.80 3873.28 "Игорь Лабутин" Когда это писали, никто не думал, что это будет прям такая супер уязвимость. +3873.28 3874.28 "Игорь Лабутин" Возможно. +3874.28 3875.28 "Игорь Лабутин" Не знаю. +3875.28 3876.28 "Игорь Лабутин" Ну, как-то. +3876.28 3885.36 "Игорь Лабутин" Возможно, когда ты это делаешь на десктопе, это не так страшно и ужасно, например, а когда это добралось до интернетов и серверов, все уже забыли, что там так можно. +3885.36 3889.52 "Анатолий Кулаков" Поэтому там никто и не использовал, потому что никому это не надо было. +3889.52 3890.52 "Анатолий Кулаков" Ну, в общем, вот. +3890.52 3897.24 "Анатолий Кулаков" Слушай, а как ты не видел ли в статье, насколько пострадала ли перформанс от того, что они изменили вот этот парсинг? +3897.24 3902.08 "Игорь Лабутин" Слушай, да нет, какая разница, то есть сейчас он ищет просто бэкслэш. +3902.08 3907.48 "Игорь Лабутин" По сути, там поиск был одного символа, да, и потом проверка следующего. +3907.48 3915.56 "Игорь Лабутин" Сейчас мы ищем, по сути, точно так же, можно искать один символ, и если следующий не подходит, просто сразу кидать exception. +3915.56 3916.56 "Анатолий Кулаков" Все. +3916.56 3922.44 "Анатолий Кулаков" Ну, просто если это уязвимость как бы во всех языках, то скорее всего, может быть, были какие-то причины, почему не делали правильно. +3922.44 3924.96 "Анатолий Кулаков" Я думаю, что причины перформанса, прежде всего, могли их подвигнуть +3924.96 3925.96 "Игорь Лабутин" на это. +3925.96 3926.96 "Игорь Лабутин" Возможно, возможно. +3926.96 3933.12 "Игорь Лабутин" Либо, когда ты делаешь, ты просто смотришь, например, как это сделано где-нибудь еще, и делаешь по аналогии. +3933.12 3935.88 "Игорь Лабутин" Блин, мне надо пропускать эти заголовки. +3935.88 3938.88 "Игорь Лабутин" Давай глянем, как это сделано в каком-нибудь популярном сервере и сделаем так же. +3938.88 3941.20 "Игорь Лабутин" Они же, наверное, не дураки, написали правильно. +3941.20 3943.88 "Анатолий Кулаков" Да, да, вполне может быть, вполне может быть. +3943.88 3945.88 "Анатолий Кулаков" Хорошо, пойдем к следующей теме. +3945.88 3949.80 "Анатолий Кулаков" Мы не хотим отставать от трендов, поэтому поговорим про ИИшку. +3949.80 3954.32 "Анатолий Кулаков" Мы все еще не скатились в подкаст про ИИ, но немножко затрагивать нужно. +3954.32 3957.96 "Анатолий Кулаков" Особенно то, что касается C#, тут нельзя пройти мимо. +3957.96 3965.80 "Анатолий Кулаков" Поэтому хочется с вами проговорить про модель контекст-портакол и, в частности, про его поддержку в C#. +3965.80 3970.40 "Анатолий Кулаков" Давайте подумаем вообще, что это такое и начнем из далека, для чего это вообще нужно. +3970.40 3974.68 "Анатолий Кулаков" Ну, все, наверное, из нас уже, по крайней мере, слышали про ИИшку. +3974.68 3976.56 "Анатолий Кулаков" Многие из нас уже пробовали про ИИшку. +3976.56 3990.04 "Анатолий Кулаков" И разработчиков она касается прям непосредственно, потому что есть куча толзов, которые за вас пишут код, за вас ревьювят код, советуют вам какие-то архитектурные всякие решения принимать. +3990.04 3992.72 "Анатолий Кулаков" В общем, наверняка многие разработчики с этим сталкивались. +3992.72 3998.08 "Анатолий Кулаков" Но при всех прелестях вот этих текстовых агентов у них есть фундаментальные проблемы. +3998.08 4014.32 "Анатолий Кулаков" Например, все базы данных, то есть все знания этих агентов, на которые они обучались, они обычно за какое-то фиксированное время, то есть на тот момент, когда вы их используете, их все знания устарели, потому что они обучаются на какой-то конкретный срок. +4014.32 4025.28 "Анатолий Кулаков" Дальше, вот эти агенты, вот эти модели, они очень хорошо для того, чтобы фантазировать, для того, чтобы генерировать контент. +4025.28 4026.28 "Анатолий Кулаков" В общем, они такие гуманитарии. +4026.28 4035.92 "Анатолий Кулаков" Но как только вы от них попросите каких-то конкретных вещей, например, какую-то четкую вычисление, четкие математические какие-то действия, вот тут вас может ожидать облом. +4035.92 4045.60 "Анатолий Кулаков" То есть они хорошо сопоставляют по шаблонам, они хорошо рисуют, они хорошо генерят, но выполнять четкие действия они уже могут с трудом, вот такой узкоспециализированный какой-то домен. +4045.60 4051.88 "Анатолий Кулаков" Далее, у них, у этих моделей обычно не хватает контекста для решения каких-то специализированных задач. +4051.88 4073.94 "Анатолий Кулаков" Например, если вы хотите что-то внутри своего интерпрайза порешать, посчитать, посмотреть, то обычно у этих моделей, внешних моделей не хватает контекста, у них нет доступа к вашим персональным репозиториям, базам данных, какой-нибудь может быть персональным данным, там, то есть информация скрытая с секьюрити отделом, в общем, все это у общепризнанных моделей тоже не хватает. +4073.94 4081.30 "Анатолий Кулаков" Также без специализированных тулзов мы от модели не можем получить какого-то предсказуемого поведения, которое мы можем повторить. +4081.30 4088.00 "Анатолий Кулаков" Что, например, необходимо для тестирования, для стабильного тестирования воспроизведения какого-то стандартного строгой функциональности. +4088.00 4099.36 "Анатолий Кулаков" В общем, вот такие вот всякие ограничения, фундаментальные проблемы, они в моделях вряд ли решатся, то есть для этого будут необходимы какие-то серьезные переделки. +4099.36 4103.92 "Анатолий Кулаков" Вот, на данный момент существует механизм, как можно это решить. +4103.92 4112.20 "Анатолий Кулаков" Этот механизм называется как раз и агентов, то есть это специализированные какие-то инструменты, которые позволяют делать какие-то конкретные действия. +4112.20 4138.28 "Анатолий Кулаков" Эти действия повторяемые, то есть они четко предсказуемы, организуемые потому, что как раз вот эти агенты внутри себя чаще всего не используют каких-то генерируемых данных или каких-нибудь ИИ-моделей, они сосредотачиваются на одной конкретной маленькой функциональности, но делают это хорошо, делают это повторяемо и могут делать это, избегая всех тех проблем, которые были раньше. +4138.28 4142.40 "Анатолий Кулаков" Вот эти агенты, им необходимо как-то с этой ИИ-моделью взаимодействовать. +4142.40 4151.88 "Анатолий Кулаков" Вот этот гуманитарный генератор, который генерирует вам идеи и чего делает, он должен каким-то образом общаться с вот этими маленькими рабочими, маленькими агентами. +4151.88 4158.64 "Анатолий Кулаков" И вот общаться он с ними может с помощью MCP-протокола, так называемого модель-контекст-протокол. +4158.64 4161.92 "Анатолий Кулаков" Вот давайте про него сейчас подробнее поговорим. +4161.92 4174.40 "Анатолий Кулаков" Вообще можно воспринимать вот этот модель-контекст-протокол и вообще всю эту взаимосвязь между агентами и своими ИИ-моделями, как некую новую платформу для разработки. +4174.40 4187.12 "Анатолий Кулаков" Ну, мы все с вами уже давно понимаем, что у нас есть консольные приложения для того, чтобы написать какое-то новое приложение, есть веб-аппликейшн-приложение, есть десктоп-приложение. +4187.12 4198.52 "Анатолий Кулаков" Ну так вот у нас в принципе получается такое приложение типа плагина для ИИшки, которое расширяет ее функциональность, используя специальный протокол, модель-контекст-протокол. +4198.52 4201.60 "Анатолий Кулаков" В общем, что это такое? +4201.60 4203.00 "Анатолий Кулаков" Это вестибо-протокол. +4203.00 4212.20 "Анатолий Кулаков" Он open-source и он признан для того, чтобы соединить приложение с ИИшкой с какими-то внешними системами. +4212.20 4219.64 "Анатолий Кулаков" Оригинально он был разработан компанией Antropic и зарелижен в 24-м году, в ноябре 24-го года. +4219.64 4229.72 "Анатолий Кулаков" Сейчас это глобальный стандарт, его поддерживают практически все модели, которые выходят, в общем все инструменты, все IDE-шки, в общем это стало таким довольно большим стандартом. +4229.72 4273.54 "Анатолий Кулаков" С помощью него ИИшки, такие как Cloud или ChatGPT, могут коннектиться к различным источникам данных, например к файлам, базам данных, пастгре, Яндекс.Диску, Google Календарю, короче вообще абсолютно куда угодно, или могут, например, использовать различные инструменты, такие как поисковые движки, калькуляторы, тот же самый GIT, Telegram, Яндекс.Карты, в общем любые инструменты, которые только возможны, могут даже использовать какие-то устройства, например подсоединиться к умному дому, или напечатать на 3D принтере ту модель, которую они только что сгенерили в трехмерном пространстве, в общем все это тоже могут делать. +4273.54 4284.04 "Анатолий Кулаков" И так же точно они могут подключаться к каким-нибудь, допустим внутрикорпоративным сетям и доставать те данные, которые, допустим, общей модели, были недоступны. +4284.04 4311.32 "Анатолий Кулаков" Сам MCP протокол, он вдохновлялся Language Server протоколом, то есть это LSP, с помощью которого у нас изначально Visual Studio Code начинала взаимодействовать с различными LSP серверами, которые предоставляли там знания о языках, об интеллисенсии, о всем остальном, а потом это точно так же LSP стал стандартом между редактором и контекстной информацией конкретного формата, между языками, интеллисенсами и тому подобное. +4311.32 4315.80 "Анатолий Кулаков" Итак, что же включается у нас в модель Context Protocol? +4315.80 4319.64 "Анатолий Кулаков" В общем случае он подразумевает под собой несколько вещей. +4319.64 4321.16 "Анатолий Кулаков" Во-первых, это MCP-спецификация. +4321.16 4335.44 "Анатолий Кулаков" Это MCP-спецификация, которая описывает о том, как правильно реализовать клиентов и серверов, и какой протокол между ними должен быть, что в него входит, как они обмениваются, и все в этом духе. +4335.44 4342.04 "Анатолий Кулаков" Так же подразумевается MCP-SDK - это специальный набор библиотек для различных языков программирования. +4342.04 4345.20 "Анатолий Кулаков" Разумеется, для C# тоже есть. +4345.20 4349.36 "Анатолий Кулаков" MCP-Development Tools - это специальные инструменты для разработчиков. +4349.36 4355.00 "Анатолий Кулаков" Наверное, самый значимый из них - это MCP-Инспектор, который позволяет вам отлаживать ваши MCP-сервера. +4355.00 4362.28 "Анатолий Кулаков" И так же точно MCP подразумевает некий репозиторий с референсной имплементацией MCP-сервера. +4362.28 4365.56 "Анатолий Кулаков" Она написана на TypeScript и Python, и поэтому нам не особо интересно. +4365.56 4368.32 "Анатолий Кулаков" Разберемся с основными концепциями MCP. +4368.32 4372.88 "Анатолий Кулаков" Что же это такое, какие там взаимодействующие системы есть и вообще, что там за такая архитектура. +4372.88 4375.60 "Анатолий Кулаков" Ну, архитектура там, прежде всего, клиент-серверная. +4375.60 4382.36 "Анатолий Кулаков" У нас есть три главных компонента - это MCP-хост, MCP-сервер и MCP-клиент. +4382.36 4386.20 "Анатолий Кулаков" Хост - это то место, где как раз хостится ишка. +4386.20 4389.28 "Анатолий Кулаков" То есть, это приложение с моделькой. +4389.28 4393.72 "Анатолий Кулаков" И хост управляет как раз различными MCP-клиентами. +4393.72 4400.68 "Анатолий Кулаков" MCP-сервер предоставляет какой-то дополнительный контекст для MCP-клиента. +4400.68 4406.88 "Анатолий Кулаков" То есть, это как раз то, где ишки нет, а там, где у нас обитают или какие-то данные, или какие-то конкретные инструменты. +4406.88 4410.32 "Анатолий Кулаков" И вот, чтобы соединить хост и сервер, у нас есть клиент. +4410.32 4416.76 "Анатолий Кулаков" Клиент как раз управляет различными соединениями между MCP-сервером и MCP-хостом. +4416.76 4425.20 "Анатолий Кулаков" Обменивается между ними командами, распространяет между ними какой-то контекст и поддерживает как раз связь. +4425.20 4433.38 "Анатолий Кулаков" Например, если мы берем Visual Studio, то Visual Studio является MCP-хостом, потому что внутри нее живет какая-то моделька. +4433.38 4440.86 "Анатолий Кулаков" Visual Studio с помощью MCP-клиента может приконектиться к какому-нибудь MCP-серверу. +4440.86 4444.20 "Анатолий Кулаков" Например, существует такой сервер, как File System Server. +4444.20 4449.64 "Анатолий Кулаков" Это специальный сервер, который предоставляет доступ к некому ресурсу, как вы, наверное, догадались, к файловой системе компьютера. +4449.64 4456.56 "Анатолий Кулаков" И, соответственно, теперь Visual Studio может управлять файлами с помощью этого MCP-сервера. +4456.56 4460.00 "Анатолий Кулаков" MCP-сервера бывают как локальные, так и удаленные. +4460.00 4461.66 "Анатолий Кулаков" Зависит это от транспорта. +4461.66 4472.04 "Анатолий Кулаков" У транспорт под капотом, то есть для обмена между сервером и хостом, используется JSON-RPC, версии второй. +4472.04 4477.72 "Анатолий Кулаков" Вообще MCP поддерживает два вида транспорта. +4477.72 4484.48 "Анатолий Кулаков" Во-первых, это STDIO, то есть это input-output, который у нас в консольке есть, стандартный input, стандартный output. +4484.48 4489.60 "Анатолий Кулаков" Он используется для локальных процессов и утверждается, что он оптимальный по производительности. +4489.60 4498.00 "Анатолий Кулаков" Именно когда у вас MCP-сервер и MCP-хост находятся на одном процессе, используется он для того, чтобы как можно быстрее выполнить команду и пообмениваться данными. +4498.00 4501.52 "Анатолий Кулаков" И второй транспорт – это, естественно, HTTP, куда же без него. +4501.52 4508.12 "Анатолий Кулаков" В общем, HTTP-транспорт позволяет вам, естественно, удаленно любые сервера вызывать, которые могут находиться далеко. +4508.12 4517.04 "Анатолий Кулаков" Из интересного – он поддерживает сервер send-евенты, то есть вы можете присылать некие события, а не только отвечать на запросы. +4517.04 4521.24 "Анатолий Кулаков" А также он поддерживает стандартную HTTP-аутентификацию. +4521.24 4525.44 "Анатолий Кулаков" Рекомендуется использовать OAuth для того, чтобы аутентифицироваться между сервером и хостом. +4525.44 4537.52 "Анатолий Кулаков" Сервер и клиент, соответственно, могут обмениваться запросами друг с другом и слать нотификации. +4537.52 4541.96 "Анатолий Кулаков" Нотификации могут пригодиться для каких-то real-time обновлений. +4541.96 4548.44 "Анатолий Кулаков" Например, если у вас в динамике появился какой-то новый тул, то вы можете об этом сообщить хосту. +4548.44 4558.32 "Анатолий Кулаков" Или, например, если у вас идет какой-то долгий процесс, вы что-то считаете, что-то индексируете, то вы вполне можете хосту сообщать о прогресс-баре, то есть о том, сколько вам там осталось доделать. +4558.32 4562.84 "Анатолий Кулаков" То есть это для таких длинных операций вполне хорошо и интересно применимо. +4562.84 4565.72 "Анатолий Кулаков" Теперь поговорим про возможности этих сторон. +4565.72 4568.52 "Анатолий Кулаков" Возможности называются примитивы почему-то. +4568.52 4576.20 "Анатолий Кулаков" Не знаю, почему такие же слова подбирали, но вполне логичнее было бы обозвать какими-то фичами или что-то в этом духе. +4576.20 4583.84 "Анатолий Кулаков" Ну, допустим, у нас у хоста есть три таких вот примитива и у сервера есть три примитива. +4583.84 4591.44 "Анатолий Кулаков" То есть примитива – это такой способ обмена какой-то расшаренной информацией, контекстуальной информацией. +4591.44 4594.64 "Анатолий Кулаков" И также посмотрим, у сервера три примитива. +4594.64 4597.92 "Анатолий Кулаков" Это Tools, Resource и Prompts. +4597.92 4605.12 "Анатолий Кулаков" Примитив Tools описывает как раз-таки выполняемые функции, которые сервер может выполнить, если его аишка попросит. +4605.12 4615.08 "Анатолий Кулаков" То есть запустить какую-нибудь команду или сделать какое-то действие, распечатать какую-нибудь модельку или сходить в какой-то интернет и там что-то скачать. +4615.08 4617.92 "Анатолий Кулаков" Все это описывается в Tools. +4617.92 4618.92 "Анатолий Кулаков" Примитив Resource. +4618.92 4622.80 "Анатолий Кулаков" Ресурс представляет собой какой-то источник данных. +4622.80 4637.40 "Анатолий Кулаков" Это может быть табличка на файловой системе или табличка в базе данных, которая может сообщить дополнительную информацию искусственному интеллекту о том, чего там такого интересного лежит и что там такого хорошего написано. +4637.40 4640.00 "Анатолий Кулаков" И третий примитив – это Prompts. +4640.00 4649.28 "Анатолий Кулаков" Это какие-то переиспользуемые шаблоны, которые помогают структурировать взаимодействие между моделью и сервером. +4649.28 4652.48 "Анатолий Кулаков" Каждый примитив обладает специальными методами. +4652.48 4670.68 "Анатолий Кулаков" Например, если мы хотим происследовать, посмотреть список всех возможных, например, инструментов, например, тулов, то мы можем добавить /list к этому методу, и он нам должен отобразить список всех тулов, то есть сервер должен вернуть список всех тулов, которые у него есть. +4670.68 4673.90 "Анатолий Кулаков" И это применимо ко всем примитивам. +4673.90 4685.16 "Анатолий Кулаков" Также точно мы можем сделать get для каждого примитива, и для примитивов Tools мы можем сделать метод call, вызвать /call и мы тут вызовем. +4685.16 4697.00 "Анатолий Кулаков" Например, клиент может взять и попросить список всех доступных тулов, вызвав ресурс, который называется tools/list, и после этого запустить их с помощью tools/call. +4697.00 4704.74 "Анатолий Кулаков" У клиента точно также есть три примитива, но совпадение с тройкой случайные, потому что примитивы там совершенно другие. +4704.74 4706.28 "Анатолий Кулаков" Первый примитив – это Sampling. +4706.28 4717.60 "Анатолий Кулаков" Он позволяет серверу взаимодействовать с IE-моделью, то есть если вам у сервера необходима какая-то информация или какая-то функциональность, он может попросить IE-шку это сделать. +4717.60 4735.28 "Анатолий Кулаков" Естественно, сервер может завести свою собственную IE-шку, но для того, чтобы исключить какую-то зависимость от конкретного SDK и использовать ту же самую модель, которая сейчас работает, в общем, сделан такой обычный callback, то есть IE-шка может попросить сервер, а сервер в этот момент может попросить IE-шку о чем-то. +4735.28 4738.72 "Анатолий Кулаков" Они будут синхронно работать на одной и той же модели. +4738.72 4741.72 "Анатолий Кулаков" Дальше третий тулс – это выявление. +4741.72 4746.32 "Анатолий Кулаков" Выявление позволяет серверу спросить пользователя о чем-то. +4746.32 4748.80 "Анатолий Кулаков" То есть получить какую-то дополнительную информацию о пользователе. +4748.80 4760.72 "Анатолий Кулаков" Или, например, запросить у пользователя подтверждение на какое-то действие, если вы выполняете какое-то опасное действие, допустим, удаление файла, то логично спросить пользователя интерактивно, точно ли вы хотите удалить или не точно хотите удалить. +4760.72 4763.84 "Анатолий Кулаков" И третий примитив – это логинг. +4763.84 4767.84 "Анатолий Кулаков" Логинг позволяет серверу писать логи на хост. +4767.84 4779.20 "Анатолий Кулаков" Но это в основном полезно для отладки, то есть все логи будут в одном месте, потому что на хосте собираются логи со всех MCP-серверов, и поэтому очень удобно их в одном месте иметь. +4779.20 4784.72 "Анатолий Кулаков" Ну вот, кратко мы разобрались о том, как работает изнутри MCP-протокол, и что же предлагает нам Микрософт. +4784.72 4793.40 "Анатолий Кулаков" А Микрософт запартнерилась с Atropik и сделали официальный C# SDK для модель контекст-протокола. +4793.40 4802.48 "Анатолий Кулаков" Этот SDK естественно open-source, естественно лежит на GitHub, уже у него там куча всяких изменений, коммитов и разумеется ждет ваших правок, если вы вдруг захотите. +4802.48 4814.48 "Анатолий Кулаков" А как вся эта штука выглядит, вот я там описал всякие тулы, примитивы, серверы, клиенты, в общем, может быть на слух показаться достаточно сложно. +4814.48 4820.28 "Анатолий Кулаков" На самом деле протокол не очень сложный, протокол простой, но опять же, не описать его двумя строчками. +4820.28 4826.04 "Анатолий Кулаков" Но вот если мы используем всю мощь C#, то как раз двумя строчками его описать и получается. +4826.04 4827.60 "Анатолий Кулаков" Что же мы собственно имеем? +4827.60 4832.16 "Анатолий Кулаков" Допустим, вы хотите создать MCP-сервер, что для этого нужно? +4832.16 4833.16 "Анатолий Кулаков" Во-первых, поставить пару пакетов. +4833.16 4836.92 "Анатолий Кулаков" Это Microsoft Extension Hosting и модель контекст-протокол. +4836.92 4839.80 "Анатолий Кулаков" Так скромно прямо и называется пакет. +4839.80 4853.24 "Анатолий Кулаков" Дальше вы создаете специальный Application Host Builder, и у этого Host Builder вызываете метод addMCPServer, который как раз декларирует, что данный хост это не просто таки хост, а MCP-серверный хост. +4853.24 4880.40 "Анатолий Кулаков" Дальше вы определяете транспорт, с помощью которого будем взаимодействовать, например, VIV_STDIO_SERVER_TRANSPORT, таким образом сообщая, что мы будем Output просто слать в консольное приложение, в его Output, и самое прекрасное директива это VIV_TOOLS_FROM_ASSEMBLY, то есть этот метод сообщает нашему хосту, что он должен просканировать текущую сборку и вытащить оттуда все те самые TOOLS, которые являются примитивами MCP-сервера. +4880.40 4881.72 "Анатолий Кулаков" Что такое TOOLS? +4881.72 4885.64 "Анатолий Кулаков" А это специальные классики, помеченные специальным атрибутом. +4885.64 4904.44 "Анатолий Кулаков" То есть вы можете создать класс, пометить его атрибутом MCP_SERVER_TOOL, и дальше у этого класса объявить какие-то делегаты, какие-то методы, например, можно объявить метод, который называется ECHO, который принимает строку в качестве параметра и назад возвращает HELLO, наша строка, наш месседж. +4904.44 4914.92 "Анатолий Кулаков" Для того, чтобы этот метод посчитался TOOL, над ним нужно навести атрибут MCP_SERVER_TOOL и навести атрибут DESCRIPTION, который человеческим языком объяснит, что этот метод делает. +4914.92 4917.04 "Анатолий Кулаков" В принципе, и все. +4917.04 4920.52 "Анатолий Кулаков" Этого достаточно для того, чтобы реализовать как раз MCP_SERVER_PROTOCOL. +4920.52 4936.44 "Анатолий Кулаков" Вспомним наши примитивы, то есть что там, ну, естественно, о всех низкоуровневых коммуникациях, о CONNECT, о HANDSHAKE, о разрыве соединения, об этом заботится непосредственно сам хост, MCP-хост. +4936.44 4944.84 "Анатолий Кулаков" А для того, чтобы предоставить список инструментов, как раз и нужны вот эти атрибуты, которые пометят наши методы специальным MCP_SERVER_TOOL атрибутом. +4944.84 4960.88 "Анатолий Кулаков" Таким образом, у нас, у ISP.NET есть список всех тулов, ISP.NET может их запускать, и ISP.NET может возвращать информацию, то есть DESCRIPTION атрибут, который мы задали, информацию о каждом конкретном инструменте, о каждом конкретном туле. +4960.88 4964.96 "Анатолий Кулаков" И навесив парочку атрибутов, мы, в принципе, реализовали весь протокол. +4964.96 4972.92 "Анатолий Кулаков" Теперь, чтобы оттестировать наш сервер, нам необязательно поднимать какой-то Visual Studio или IDE, в общем, какой-то ISP-хост. +4972.92 4974.48 "Анатолий Кулаков" Этого делать необязательно. +4974.48 4981.88 "Анатолий Кулаков" Есть прекрасная вещь, которая называется MCP_INSPECTOR, это инструмент как раз для отладки MCP серверов. +4981.88 4991.30 "Анатолий Кулаков" Визуальная штука, запускается она, правда, через ноду, поэтому придется вам пострадать, но в общем случае открывается такое UI-ное визуальное окошко, чем-то похоже на свагер. +4991.30 4995.56 "Анатолий Кулаков" Вот вы там в свагере можете ввести какой-то URL, задать ему параметры, нажать кнопочку "выполнить". +4995.56 4997.64 "Анатолий Кулаков" Вот здесь такая же точная концепция. +4997.64 5002.76 "Анатолий Кулаков" Вы нажимаете кнопочку "connect", подсоединяетесь к вашему серверу. +5002.76 5009.76 "Анатолий Кулаков" Дальше этот инспектор автоматически отслеживает, какие ресурсы предоставляет ваш сервер. +5009.76 5027.72 "Анатолий Кулаков" То есть он находит ваш метод эха, вы можете кликнуть по методу, посмотреть детальную информацию, то бишь наш дескриптор о нем, и если вы жмакните на "run tool" кнопочку, то запустится, соответственно, тот тул, который вы задали, и отобразится результат, ожидаемый, который вы задали в коде. +5027.72 5030.02 "Анатолий Кулаков" В общем, такая хорошая, легкая отладочка получается. +5030.02 5038.84 "Анатолий Кулаков" Ну, как легкая, надеюсь, что когда-нибудь его переведут, конечно, на что-то более вменяемое, чем запуск ноды на вашем компьютере, но пока живем так. +5038.84 5045.10 "Анатолий Кулаков" Естественно, все это можно потом подключить к какой-нибудь EDE-шке или к какому-нибудь настоящему MCP-хосту и там поиграться. +5045.10 5046.90 "Анатолий Кулаков" Но это уже тема совсем другого разговора. +5046.90 5069.66 "Анатолий Кулаков" Я еще приложил к нам в шоу ноты GitHub-репозиторий, который называется sm.net.mcp, там много, прям куча MCP всяких серверов, в том числе, естественно, есть на дотнете, то есть если вы задумаетесь о написании своего сервера, то первым делом советую взглянуть именно на те примеры, которые там есть. +5069.66 5083.82 "Анатолий Кулаков" Там есть куча мусора, куча интересного, ну, стандартный, ауф-экзампл стоит посмотреть, то есть каким образом правильно аутентификацию делать, чтобы к вашим интерпризным данным не ходили все, кто подряд, для кого выставили на оружие JSON-RPC. +5083.82 5096.74 "Анатолий Кулаков" Есть, например, MCP-сервер, который позволяет вам строить UI-ку для Avalon'и, как ни странно, есть MCP-сервера с доступом для SQLite, для Postgre, естественно, для всех популярных баз данных. +5096.74 5099.70 "Анатолий Кулаков" Есть сервера, которые помогают вам писать Unity-приложения. +5099.70 5103.22 "Анатолий Кулаков" В общем, можно найти, кажется, что на любой вкус. +5103.22 5145.86 "Анатолий Кулаков" Из интересного, что я нашел, это штука, которая динамически преобразует Swagger API, который есть, по сути, у всех наших современных ASP-приложений, в MCP-tool-протокол, то есть вы стандартными Swagger'овскими атрибутами, по сути, но это не Swagger'овские атрибуты, это, получается, такие ASP.NET атрибуты, в общем, которые превращаются в Swagger-протокол, а эта штука берет этот Swagger-протокол и превращает это все в MCP-протокол, и вам уже не нужно развешивать вот эти MCP-сервер-тул-атрибуты, которые есть, и всякие Description-атрибуты, которые есть, в принципе, вы можете использовать и ваш Swagger-протокол для того, чтобы притвориться MCP-сервером. +5145.86 5148.78 "Анатолий Кулаков" Интересная идея, надо ее покрутить. +5148.78 5169.90 "Анатолий Кулаков" Дальше из интересного есть инкрементальный Source-генератор на основе рослина, для того, чтобы автоматически генерить статическое описание тулов, ну, то есть не с помощью вот этих атрибутов, как делали в прошлом веке наши деды с помощью Reflection, а как положено, с помощью статических Source-генераторов, почему бы и нет. +5169.90 5175.42 "Анатолий Кулаков" Ну, в общем, много всего интересного народ придумывает, в общем, посмотрим, куда эта кроличья нара нас заведет. +5175.42 5188.14 "Анатолий Кулаков" В общем, получился такой модель Context-протокол, который хорошо стандартизует обмен между модельками, хостингами и какими-то приложениями, которые прекрасно пишутся на дутнете и прекрасно работают. +5188.14 5206.38 "Анатолий Кулаков" SDK очень мощный, хороший, интересный получился, несмотря на то, что он недавно зарелижен, в общем, там добавляются новые интересные инструменты, я думаю, про это мы еще с вами поговорим, о том, как написать уже более сложные какие-то MCP-серверные приложения и что из них можно другого выжать. +5206.38 5227.34 "Игорь Лабутин" Интересная действительно тема, у меня все никак не доходят руки, не знаю, дойдут ли, покопаться в этом направлении, я скорее пока так использую яичку, чисто как потребитель, не пытаясь дописать какой-нибудь сервачок и предоставить MCP для чего-нибудь, но поглядим. +5227.34 5230.94 "Игорь Лабутин" Если попробую, обязательно поделюсь опытом. +5230.94 5234.70 "Игорь Лабутин" Свою базу данных с пользователями пока не пускаешь, да? +5234.70 5240.66 "Игорь Лабутин" Нет, нет, нет, нет, не пускаю пока, ни в коем случае, не доверяю. +5240.66 5254.90 "Игорь Лабутин" Так, есть у нас еще одна статья от Эндрю Лока, она такая, снова про respond-core, про что же еще может быть Эндрю Лок нам рассказывать, но тем не менее, про фичу, которую я на самом деле особо не знал раньше. +5254.90 5261.06 "Игорь Лабутин" Никогда ей не пользовался, но вот она действительно есть такая, довольно интересная и с не совсем тривиальным поведением. +5261.06 5262.06 "Игорь Лабутин" Не совсем тривиальным. +5262.06 5266.24 "Игорь Лабутин" Фича называется fallback endpoints, что это такое? +5266.24 5272.58 "Игорь Лабутин" Значит, давайте для начала вспомним, что такое вообще роутинг в respond-core и как он работает. +5272.58 5282.10 "Игорь Лабутин" Значит, сам себе роутинг — это просто способ как-то замапить входящий URL, URL входящего запроса на тот хендлер, который будет его исполняться. +5282.10 5287.90 "Игорь Лабутин" Естественно, для этого используется middleware, ну куда же без них в respond-core, и их две. +5287.90 5314.34 "Игорь Лабутин" Одна называется endpoint routing middleware, она выполняется довольно рано в момент обработки запроса, и ее задача по url либо каким-то другим способом понять, какой же в итоге код нужно выполнить, какой хендлер, в зависимости от того, ну в конце, когда мы до него таки доберемся, если доберемся, если позволит аутентификация, если позволит еще что-то. +5314.34 5322.06 "Игорь Лабутин" И есть еще endpoint middleware, это собственно middleware, который непосредственно выполнит то, что было выбрано. +5322.06 5337.82 "Игорь Лабутин" Раньше до шестого дотонета нужно было, все наверное помнят те, кто писал, нужно было указать два волшебных вызова, useRouting и useEndpoints, если вы неправильно их указывали, то у вас была недоступна информация о каком, а там выбранном контроле или еще о чем-нибудь. +5337.82 5369.38 "Игорь Лабутин" Вот сейчас Evaluation автоматически это все добавляет, и разбедение на эти два, как я сказал, довольно важно, потому что мы должны выбрать, куда мы пойдем довольно рано, потому что какая-то мета-данные, которые ассоциированы с этим самым endpoint выбранным, то есть с контроллером ли, или с методом minimal API, или Razor страницы, или еще чем-нибудь, могут быть важны вот эти мета-данные для того, чтобы определять, можно ли ее исполнять или как исполнять. +5369.38 5381.74 "Игорь Лабутин" То есть endpoint routing middleware выбирает, что мы будем исполнять, дальше в каких других middleware мы можем прочитать мета-данные об этом endpoint и принять решение, хотим ли мы его выполнять. +5381.74 5388.58 "Игорь Лабутин" Ну и если мы можем что-то делать на основе мета-данных, значит эти мета-данные нужно как-то добавить. +5388.58 5409.46 "Игорь Лабутин" Ну, в целом вообще не только мы это делаем, стандартный фреймворк это тоже делает, то есть например, когда мы размечаем ваши контроллеры атрибутами всякие allowAnonymous или еще что-нибудь в таком духе, это как раз те самые мета-данные, которые потом authorization middleware будет читать и на них что-то делать. +5409.46 5412.50 "Игорь Лабутин" Или например, course middleware тоже работает на мета-данных. +5412.50 5418.10 "Игорь Лабутин" Вот, то есть как правило, это либо атрибуты на контроллерах, либо специальные методы на minimal API варианте. +5418.10 5429.98 "Игорь Лабутин" А теперь возвращаемся, когда мы теперь поняли и вспомнили, что же такое routing, возвращаемся к началу и вспоминаем или пытаемся понять, что такое fallback routing. +5429.98 5438.50 "Игорь Лабутин" И fallback это штука, которая, ну, как логичная следует из перевода, срабатывает, когда непонятно куда идти. +5438.50 5445.06 "Игорь Лабутин" То есть когда мы раутим, мы пытаемся по углу решить, какой же endpoint мы будем выполнять. +5445.06 5451.82 "Игорь Лабутин" Как правило, это некоторый граф, по сути, обход графа, поиск в глубину и поиск, куда же мы пойдем. +5451.82 5465.38 "Игорь Лабутин" Но предположим, что мы ничего не нашли, и тогда можно задать ncsp.core специальный endpoint, который будет выполняться, если не найден никакой другой. +5465.38 5490.94 "Игорь Лабутин" В зависимости от того, что вы используете, minimal API, контроллеры, reserve pages, там немножко разные методы того, как это сделать, но по большому счету они все начинаются с map_fallback, то есть в minimal API мы говорим map_fallback метод, и внутри определяем тут лямбду, тот код, который будет выполняться, если не нашелся ни один из раутов. +5490.94 5536.10 "Игорь Лабутин" Как правило, это используется для того, чтобы заре-директить вас на какую-нибудь нужную страничку, то есть можно придумать что-то более сложное, например, попытаться угадать, что хотел сказать пользователь каким-нибудь неверным URL, и подправить URL, и заре-директить его куда-нибудь, либо такое может случиться, если вы используете какой-нибудь client-side routing в вашем SPA-приложении, пользователь, находясь на какой-то страничке, нажал F5, и вот этот вот get-запрос со странным раутом, который на самом деле относится к клиенту, а сервер про него ничего не знает, прилетит на сервер, ну и сервер, естественно, обычно в таком случае просто редиректит на фронт, ну на рутовый URL, да, и фронт дальше пусть сам разбирается со своим раутингом без того, чтобы ввлекать в это дело сервер. +5536.10 5537.10 "Игорь Лабутин" Вот. +5537.10 5567.30 "Игорь Лабутин" Соответственно, есть, как я сказал, разные способы, есть метод, называется mapFallbackToFile, который возвращает, собственно, в любой файлик индекса, что вы хотите, можно mapFallbackToPath, и тогда он принимает путь к странице и вернет вам зарендеренную RazorPage, либо mapFallbackToController, и здесь, меня удивило, но прямо указывается action и controller с строками, просто указывает название контроллера, название метода, которое нужно выполнить. +5567.30 5582.30 "Игорь Лабутин" Ну, окей, хорошо, они выглядят все одинаково, ведут себя, наверное, тоже поодинаково, но нет, на самом деле, нет, Andrew Locke я такой раз с этим столкнулся, я говорю, что никогда это не использовал, но мне показалось это интересно. +5582.30 5598.66 "Игорь Лабутин" Например, смотрите, берем, ну, то, что я уже упоминал, allowAnonymous, и берем minimal API, и говорим, что mapFallback что-нибудь, и на него навешиваем на этот fallback метаданные. +5598.66 5633.86 "Игорь Лабутин" Основная проблема и основная разница возникает в том, как эти метаданные обрабатываются, то есть сами fallbacks работают, но, допустим, мы навесили allowAnonymous на mapFallback или на вариант mapFallbackToFile, но все будет работать нормально, то есть если мы разрешили анонимный доступ и мы не залогенины, и мы введем какой-нибудь неверный несуществующий url, нам AspirantCore прекрасно выполнит этот fallback метод, потому что анонимным пользователям разрешено, все будет хорошо, и нам покажут результаты выполнения этого fallback метода. +5633.86 5644.02 "Игорь Лабутин" Ну, в примере там понятно, что просто выводится какая-то строчка, чтобы было понятно, что за урл ответил, но если вы работаете с razor-пейджами или с контроллерами, то все будет немножко по-другому. +5644.02 5672.50 "Игорь Лабутин" Значит, mapFallback и mapFallbackToFile, те, которые мы рассмотрели чуть выше, они работают следующим образом, они на самом деле регистрируют фактически новый endpoint внутри вот этого всего механизма, так что когда у вас endpoint routing middleware пытается выбрать, куда же пойти, оно фактически выберет этот самый endpoint. +5672.50 5679.78 "Игорь Лабутин" Вот, это будет конкретный endpoint, на нем есть конкретные метаданные, которые вы навесили, и с ним все будет работать. +5679.78 5683.42 "Игорь Лабутин" А вот razor-пейдж и контроллер делают немножко по-другому. +5683.42 5684.66 "Игорь Лабутин" Они делают следующее. +5684.66 5836.46 "Игорь Лабутин" Они, когда вы задаете mapFallbackToController или mapFallbackToPath, то в этом случае на самом деле регистрируется специальный такой endpoint, который имеет dynamicPageMetadata или dynamicControllerMetadata, специальные метаданные, такие, что в момент, когда выбирается правильный endpoint, в этот момент на самом деле вот эти dynamicPageMetadata, dynamicControllerMetadata используются endpoint routing middleware, насколько я понимаю, и в результате, поскольку мы говорим, по сути, контроллер или пейдж, он перенаправляет на существующий контроллер или на существующий метод контроллера, или на существующую razor-страницу, поэтому незачем создавать новый endpoint, и фактически внутри из-за этих метаданных мы перенаправляем, endpoint routing для всей дальнейшей цепочки middleware будет выглядеть, как будто он выбрал вот тот метод или тот контроллер, тот метод или ту razor-страницу, на которую вы фулбэчились, то есть поведение с точки зрения пользователя одинаковое, как если бы он пошел через фулбэк, либо как если бы он пошел сразу на ту страницу, куда вы фулбэчились, и по факту это означает, что метаданные, которые вы навесите на такой фулбэк-страницу, они недоступны в дальнейшем pipeline, потому что endpoint выбирается тот, который реальный, метаданные не копируются туда, берутся те метаданные, которые висят на нормальном endpoint, потому что мы знаем, конечно, в момент выбора раутинга, откуда мы пришли, из фулбэка или не из фулбэка, но этот факт не используется, берутся просто обычные метаданные, и поэтому фактически, несмотря на то, что вы можете написать map map_fulback_to_controller.ed, там любые метаданные, anonymous, например, фактически все эти вызовы абсолютно бесполезны, эти метаданные никуда не сохранятся, не будут вам доступны в рантайме, ну только если вы в какой-нибудь reflexi их не достанете, и с этим можно интересно столкнуться, если вы, например, мигрируете, ну допустим, не знаю, у вас был minimal API, вы как-то все там развесили через фулбэк-эндпойнты, навесили метаданные, у вас все прекрасно работает, потом вы говорите, ну ладно, не знаю, там minimal API приложение стало слишком большим, давайте перепишем на контроллеры. +5836.46 5844.54 "Игорь Лабутин" Добавляйте ровно ту же логику, с теми же фулбэками, с теми же метадонами, и все перестает работать, потому что метаданные на контроллерах игнорируются, если вы идете через фулбэк. +5844.54 5855.86 "Игорь Лабутин" Вот такая вот песня, не совсем миграция из minimal API в контроллеры и обратно прозрачно, на самом деле есть некоторая разница в поведении. +5855.86 5861.02 "Анатолий Кулаков" Не, ну надо было ожидать, потому что все-таки технологии довольно сложные. +5861.02 5874.14 "Игорь Лабутин" Ну, они сложные и разные, да, и как-бы когда ты задумываешься, действительно кажется, что логично, если ты проводишь на существующий контроллер, зачем тебе создавать фейковый эндпойнт, который будет по сути выполнять то же самое. +5874.14 5884.26 "Игорь Лабутин" То есть можно было бы внутри создать эндпойнт, на который положить какие-то метаданные, но возникает вопрос, а как эти метаданные смёрзнуть с теми метадонами, которые уже есть на том эндпойнте, который реально будет выполняться. +5884.26 5899.30 "Игорь Лабутин" Вот, видимо, чтобы не решать эту проблему, решили просто игнорить те эндпойнты, которые на фоллбеке, наверное, ой, не эндпойнты, а метадонны, наверное, это не такая большая проблема, хотя, возможно, вот как раз с вопросом allow anonymous или ещё что-нибудь в таком духе она где-нибудь дострельнёт. +5899.30 5904.06 "Игорь Лабутин" В общем, если используете фоллбеки, смотрите внимательно, следите за вашими метадонами. +5904.06 5905.06 "Игорь Лабутин" Такие дела. +5905.06 5914.16 "Анатолий Кулаков" Так, ну отлично, давай, я думаю, ещё успеем коротко о разном поговорить, у меня тут немножко ссылочек собралось. +5914.16 5922.90 "Анатолий Кулаков" Прежде всего, хочется посоветовать вам подлодку, 425-й выпуск, в гости заходил Андрей Брислав и поговорили ребята про языки программирования будущего. +5922.90 5928.10 "Анатолий Кулаков" Ну, несмотря на слишком кричащий заголовок, тема была довольно интересная. +5928.10 5940.66 "Анатолий Кулаков" Дело в том, что Андрей Брислав, кто не знает, это автор Котлина, он сейчас разрабатывает, ну, то есть он сейчас работает в стартапе и разрабатывает язык, который был бы полезен для того, чтобы программировать с помощью ИИ-моделей. +5940.66 5954.58 "Анатолий Кулаков" То есть, казалось бы, чего ИИ-моделям не хватает, у них есть формализованные языки, но дело в том, что эти формализованные языки, которые писались десятилетиями до них, они слишком для узкого круга, они слишком для программистов. +5954.58 5958.70 "Анатолий Кулаков" В общем, ИИ-шка кажется, что может программироваться с помощью обычного естественного языка. +5958.70 5970.10 "Анатолий Кулаков" Это может быть не обязательно английский, можно на русском программировать, если сильно захочется, но дело в том, что некие специальные структуры, которые человечество выработало, они до сих пор нужны. +5970.10 5983.50 "Анатолий Кулаков" Допустим, нам необходимы некие модули, которые мы можем повторять, переиспользовать, нам необходимы какие-то декларации терминов, которые четко будет понятно, что они значат и в каком контексте, какие термины, что обозначают. +5983.50 6002.06 "Анатолий Кулаков" В общем, с помощью вот таких вот каких-то базовых элементов, которые, казалось бы, в каждом языке уже есть и они нам уже привычны и доступны, в общем, но если мы начинаем говорить про язык программирования, который понимает ИИ-шка и который на естественном языке, вот там таких элементов нет. +6002.06 6034.94 "Анатолий Кулаков" Вот Андрей пытается это сделать, то есть он пытается придумать, каким образом должен выглядеть язык, который можно программировать, вроде бы, человеческим синтаксисом, но при этом там должны быть какие-то стандартные концепции, которые умеют упрощать сложные какие-то большие аппликейшены в нашем современном мире, чтобы можно было на обычном человеческом языке написать какое-то большое-большое интерфайс-приложение, как оно там должно поддерживаться, как оно должно тестироваться, как оно должно инкрементально как бы эволюционировать и так далее. +6034.94 6043.42 "Анатолий Кулаков" В общем, интересные мысли, посмотрим, что из этого выйдет, а вот на старте послушать, как обо всем об этом думает автор, тоже весьма и весьма полезно. +6043.42 6095.74 "Анатолий Кулаков" Так, вторая новость о том, что заанонсирован спонсоршип на Nuget.org, то есть для авторов пакетов теперь есть возможность рассказать, что они нуждаются в донатах, в общем, для этого необходимо пойти в Nuget.org, зайти в личный кабинет, там нажать на «Manage packages» и вставить свою ссылку на один из поддерживаемых сайтов для донатов, в частности это GitHub Sponsors, Patreon, Open Collective и несколько там других менее известных, в общем, то есть сам Nuget не собирает никакие донаты, он просто позволяет вам вставить ссылочку на вашу страничку, и рядом с пакетом отобразится такая иконка в виде сердечка, на которую все желающие могут кликнуть и задонатить вам кучу бабла, поэтому если у вас есть такая возможность, наверное, будет не лишним. +6095.74 6119.26 "Анатолий Кулаков" Так, еще одна статейка от Microsoft, которая рассказывает о том, что они внедрили в GitHub копайлотов неких кастомных агентов и добавили для примера двух кастомных агентов, это агенты, которые называются C-Sharp Expert и Evenform Expert, в общем, такая необычная связочка у нас. +6119.26 6132.34 "Анатолий Кулаков" Агенты, которые C-Sharp Expert, то есть что такое вообще эти агенты у копайлота, то есть вы сделали какой-то pull-request, допустим, и на этот pull-request можете натравить агентов, которые вам расскажут, насколько он хороший, то есть которые проведут какое-то ревью, к примеру. +6132.34 6167.90 "Анатолий Кулаков" В общем, C-Sharp Expert смотрит, насколько код хороший с точки зрения C-Sharp, и что, в частности, он там учитывает, он там смотрит всякие best-practices, насколько хорошо используется современный синтаксис, структура файлов, структура проектов, следит за перформансом, что мы там никакие глупости по перформансу не наделали, также он проверяет, насколько правильно мы используем async/await паттерны, правильно ли пропасываем cancellation токены, хорошо ли обрабатываем ошибки, то есть такие стандартные best-practices, которые каждый из нас должен знать, помнить и смотреть на ревью, вроде по описанию нормуль, вроде подходит. +6167.90 6177.82 "Анатолий Кулаков" Ну и плюс еще он смотрит, насколько мы правильно тестируем, насколько там совпадает с DDD workflow все наши тесты, в общем, и так далее. +6177.82 6191.78 "Анатолий Кулаков" С WinForm тут вообще интересно, то есть он в WinForm смотрит, опять же, best-practices, насколько мы хорошо реализовали MVVM, шаблон в WinForm, вообще в MVVM, в WinForm это уже сильно как бы. +6191.78 6204.58 "Анатолий Кулаков" Он следит за различными событиями, я напомню, это самый частый причин для утечки, это неправильное отписывание от событий, в общем, это у него есть встроенный анализатор. +6204.58 6221.50 "Анатолий Кулаков" Одна, наверное, из киллер-фич для WinForm, это то, что он не позволяет менять сгенерированные дизайнером файлы, который это дизайнер.cs, потому что раньше моделька меняла их вовсю, в общем, и, соответственно, помогает писать лучшие WinForm-приложения. +6221.50 6230.82 "Анатолий Кулаков" Эту штуку можно подключить автоматически на GitHub, чтобы она к каждому вашему pull-request уцеплялась или можно заставить его именно писать и помогать вам, этих экспертов, не только ревьюить. +6230.82 6242.26 "Анатолий Кулаков" Я ради интереса полез посмотреть, потому что там же все open source, все такое, полез посмотреть на те самые best-practices, которые эти ребята декларируют, как они там описаны, что они там делают. +6242.26 6252.42 "Анатолий Кулаков" В общем, нашел кучу всего интересного, также я по пути заглянул в Cursor Directory, где там тоже описаны всякие .NET-эксперты, и есть о чем поговорить нам, Игорь, есть о чем поговорить. +6252.42 6258.22 "Анатолий Кулаков" Я думаю, это мы вынесем в отдельную большую тему и обсудим, а кто такие C#-эксперты по мнению всяких ИИ-моделей. +6258.22 6260.78 "Анатолий Кулаков" Как-нибудь в следующих выпусках. +6260.78 6294.50 "Игорь Лабутин" А еще вышла статейка, в которой анонсится о том, что UnaPlatform – это, я напомню, кроссплатформенный UI, который можно писать на .NET под практически… вообще, по-моему, под все платформы, которые есть, заанонсили такое совместное развитие, что ли, MAUI с Майкрософтом, в чем это будет… ну, не только MAUI, кстати, в чем будет заключаться. +6294.50 6307.18 "Игорь Лабутин" То есть, во-первых, они довольно много, UnaPlatform-команда, в смысле, примерно полтора месяца довольно тесно общались с Майкрософтом и помогали им втащить Android API 36.1 в MAUI, чтобы там все работало. +6307.18 6323.34 "Игорь Лабутин" Дальше они задумываются о том, чтобы еще впилить в MAUI, напомню, что там есть экспериментальная, как я понимаю, поддержка ВАЗМа, или не очень экспериментальная даже, но там нет нормального мультитрейдинга, вот, соответственно, попробуйте включить в ВАЗМ мультитрейдинг. +6323.34 6341.34 "Игорь Лабутин" Более того, они собираются активно помогать ревьюить пиары в MAUI Core-компоненты, ну и также они собираются контрибьютить и мейнтейнить с Ksharp-репозиторий вместе с Майкрософтом, потому что это их в том числе основной график-энджин. +6341.34 6351.06 "Игорь Лабутин" То есть, короче, UnaPlatform как-то очень сильно стремятся в сторону того, чтобы поддержать MAUI, посмотрим, что из этого получится. +6351.06 6354.30 "Игорь Лабутин" Чтобы их купил Майкрософт, я так понимаю, они стремятся? +6354.30 6367.20 "Игорь Лабутин" Ну, либо чтобы у них тоже все нормально работало, потому что UnaPlatform, я напомню, это же способ писать что-то на кроссплатформе, а внутри они используют на разных платформах разные, грубо говоря, относительно нативные для этих платформ движки. +6367.20 6370.60 "Игорь Лабутин" То есть они не полностью, по-моему, все рендерят сами, а все-таки используют нативные штуки. +6370.60 6374.40 "Игорь Лабутин" И, видимо, MAUI им нужен в том числе для того, чтобы все работало. +6374.40 6375.40 "Игорь Лабутин" Так или иначе. +6375.40 6376.40 "Игорь Лабутин" Ну, либо с Ksharp как минимум. +6376.40 6382.36 "Анатолий Кулаков" Мне кажется, что как раз MAUI можно выкинуть и купить как бы себе маленькую Una. +6382.36 6383.36 "Игорь Лабутин" Возможно. +6383.36 6386.36 "Игорь Лабутин" А это типа, как называется там, короче, тестовое задание. +6386.36 6387.36 "Игорь Лабутин" Вот. +6387.36 6391.64 "Анатолий Кулаков" Да-да, тестовое задание сделали, хорошо, MP-шка есть сейчас бац-бац в продакшн. +6391.64 6396.24 "Игорь Лабутин" Не, ну в смысле типа это, если справитесь, мы вас купим. +6396.24 6397.24 "Игорь Лабутин" Нормально? +6397.24 6398.24 "Игорь Лабутин" Да. +6398.24 6399.24 "Игорь Лабутин" Нормально. +6399.24 6401.24 "Игорь Лабутин" Ладно, посмотрим, во что это превратится, поглядим, пока это обещание. +6401.24 6405.68 "Игорь Лабутин" Ну нет, что-то они, конечно, сделали, но посмотрим, будут ли мультитрейдинг в АСМИ и так далее. +6405.68 6430.52 "Игорь Лабутин" Ну что, на этом, наверное, на сегодня все, 125-й выпуск, обсудили 10-ый релиз Кандидат 2, в смысле, релиз Кандидат 2 десятки, System Command Line 2.0, поговорили про уязвимости в ASP.NET Core, обсудили MCP-протокол и как оно соотносится с C#, поговорили про методаты fallback and points, ну и кратенько немножко обсудили разных мелочей. +6430.52 6433.88 "Игорь Лабутин" На этом, наверное, все на сегодня. +6433.88 6440.96 "Анатолий Кулаков" Не забывайте лайк, обшарить, репостать, там пишите комменты, ставьте побольше звездочек или что там пальцев вверх, что там есть на вашей платформе. +6440.96 6446.80 "Анатолий Кулаков" В общем, поддерживайте, поддерживайте, давайте, мы вас ждем, а также на Boost у нас тоже есть интересные кнопочки, которые можно потыкать. +6446.80 6448.28 "Анатолий Кулаков" До новых встреч, всем пока. +6448.28 6448.80 "Игорь Лабутин" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-126.txt b/input/Radio/Transcriptions/RadioDotNet-126.txt new file mode 100644 index 0000000..5ba443e --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-126.txt @@ -0,0 +1,658 @@ +0.00 11.46 "Анатолий Кулаков" Здравствуйте, дорогие слушатели, в эфире Радио.нет выпуск 126-й. +11.46 14.72 "Анатолий Кулаков" И в студии его постоянные ведущие Анатолий Кулаков +14.72 15.72 "Игорь Лабутин" и Игорь Лабутин. +15.72 16.72 "Игорь Лабутин" Всем привет. +16.72 22.38 "Анатолий Кулаков" А в нашем прекрасном чатике и за нашими спидами наши благодарные слушатели. +22.38 47.48 "Анатолий Кулаков" Среди них Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев, Юрий Лодейкин, Котков Михаил и Михаил Королев. +47.48 48.48 "Анатолий Кулаков" Спасибо, друзья. +48.48 55.72 "Анатолий Кулаков" Спасибо всем, кто нас поддерживает и подключайтесь, если вы еще не здесь, не в этом бравом списке. +55.72 59.58 "Анатолий Кулаков" Заходите на Boosty и смотрите, как можно помочь нашему подкасту развиваться. +59.58 70.44 "Игорь Лабутин" А теперь представьте, где-то в разных торговых точках в Германии, Бельгии стоят сотни устройств, терминалов а-ля банкомат, где люди могут сделать прогнозы на спортивные события и внести какие-то деньги. +70.44 76.12 "Игорь Лабутин" А ваш командный дотнет разработки должна сделать так, чтобы приложение запущенное на этих устройствах стабильно работало 24/7. +76.12 79.72 "Игорь Лабутин" При этом вы разрабатываете только программную часть для терминалов. +79.72 86.96 "Игорь Лабутин" А вот когда и где устройства введут в эксплуатацию, какой там будет железо, периферия, например модель купюру приемника, ну вообще говоря, вы не очень контролируете. +86.96 94.84 "Игорь Лабутин" Для решения этой задачи ребята из Altenar разработали свою библиотеку, которая позволяет взаимодействовать с устройствами на разных протоколах, и является кроссплатформенной. +94.84 99.00 "Игорь Лабутин" И показали, как она работает на DotNext, а также начинает показывать на своих митапах. +99.00 104.40 "Игорь Лабутин" А еще такое ПО должно обновляться бесшовно, так чтобы всегда быть доступным конечному пользователю. +104.40 110.68 "Игорь Лабутин" Для этого ребята реализовали облегченную версию управления онлайн-устройствами и встроили процесс обновления в свою CI/CD-систему. +110.68 121.16 "Анатолий Кулаков" Отлично, ну что ж, сегодня выпуск будет посвящен самому знаменательному событию, которое происходит раз в год - это запуск нового DotNet. +121.16 126.26 "Анатолий Кулаков" И в этом году это не просто запуск нового DotNet, а это запуск LTS-версии. +126.26 134.28 "Анатолий Кулаков" Поэтому сейчас обсудим, посмотрим, подытожим с чем же мы будем работать, ну как минимум в ближайший год, а то может и все три. +134.28 148.52 "Анатолий Кулаков" Вообще мы все темы, которые у нас были в релизе, естественно мы разбирали в выпусках за весь этот год, поэтому практически по каждой из тем вы сможете найти какой-нибудь отдельный выпуск, который посвящен практически целиком этой теме. +148.52 151.52 "Анатолий Кулаков" В общем, за исключением мелких, естественно. +151.52 159.84 "Анатолий Кулаков" Поэтому сегодня у нас будет подведение итогов, краткая суммаризация всех выпусков, которые были за год и посвящены новому DotNet. +159.84 163.92 "Анатолий Кулаков" Ну и начнем, конечно же, с C#. +163.92 179.04 "Анатолий Кулаков" Зарелизился новый C#, получил он номер 14, несмотря на то, что весь DotNet 10, язык у нас идет вперед, впереди даже всех своих DotNets, в общем 14-й C#, посмотрим что в нем есть интересного. +179.04 190.12 "Анатолий Кулаков" Ну и, конечно же, самая интересная, самая долгожданная и самая прекрасная фича, которая зарелизилась, это Extension Members, которую мы ждали еще в прошлом году, но ее в последний момент отменили. +190.52 198.84 "Анатолий Кулаков" Но в этом релизе она вошла, доделали, дотюнили, если можно так сказать, и мы ее, соответственно, дождались. +198.84 201.92 "Анатолий Кулаков" Что же это такое за штука? +201.92 213.32 "Анатолий Кулаков" Ну, надеюсь, все из вас знают, что такое Extension методы, это как раз способ расширения тех классов, которые, возможно, нам не подвластны, то есть исходным кодом, которого мы не обладаем. +213.32 217.16 "Анатолий Кулаков" Мы можем вполне их расширить, можем дописать какие-то новые методы. +217.16 227.84 "Анатолий Кулаков" И эта штука очень прекрасная, очень мощная, буквально на ней выстрелил Линку, только благодаря ему сделали такую прекрасную технологию, как Линку. +227.84 231.16 "Анатолий Кулаков" В общем, довольно мощная и ежедневно применимая вещь. +231.16 239.64 "Анатолий Кулаков" Но у этих Extension методов было одно критическое недостатку, это то, что они могли расширять только методы. +239.64 244.52 "Анатолий Кулаков" И вот этот недостаток микрософтовцы пытались устранить много-много лет. +244.52 247.84 "Анатолий Кулаков" То есть хочется расширять, конечно, все, вкус приходит во время еды. +247.84 251.40 "Анатолий Кулаков" И как только мы увидели, что методы можно расширять, нам захотелось расширять все. +251.40 256.48 "Анатолий Кулаков" И вот как раз Extension Members – это лишь первый шаг на пути к тому, чтобы расширять все. +256.48 271.56 "Анатолий Кулаков" Но уже этот первый шаг довольно значительен, потому что в этом релизе мы научились расширять свойства, статические методы и User-Defined Operators, то есть частичный пример свойств. +271.56 273.16 "Анатолий Кулаков" Как же это выглядит? +273.16 280.96 "Анатолий Кулаков" Синтексис мы уже много раз обсуждали и в принципе он не сильно изменился, то есть все минусы, которые мы обговаривали, они до сих пор здесь. +280.96 288.78 "Анатолий Кулаков" В общем случае, нам как и раньше, необходимо объявить статический класс и в этом статическом классе начинается всякая магия. +288.78 299.96 "Анатолий Кулаков" Если раньше мы могли в Extension методах просто написать статический метод с маленьким ключевым словом и дальше ни о чем не загоняться, то вот в новом синтексисе нет. +299.96 303.96 "Анатолий Кулаков" В новом синтексисе нам нужно выучить уйму непонятных магических знаков. +303.96 313.84 "Анатолий Кулаков" Во-первых, это ключевое генерик слова Extension, которое рассказывает, к какому классу мы сейчас будем лепить Extensions. +313.84 321.76 "Анатолий Кулаков" Также он может принимать, как я уже сказал, генерик, то есть мы можем сделать Extension к любому генерик классу. +321.76 333.64 "Анатолий Кулаков" И внутри этого скопа уже, который называется Extension, мы можем декларировать различные свойства и различные методы так, как делали бы это внутри другого какого-нибудь класса. +333.64 334.64 "Анатолий Кулаков" Который мы хотим расширять. +334.64 340.28 "Анатолий Кулаков" Например, мы можем описать свойства, мы можем описать статические методы, мы можем описать статические операторы. +340.28 344.24 "Анатолий Кулаков" Например, переопределить оператор плюс и так далее, и так далее. +344.24 345.24 "Анатолий Кулаков" Вот. +345.24 346.24 "Анатолий Кулаков" Что здесь интересного? +346.24 350.40 "Анатолий Кулаков" Во-первых, не очень привычный синтексис для C#. +350.40 351.40 "Анатолий Кулаков" Почему не привычный? +351.40 358.24 "Анатолий Кулаков" Потому что у нас с маленькой буквы обычно пишутся какие-нибудь кейварды и с большой буквы пишутся какие-нибудь названия классовые проперти. +358.24 364.96 "Анатолий Кулаков" И обычно именно названия классов и методов имеют generic параметр. +364.96 371.84 "Анатолий Кулаков" А здесь такая штука, что у нас новый кейвард Extension и у него есть generic свойства. +371.84 374.16 "Анатолий Кулаков" То есть это generic кейвард получается. +374.16 376.24 "Анатолий Кулаков" В общем, такого мы еще никогда не видели. +376.24 379.44 "Анатолий Кулаков" Такого синтексиса у нас еще никогда не было, так нам еще никогда голову не ломали. +379.44 380.44 "Анатолий Кулаков" Вот. +380.44 387.68 "Анатолий Кулаков" Ну и вторая, как бы сказать, бага этого подхода – это в том, что у нас появляется слишком много вложенных скоупов. +387.68 392.12 "Анатолий Кулаков" То есть, допустим, чтобы определить новый extension метод, у нас три вложенных скоупа. +392.12 396.96 "Анатолий Кулаков" Один для класса, один для extension блока и третий уже для самого метода непосредственно. +396.96 401.94 "Анатолий Кулаков" И это с учетом того, что мы используем file-based namespaces. +401.94 409.20 "Анатолий Кулаков" Если бы мы их не использовали, то нам нужно было бы там 4 скоупа определить для того, чтобы extension метод сделать. +409.20 411.80 "Анатолий Кулаков" Вот это, конечно, тоже не очень красиво выглядит. +411.80 416.60 "Анатолий Кулаков" Но во всем остальном конструкция довольно расширяемая и довольно функциональная. +416.60 427.32 "Анатолий Кулаков" То есть кажется, что в будущем здесь можно будет легко сделать и extension-конструкторы, и extension-наследования, и extension-имплементацию различных интерфейсов. +427.32 428.72 "Анатолий Кулаков" В общем, она универсальна. +428.72 432.32 "Анатолий Кулаков" Именно поэтому ее выбрали такую уродливую и некрасивую. +432.32 439.26 "Анатолий Кулаков" Ну, потому что только она давала разработчикам возможность расширяться в будущем до безграничных пределов. +439.26 444.16 "Анатолий Кулаков" Ну, детально мы уже рассказывали про extension-мембры, как я уже говорил. +444.16 447.24 "Анатолий Кулаков" Фича хорошая, фича полезная, наверняка сейчас залетит и будем сильно употреблять. +447.24 452.48 "Анатолий Кулаков" Это самое главное нововведение нового C# 14. +452.48 457.76 "Анатолий Кулаков" Все остальное это такие довольно приятные или, может быть, не очень мелочи. +457.76 460.16 "Анатолий Кулаков" Ну, давайте пробежимся по этим мелочам тоже. +460.16 461.16 "Анатолий Кулаков" Знать надо в лицо. +461.16 462.16 "Анатолий Кулаков" Итак, field-keyword. +462.16 474.64 "Анатолий Кулаков" Тоже как-то долго вымученная штука, мне кажется, она не сильно стоит того, сколько они было возласов и сколько они писали и говорили, но все же полезная вещь. +474.64 475.64 "Анатолий Кулаков" Что это такое? +475.64 478.08 "Анатолий Кулаков" В общем, все мы знаем, все мы любим, автопроперти. +478.08 482.52 "Анатолий Кулаков" Это свойства, в которых достаточно писать set и get и больше ни о чем не загоняться. +482.52 494.00 "Анатолий Кулаков" Компилятор под капотом сделает для них backing field, то есть непосредственно то хранилище, куда будет записываться само значение и будет прозрачно и тестовать, читать и писать в этот backing field все значения. +494.00 498.76 "Анатолий Кулаков" И все бы хорошо до тех пор, пока мы не хотим внести маленькое изменение какое-нибудь. +498.76 507.92 "Анатолий Кулаков" Допустим, выставить проверку, которая проверяет, что set-ать можем мы только значение, которое не равно null. +507.92 519.48 "Анатолий Кулаков" Как только мы захотим это сделать, мы будем вынуждены завести явный backing field и расписать уже get и set не как автосвойства, а уже как непосредственно методы. +519.48 539.80 "Анатолий Кулаков" И обычно это бывает очень обидно, потому что тратить лишние строчки, тратить лишнее заведение переменной, то есть филда, который где-то далеко находится ради обычных проверок каких-нибудь или банального кэширования или банального лэзи-загрузки или еще чего-нибудь, обидно. +539.80 546.32 "Анатолий Кулаков" И разработчики решили эту маленькую горечь нашу немножко скрасить, поэтому сделали вот такое ключевое слово field. +546.32 552.72 "Анатолий Кулаков" С помощью этого ключевого слова мы можем обращаться к тому backing field, который будет генерировать компилятор. +552.72 556.16 "Анатолий Кулаков" При этом, опять же, мы не знаем ни как он его назовет, ничего. +556.16 557.16 "Анатолий Кулаков" Просто это такое ключевое слово. +557.16 560.36 "Анатолий Кулаков" Естественно, в Илькоде оно не будет называться field. +560.36 562.52 "Анатолий Кулаков" И с этим field мы можем делать всякое. +562.52 569.60 "Анатолий Кулаков" Мы можем это делать как в одном методе, get или set, так и в обоих методах. +569.60 575.32 "Анатолий Кулаков" Например, в set мы можем проверить, что у нас выставляемое значение не null, и бросить, допустим, исключение. +575.32 580.36 "Анатолий Кулаков" А в get мы можем проверить, что оно не null, допустим, и вернуть какое-то дефолтное значение на get. +580.36 582.88 "Анатолий Кулаков" Тут только ограничено все ваши фантазии. +582.88 587.48 "Анатолий Кулаков" Поэтому такое ключевое слово field позволяет нам сделать такую штуку. +587.48 605.24 "Анатолий Кулаков" Один из самых практичных примеров, которые везде есть, это заимплементировать NotifyPropertyChanged, который может теперь сделаться без backing field, потому что это самый наверное частый case, когда нам необходимо было делать backing field на пустом месте, то есть не для свойства. +605.24 616.32 "Анатолий Кулаков" Потому что NotifyPropertyChanged очень часто применяется во всяких UI-ках, в MVVM-подходе, и там люди этого хотят практически для всех свойств. +616.32 622.72 "Анатолий Кулаков" Поэтому там можно будет сделать немножко более красиво, чем есть сейчас. +622.72 626.48 "Анатолий Кулаков" Также это нововведение вносит breaking change. +626.48 628.08 "Анатолий Кулаков" Нельзя об этом промолчать. +628.08 643.08 "Анатолий Кулаков" Если вдруг у вас в классе есть backing field, который называется field, то есть его название совпадает с тем ключевым словом, которое было введено в C#, то у вас могут быть небольшие трудности. +643.08 654.28 "Анатолий Кулаков" Ну, во-первых, компьютер вам, конечно же, подскажет, что тут вы используете слово, которое может немножко скрывать наш кейворд или наоборот, и попросит его как-нибудь заменить. +654.28 661.36 "Анатолий Кулаков" Например, можно уточнить, к кому мы обращаемся с помощью собаки или с помощью this.field, тогда все станет довольно ясно. +661.36 672.24 "Анатолий Кулаков" Но, опять же, рекомендация такая, что не надо скрывать это какими-нибудь собаками или this-ами, просто переменуйте поле или выкиньте его и воспользуйтесь ключевым свойством field. +672.24 682.24 "Анатолий Кулаков" Такой небольшой breaking change, я думаю, не сильно кого-то заденет, но если вдруг почему-то вы называете ваши backing field таким странным способом, то прекратите, перестаньте. +682.24 688.24 "Анатолий Кулаков" Итак, следующее нововведение - это неявная конвертация спанов. +688.24 694.68 "Анатолий Кулаков" В C# 14 спаны решили сделать, как называется, first-class support. +694.68 696.92 "Анатолий Кулаков" Не только спаны, но read-only спаны. +696.92 713.84 "Анатолий Кулаков" В общем, спаны - это прекрасная штука, ввели ее относительно давно, она помогает делать allocation-free API, то есть выделять меньше памяти, при этом очень быстро обращаться с этой памятью и, в общем, для high-performance штук - незаменимая вещь. +713.84 719.96 "Анатолий Кулаков" Так вот, в 14-м C# наконец эти спаны решили поддержать на уровне языка. +719.96 735.84 "Анатолий Кулаков" То есть теперь парень знает компилятор, теперь он умеет их лучше и сильнее оптимизировать и в частности у них добавились всякие неявные преобразования, то есть преобразования между массивами, между спанами, read-only спанами и строкой. +735.84 741.32 "Анатолий Кулаков" И эти преобразования неявные могут вступать в небольшой конфликт. +741.32 744.76 "Анатолий Кулаков" То есть это тоже небольшой breaking change. +744.76 747.96 "Анатолий Кулаков" Казалось бы, добавили всего лишь неявные преобразования, а что же такое могло случиться? +747.96 749.32 "Анатолий Кулаков" Ну, могло случиться много чего. +749.32 766.80 "Анатолий Кулаков" Например, когда вы передаете тип, который поддерживает и спан, и другой тип, ну, например, массив, да, вы передаете какой-то массив в некий метод, и этот метод поддерживает и сам массив, и поддерживает спан от этого массива. +766.80 775.40 "Анатолий Кулаков" В общем, раньше было понятно, что вызовется, как не было implicit спана, то вызывался метод с массивом. +775.40 788.12 "Анатолий Кулаков" Сейчас непонятно, потому что массив может передаться как сам, так и сконвертироваться в спан, а компилятор очень любит все конвертировать в спан, потому что это, как я уже сказал выше, такой самый оптимальный для перформанса вариант. +788.12 790.08 "Анатолий Кулаков" Компилятор его пытается засунуть просто везде. +790.08 791.08 "Анатолий Кулаков" Вот. +791.08 793.36 "Анатолий Кулаков" И в эти моменты у вас может быть небольшой breaking change. +793.36 802.28 "Анатолий Кулаков" Ну, опять же, он довольно легко компиляторам выявляется, компиляторам предупреждается, так что никакой критической проблемы быть не может. +802.28 808.56 "Анатолий Кулаков" Максимум у вас там проект не скомпилится с понятными инструкциями, что надо сделать, и это легко переделывается. +808.56 827.48 "Анатолий Кулаков" Из прочих мелочей у нас оператор Keyword, наверное, NameOf, начал поддерживать OpenGenericType, то есть раньше для того, чтобы получить название generic типа, например, лист от int, вам необходимо было указать NameOf, лист от int. +827.48 831.28 "Анатолий Кулаков" И этот оператор, к большому удивлению, возвращал просто лист. +831.28 832.28 "Анатолий Кулаков" То есть он generic параметр отбрасывал. +832.28 837.28 "Анатолий Кулаков" Ну, допустим, такое поведение, так и решили создатели, это окей. +837.28 847.88 "Анатолий Кулаков" Но, опять же, если мы хотим получить просто имя лист, нам не хочется задавать в качестве аргумента лист от int, потому что какая разница, если мы просто хотим название лист получить. +847.88 863.36 "Анатолий Кулаков" Ну, так вот, теперь мы можем это сделать, мы можем сказать NameOf лист от OpenGenericType, ну, то есть поставить просто треугольные скобочки без указания конкретики и нам вернется тот же самый строка лист, что, наверное, иногда бывает удобно. +864.08 874.32 "Анатолий Кулаков" LambdaExpression параметры теперь у нас могут принимать различные модификаторы, такие как ref, in, out, or, ref, readonly и прочее. +874.32 882.96 "Анатолий Кулаков" Раньше они этого делать не умели, поэтому иногда было сложно какие-нибудь интересные лямбды замыкать, например, с каким-нибудь кастомным делегатом, который out параметр требует. +882.96 885.52 "Анатолий Кулаков" Теперь это можно сделать. +885.52 891.84 "Анатолий Кулаков" Мы можем делать теперь больше partial members, наверное, тоже довольно неплохая в практике штука. +891.84 896.64 "Анатолий Кулаков" Я напомню, что partial members очень часто сейчас используются в генераторах. +896.64 899.96 "Анатолий Кулаков" Раньше они были нужны только всяким winform-дизайнерам. +899.96 905.60 "Анатолий Кулаков" Вообще, ну, просто как появились генераторы, partial members приобрели просто вторую жизнь. +905.60 916.84 "Анатолий Кулаков" Сейчас генераторы могут, типа, дополнять ваши классы, ваши методы, ваши свойства различными сгенерированными всякими интересными стейтнами. +916.84 919.28 "Анатолий Кулаков" И чем знаменит новый C#? +919.28 924.28 "Анатолий Кулаков" Тем, что он добавил возможность делать partial'ами конструкторы и ивенты. +924.28 926.88 "Анатолий Кулаков" В общем, этого тоже не было, не поддерживалось. +926.88 933.64 "Анатолий Кулаков" Теперь, пожалуйста, можно делать частичные ивенты, можно делать частичные конструкторы, что открывает, как я уже сказал, возможности для генераторов. +933.64 940.56 "Анатолий Кулаков" Так, еще одно нововведение — это user-defined compound assignments. +940.56 944.92 "Анатолий Кулаков" Все мы, наверное, знаем, что можно перекрывать в C# операторы. +944.92 948.76 "Анатолий Кулаков" Например, оператор плюс, минус, умножить, разделить и так далее. +948.76 953.32 "Анатолий Кулаков" Опять же, на практике этим редко кто пользуется в обычной жизни. +953.32 968.36 "Анатолий Кулаков" Но если вы вдруг сталкиваетесь с какой-нибудь математикой, там с векторами, с тензорами, еще с какими-то кастомными BigInt-типами или еще что-то, вот там операторы очень хорошо используются, перекрыть именно операторы. +968.36 979.96 "Анатолий Кулаков" Потому что можно дать такой нативный синтаксис всяким чужеродным классам и сделать их очень похожими на те, как будто мы прямо в C# они задекларированы, как будто из настоящего BCL вылезли. +979.96 983.00 "Анатолий Кулаков" Поэтому там перекрытие операторов довольно часто используется. +983.00 984.70 "Анатолий Кулаков" В общем, в математике это очень удобно. +984.70 1003.32 "Анатолий Кулаков" Столкнулись люди с тем, что оператор плюс, например, если мы берем какие-нибудь векторы или матрицы и складываем две матрицы через оператор плюс, это не то же самое, что написать «плюс равно», т.е. сложить текущую матрицу с кем-то другим. +1003.32 1018.76 "Анатолий Кулаков" Т.е. когда у нас оператор плюс, у него есть лево и право, там не понимаем, что складываем, то есть понимаем, что складываем и прибавляем в третью переменную, а когда у нас плюс равно, то мы берем текущую ячейку, ее с чем-то складываем и записываем в ту же самую ячейку. +1018.76 1026.60 "Анатолий Кулаков" Кажется, что это одно и то же, но на самом деле в математике для подобной операции существует огромное количество оптимизаций. +1026.60 1039.32 "Анатолий Кулаков" Т.е. если бы можно было перекрыть плюс равно, то для математики это означало бы возможность писать красиво и при этом использовать оптимизации, которые у них в том же есть. +1039.32 1044.28 "Анатолий Кулаков" Например, семды, в общем, под это очень хорошо подходят, чтобы их таким способом оптимизировали. +1044.28 1052.16 "Анатолий Кулаков" И раньше писали класс и делали там метод типа класс какой-нибудь вектор, у него метод add и туда добавляли какие-то значения. +1052.16 1057.08 "Анатолий Кулаков" А хотелось бы логически красиво это писать, плюс равно и добавить туда какое-то значение. +1057.08 1066.96 "Анатолий Кулаков" Ну так вот, теперь мы можем перекрыть не просто плюс, а перекрытие оператор плюс равно и наши любимые математики теперь смогут воспользоваться этой возможностью. +1066.96 1069.96 "Анатолий Кулаков" Естественно, не только плюс равно, но и минус равно и так далее. +1069.96 1074.48 "Анатолий Кулаков" Вот, как только мы перекроем, можно будет какую-то оптимизацию сделать. +1074.48 1088.60 "Анатолий Кулаков" Интересно, что там в комментах всплывал специально вопрос типа, а нормально ли, что мы перекроем оператор плюс и сделаем там что-то и перекроем оператор плюс равно и сделаем там абсолютно что-то другое, т.е. что не связано с плюсом. +1088.60 1096.28 "Анатолий Кулаков" Т.е. соответственно, мы можем получить какой-нибудь класс А плюс класс Б, получаем класс С. +1096.28 1101.44 "Анатолий Кулаков" А если напишем класс А плюс равно Б, то получим класс Д. +1101.44 1104.16 "Анатолий Кулаков" Т.е. абсолютно другое, не то, что рассчитываем. +1104.16 1121.52 "Анатолий Кулаков" И да, подняли спецификацию, и в спецификации ясно написано, что эти операторы могут давать разные значения, т.е. их поведение может быть абсолютно разным, поэтому плюс и плюс равно не обязаны по своим функциональным свойствам совпадать, они вполне могут давать какие-то разные вещи. +1121.52 1126.60 "Анатолий Кулаков" Поэтому там смирились, объявили вот эти новые перекрытия и велели всем пользоваться. +1126.60 1133.60 "Анатолий Кулаков" Более того, уже там для стандартных типов их тоже перекрыли, для симдов, например, прооптимизировали и пустили в массы. +1133.60 1140.48 "Анатолий Кулаков" Так, еще один полезный оператор, который немножко помогает нам упростить стандартные синтаксические конструкции. +1140.48 1154.52 "Анатолий Кулаков" Это null condition assignment, т.е. представьте себе ситуацию, в которой вам нужно проверить юзера и проверить, что если юзер не null, тогда мы имя у этого юзера меняем на какое-то другое. +1154.52 1161.44 "Анатолий Кулаков" Скорее всего, такой частый паттерн, наверное, вы часто с ним сталкивались, т.е. проверить, если перемена не равна null, тогда пошли менять ей какие-то поля. +1161.44 1178.44 "Анатолий Кулаков" И, соответственно, теперь можно написать вместо четырех строчек с вот этим if, скобочки, юзер = name, мы можем написать всего-навсего одной этой строчкой, юзер, поставить вопроситель знак, точка, обратиться к нейму и сказать равно какое-то имя. +1178.44 1185.64 "Анатолий Кулаков" Очень похоже на то, как мы обращаемся к нулябельным свойствам, т.е. мы не знаем, есть там свойство или нет там свойства, мы ставим вопросик и точку. +1185.64 1193.06 "Анатолий Кулаков" Вот, теперь мы можем делать точно так же, но только не с правой части, т.е. не читать это значение, а с левой части присваивать это значение. +1193.06 1204.68 "Анатолий Кулаков" Ну, сначала выглядит непривычно, дико, но, наверное, как только это все устаканится в головах, довольно полезная конструкция, будет довольно часто использоваться. +1204.68 1218.62 "Анатолий Кулаков" А вот этот null condition оператор, его можно применять не только для доступа к свойствам, ну и, например, к индексу в массиве, т.е. поставить вопроситель знак, квадратные скобочки и обратиться к какому-нибудь индексу. +1218.62 1224.24 "Анатолий Кулаков" Поведение будет точно так же, т.е. компилятор проверит его сначала на неравность null, а потом что-нибудь присвоит. +1224.24 1241.00 "Анатолий Кулаков" Вот такие изменения, в принципе, не то чтобы сильно много, но есть полезные, есть хороший extension member, который хотя бы оправдывает выход нового релиза, в отличие от предыдущих, ну и, я думаю, внесет свою лепту в то, как сейчас выглядит язык C# и каким он будет в будущем. +1241.00 1243.88 "Игорь Лабутин" Да, поглядим, посмотрим. +1243.88 1267.48 "Игорь Лабутин" Мы ждем, конечно, чего-то масштабного и прикольного в 15 C# в следующем году, но там будет short-term релиз, который, правда, теперь, напомню, поддерживается те же, сколько у нас, 3 года, да, получается, поэтому… А, нет, он поддерживается до конца следующего LTS, там как-то так было, ну да, те же 3 года, по сути, вот. +1267.48 1268.96 "Анатолий Кулаков" Их там как-то выровняли уже. +1268.96 1276.76 "Игорь Лабутин" Да, да, да, их подровняли, поэтому, в общем, наверное, там тоже может быть что-нибудь интересненькое, а пока начинаем применять 14 C#. +1276.76 1277.76 "Игорь Лабутин" Ну и пойдем дальше. +1277.76 1299.04 "Игорь Лабутин" C#, C#, но без рантайма мы никуда, и рантайм долгое время, если мы вспомним прошлые .NET Conf, было довольно много, ну не то, что хайпа, а фокуса такого и продвижения того, что .NET стал еще быстрее. +1299.04 1329.20 "Игорь Лабутин" Мне, кстати, в этот раз не показалось, что на этом какой-то основной упор, вероятно, сейчас основной упор больше на там искусственном интеллекте и все, что с ним связано, но, тем не менее, JIT-команда не спит, JIT-команда тоже работает, и JIT-команда внесла ряд улучшений в наш рантайм, ну конкретно в JIT, и не только в JIT на самом деле, которые позволяют .NET быть а) быстрее, б) местами может быть кушать немножко памяти поменьше или еще всячески оптимизировать. +1329.20 1330.20 "Игорь Лабутин" Давайте по ним пробежимся. +1330.20 1336.84 "Игорь Лабутин" Начнем, собственно, с JIT-а, с того, что теперь умеет делать JIT-компилятор, того, чего он не умел раньше. +1336.84 1354.98 "Игорь Лабутин" Во-первых, если вы используете структуры и передаете структуры в аргументы функций, то уже прошлая версия .NET умела делать так называемый promotion, когда структура пакуется и передается без того, чтобы ассоциироваться на стэке, а прямо через регистры. +1354.98 1374.06 "Игорь Лабутин" То есть если у вас, например, структура из двух лангов, ну это типичный какой-нибудь там point, например, целочисленный, такой классический из каких-нибудь модельных примеров, тип точка с координатами x, y, то она может передаваться просто через два регистра без необходимости чего-либо ассоциировать на стэке. +1374.06 1385.86 "Игорь Лабутин" Это, понятное дело, максимально быстро, максимально хорошо, и в C# программе выйдет как структура, а по факту это просто она разбирается на запчасти, и каждый field передается отдельно. +1385.86 1400.86 "Игорь Лабутин" Но если мы, например, говорим о структуре, которая не два ланга, а два int, то по некоторым calling convention, вызывающая функция, обязана положить оба int в один регистр. +1400.86 1420.58 "Игорь Лабутин" Регистр это у нас 64-битный, а int 32, ну, казалось бы, что может быть проще, положить два 32-битных int в один 64-битный, но прошлый джит этого не умел, точнее он умел, но он требовал промежуточную запись в память, что как бы нивелирует пользу от того, что мы передаем это через регистры. +1420.58 1435.22 "Игорь Лабутин" Десятый dotnet научился это делать, и теперь нормально передает в такие функции, требующие передачи значений через регистры, более маленькие типы, которые помещаются в один регистр. +1435.22 1437.82 "Игорь Лабутин" Нормально сразу все это складывает. +1437.82 1438.82 "Игорь Лабутин" Дальше. +1438.82 1474.38 "Игорь Лабутин" Работа с циклами улучшилась, с циклами на самом деле довольно много оптимизаций есть самих по себе, но если мы пишем цикл while, ну, а цикл while мы пишем довольно часто, мне кажется, то на самом деле именно while, он довольно неприятен для дальнейшей оптимизации внутри джита, и выгоднее писать do while, то есть выгоднее написать if condition do тело цикла while то же самое condition, то есть один раз проверить на входе через if, а дальше проверять в конце цикла, по разным причинам это чуть проще оптимизируется потом для всяких разных других целей. +1474.38 1521.06 "Игорь Лабутин" И теперь, соответственно, джит это умеет переделывать while, в такой do while с проверкой в ифе, причем он это умеет делать не только глядя на, так сказать, текст программы, потому что раньше это делал не джит, раньше, в принципе, родственник, по-моему, умел такое делать, а джиту достается уже некоторое, так скажем, ну, по сути, или код, вот он теперь умеет делать, глядя на некоторое свое внутреннее представление этой штуки, этого кода, и поэтому в более большом количестве случаев такая оптимизация имеет место быть, которая потом позволит включиться остальным оптимизациям, всякий loop cloning, loop unrolling, вот это все, они как раз хорошо работают с do while, по внутренней причине. +1521.06 1583.38 "Игорь Лабутин" Дальше, в борьбе за скорость, в борьбе за еще более эффективное исполнение, донетт довольно много работает над проблемой идеи виртуализации, то есть в чем у нас идея, мы, конечно, умеем вызывать методы, у нас есть интерфейсы, и любой вызов метода через интерфейс технически может приводить к виртуальному вызову, потому что мы не знаем в рантайме, какой же метод на самом деле, метод какого класса там будет за этим интерфейсом скрываться, и поэтому это делается виртуальный вызов, нужно сходить в таблицу виртуальных функций, посмотреть, что там на самом деле лежит, и вот это все, но, вообще говоря, в JIT есть всякие практики де-виртуализации, если мы твердо знаем по разным причинам, по пропадателям, какой-нибудь профайл данным, либо еще по какой-то причине, что именно в этом месте у нас будет строго известный тип, несмотря на то, что это интерфейс, то JIT умеет в этом случае делать не виртуальный вызов, а вызов конкретного метода, конкретного класса. +1583.38 1609.26 "Игорь Лабутин" Это все было, но, к сожалению, это не работало с массивами, потому что массивы, они реализованы, они как бы реализуют какой-нибудь inumerable, но они его реализуют не в том варианте, как все обычные классы коллекции реализуют inumerable, а все-таки довольно специфически, и поддержка вот этих реализаций интерфейсов для массивов, она реализована глубоко внутри рантайма, и это такое внутреннее знание. +1609.26 1644.06 "Игорь Лабутин" JIT теперь умеет понимать, что, например, у нас в inumerables хранится массив, и тогда умеет де-виртуализировать вызов, понимая, что это массив, ну и там включается, понятно, вся магия и все умения JIT-а оптимизировать работу с массивами, то есть там вынос, проверки для for-циклов каких-нибудь, количество элементов заранее, вот это все, чтобы bound-чеков поменьше было, в общем, вот это все начинает сразу хорошо работать, поэтому это важная штука, или работа на этом не закончена, там есть еще чем позаниматься вокруг массивов. +1644.06 1761.38 "Игорь Лабутин" Дальше улучшился, так скажем, улучшился подход, алгоритм того, как код раскладывается в памяти, то есть у нас есть il, il-код, он примерно плюс-минус один-в-один практически то, как у вас написана программа на C#, просто с транслированной в более низко уровень инструкции, но дальше возникает вопрос, вот у вас есть какой-нибудь код, il-код метод, его нужно преобразовать в ассемблер, понятно, что, условно, если у вас есть if, какое-то условие else, джит имеет возможность либо проверить условие и сделать jump на else ветку, либо он может развернуть условие и сначала написать else ветку, именно в ассемблере, в машинном коде, а потом уже сделать if ветку, например, потому что он считает, что else ветка будет выполняться чаще, благодаря какой-нибудь статистике, или еще что-нибудь в таком духе, вот, но если у вас метод довольно сложный, у вас там много if-ов, каких-нибудь циклов, не дай бог go to встретится внезапно, то вообще поиск оптимального layout'а, оптимального размещения машинного кода для заданной функции — это довольно-таки сложная задачка, потому что джит нужно решить быстро, а по сути она алгоритмически сложная, раньше джит использовал, они это называют reverse post-order traversal, то есть, по сути, они шли с конца и пытались разобраться, ну, построить направленный граф логических блоков кода, кто кого куда вызывает и кто куда может переходить, и из этого составить некоторую более-менее оптимальную расположение кода в памяти, которое там минимизирует бранчи, но при этом не будет делать слишком далеких джампов, ну, в общем-то, есть несколько характеристик, которые нужно одновременно удовлетворить, и все удовлетворить невозможно. +1761.38 1826.62 "Игорь Лабутин" Сейчас в десятом дотнете сделали немножко другой алгоритм, они по сути взяли алгоритм решения задачками выезжора, которое, ну, в общем виде не решается, особенно в формате ограничения времени джита, но там есть некоторые приближения, некоторые эвристики добавили, добавили немножечко информации из profile-guided optimizations, ну, вот этих собранных данных профилятора внутреннего, ну и в результате получился некоторый алгоритм, который строит немножко другое расположение в итоге блоков памяти, но которое считается более оптимальным, которое с одной стороны все еще сохраняет довольно плотную компоновку самого частого пути внутри функции, но при этом пытается относительно минимизировать все-таки расстояние, куда нужно переходов, когда делаются в итоге branch, потому что это позволяет все-таки все держать чуть более локально в памяти. +1826.62 1828.26 "Игорь Лабутин" Надеюсь, это поможет скорости. +1828.26 1836.02 "Игорь Лабутин" А также скорости помогает, конечно же, inlining, то есть вместо того, чтобы вызывать функцию, можно тело ее встроить вместо вызова. +1836.02 1856.70 "Игорь Лабутин" Опять же, там есть проблема, что ее все бесконечно встраивать нельзя, потому что функции на все он становится большими, джампы будут становиться долгими, и все это будет работать совершенно медленно и ужасно просто, потому что будет куча дублирования кода, если вы inlining'ите одну и ту же функцию много раз, и, соответственно, должны быть ограничения. +1856.70 1877.38 "Игорь Лабутин" С другой стороны, если мы inlining'им какую-нибудь функцию, может оказаться так, что открывается простор, например, для девиртуализации, то есть мы inlining'или функцию, когда получают какую-нибудь коллекцию, и выяснили за счет того, что мы ее inlining'или, что в рамках вызываемой функции, вызывающей функции коллекция, всегда будет массивом, и тогда мы сможем девиртуализировать массив. +1877.38 1881.94 "Игорь Лабутин" Это все, конечно, хорошо, но заранее не угадаешь. +1881.94 1895.18 "Игорь Лабутин" Поэтому теперь JIT пытается понять, что может помочь будущей девиртуализации, также они разрешили inlining'ить try_finally, точнее, функции, в которых есть try_finally. +1895.18 1905.66 "Игорь Лабутин" Это довольно частая конструкция благодаря юзингу, то есть catch, он как бы сразу, я так понимаю, все еще это блокер для inlining'инга, если там есть именно явно написаный catch. +1905.66 1908.34 "Игорь Лабутин" Но если просто try_finally, то теперь такие функции будут inlining'иться. +1908.34 1937.70 "Игорь Лабутин" Если, опять же, JIT понимает, что вы вызываете функцию, у нее есть какие-то возвращаемые значения, если он ее inlining'ит, понятно, что, возможно, он должен какие-то временные переменные объявить, еще что-нибудь, если он понимает для таких временных переменных, что типы тоже всегда одни и те же, то это тоже хороший повод запомнить это, потому что это может включить девиртуализацию. +1937.70 1951.94 "Игорь Лабутин" Ну и, опять же, в зависимости от данных про филятора, то есть данных, собранных во время исполнения, может быть поднята граница размера функции, до которой происходит inline. +1951.94 1966.94 "Игорь Лабутин" То есть совсем большие функции inline смысла нет, но если по данным про файла получается, что такая функция вызывается очень часто, то для этой функции граница будет поднята, она будет заinlining'ина, и если это приведет к хорошим оптимизациям, ну, значит, хорошо. +1966.94 1986.98 "Игорь Лабутин" В общем, JIT становится более полагаться на эвристике данных про файлора внутри себя, но, видимо, это необходимое изменение, чтобы все эти сложные, довольно-таки, точнее как, простые сами по себе, в отдельности, но сложно комбинируемые оптимизации, хорошо работали все вместе. +1986.98 2018.18 "Игорь Лабутин" Дальше, процессоры у нас не стоят на месте, все время появляются какие-то новые наборы инструкций, так для x64 процессоров появился новый набор инструкций avx10.2, но в релиз ноутсах написано забавно, что мы, конечно, все поддержали, но поскольку железо с такими инструкциями пока еще не доступно, то мы все это задезаеблили, но уже поддержали, но пока задезаеблили by default, вероятно, они на каких-то, я не знаю, инженерных образцах тестировали, непонятно как это все… +2018.18 2021.34 "Анатолий Кулаков" Ну или на эмуляторах, наверно, что эмуляторы какие-то… +2021.34 2032.70 "Игорь Лабутин" Ну, наверное, наверное, не знаю, в общем, как-то странно там, типа прям в релиз ноутсах написано, что вот, мы поддержали avx10.2, но, короче, hardware isn't yet available, типа support… +2032.70 2034.78 "Анатолий Кулаков" Ну они не работают, типа, поддержали, но… +2034.78 2039.10 "Игорь Лабутин" Ну и support is disabled by default, ну, ладно, посмотрим, но опять +2039.10 2043.74 "Анатолий Кулаков" же… Не, ну зато всем рассказали, какие они крутые, переди планеты все и все поддержали, это же тоже реклама. +2043.74 2052.70 "Игорь Лабутин" Это да, ну и плюс все-таки это LTS, он 3 года будет жить, за 3 года-то может и появится уже железо, а они там, оп, флажок включили и все, заработало, все прекрасно. +2052.70 2053.70 "Игорь Лабутин" Ну, может и тогда. +2053.70 2075.46 "Игорь Лабутин" Дальше, а локации на стейке, напомню, ну, как это, давняя мантра, то, что у нас там структуры на стейке, объекты в хипе, да, хотя структуры тоже могут быть в хипе, если боксятся, сейчас потихонечку уходит в прошлое, потому что дотнет пытается, если он может доказать, что заданный объект не покидает пределы функций, аллоцировать его на стейке, даже если это референс-тайп. +2075.46 2095.14 "Игорь Лабутин" Вот, в 10-м дотнете добавилась такая опция, точнее, эвристика для того, чтобы аллоцировать на стейке небольшие массивы типов значений, то есть value-тайпов, и небольшие массивы ссылочных типов, они тоже будут аллоцироваться прямо на стейке. +2095.14 2112.38 "Игорь Лабутин" И более того, улучшился escape analysis, то есть если теперь не только, допустим, как я говорю, там маленький массив аллоцируется на стейке, но раньше, если мы маленький массив, например, обернем в структуру, то уже поле структуры не анализируется, что там на самом деле лежит. +2112.38 2127.62 "Игорь Лабутин" Теперь оно анализируется, то есть если у нас есть структура, которая локальная, гарантируется никуда не уходит из функции, и у нее в поле лежит, например, маленький массив, то он тоже будет аллоцирован на стейке сразу, а не только сама структура. +2127.62 2141.42 "Игорь Лабутин" Ну и для делегатов мы тоже подробно обсуждали, что делегаты в дотнете приводят к аллокации на самом деле двух сущностей, одна это, собственно, сам объект func, да, делегата, собственно, ссылка на метод, которым это исполняется, и второй объект — это замыкание. +2141.42 2150.46 "Игорь Лабутин" Замыкание пока все так же аллоцируется на хипе, а вот объект делегата будет стараться аллоцироваться на стейке, если есть доказательства, что он не покидает пределы функции, где это используется. +2150.46 2158.26 "Игорь Лабутин" В нейте-фаоте есть некоторые улучшения, но не буду поружаться там совсем технической детали. +2158.26 2167.06 "Игорь Лабутин" Ну и для ARM64 улучшили барьеры записи, это техника, которая позволяет немножко ускорить garbage collector. +2167.06 2183.82 "Игорь Лабутин" Смысл в чем, что garbage collector у нас поколенческий, и, по-моему, каждый раз обходить все объекты во всех кучах — это долго и дорого, и поэтому garbage collector старается обходить только, понятно, ограничиваться молодым поколением. +2183.82 2190.18 "Игорь Лабутин" Но нам же нужно знать, есть ли на объект молодого поколения ссылки из более старшего поколения. +2190.18 2209.94 "Игорь Лабутин" И поэтому в .NET реализован механизм write barrier, который каждый раз, когда мы куда-то что-то присваиваем, ссылку на объект куда-нибудь, он помечает определенным образом тот регион, куда мы это присвоили, что вот там, возможно, есть ссылка на объект младшего поколения. +2209.94 2215.10 "Игорь Лабутин" И EGC, когда собирает мусор, он знает, что вот такие региончики надо проверить, и в них проверить ссылки. +2215.10 2221.06 "Игорь Лабутин" То есть не нужно проверять все второе поколение, или первое поколение, если мы собираем нулевое, а только часть из него. +2221.06 2230.58 "Игорь Лабутин" Все хорошо, на x64 это там все работает, там есть несколько вариантов реализации этих write barrier, более того, он может динамически, рандомно переключаться между ними. +2230.58 2245.42 "Игорь Лабутин" А вот для ARM64 такого не было, ну в смысле, не было такого разнообразия, теперь есть, и это позволило снизить длину пауз GCE с 8 до, в смысле, до 8-20%. +2245.42 2259.58 "Игорь Лабутин" Соответственно, улучшили, ускорили сборку мусора, увенчали паузы, что хорошо, видимо, за счет более точной разметки того, какие объекты, какие регионы из старшего поколения надо смотреть. +2259.58 2278.78 "Игорь Лабутин" Вот примерно такие изменения у нас в рантайме, так что в основном все про перв, все про перв, каких-то особо больших заявлений тем того, что мы стали опять в 10 раз быстрее, чем какой-нибудь питон, я вроде не видел, но может и пропустил, но Blueprint явно становится быстрее. +2278.78 2284.58 "Анатолий Кулаков" Ну да, с каждым релизом лучше и лучше, быстрее и быстрее. +2284.58 2290.50 "Анатолий Кулаков" Ну что ж, рантайм он становится быстрее не только для C#, но и для всех других языков, в частности, из других у нас F#. +2290.50 2303.66 "Анатолий Кулаков" Разберемся, что нового появилось в 10 F#, к сожалению, совсем мало всего, никаких больших фич нет, поэтому какого-нибудь отдельного специалиста по F# мы сегодня даже не позвали, но давайте посмотрим, а что есть. +2303.66 2312.98 "Анатолий Кулаков" Так, во-первых, появился scope warning suppression, то есть это возможность подавить какой-то warning в пределах нескольких строчек, то есть не всего файла. +2312.98 2313.98 "Анатолий Кулаков" Что было раньше? +2313.98 2323.66 "Анатолий Кулаков" Раньше можно было написать no warn, и эта директива работала на весь файл, который шел после этой директивы. +2323.66 2330.42 "Анатолий Кулаков" Теперь можно сказать warn on и включить обратно тот warning, который мы подавили строчкой выше. +2330.42 2346.62 "Анатолий Кулаков" Таким образом, мы можем вымерить какой-то определенный скоп, какое-то определенное количество строк и гасить warning только в них, а весь остальной файл продолжает анализироваться, что спасет от каких-нибудь нежелательных подавлений, из-за которых можно пропустить ошибку. +2346.62 2354.18 "Анатолий Кулаков" Следующее нововведение – это появился удобный метод, с помощью которого мы можем раскрыть или закрыть свойства. +2354.18 2370.94 "Анатолий Кулаков" То есть, допустим, у нас есть какое-то стандартное свойство, у него есть getter и setter, и очень частая такая ситуация у нас была, что мы хотим getter сделать публичным, чтобы могли это свойство читать, а setter – приватным, чтобы могли только какие-нибудь внутри функции записывать туда. +2370.94 2376.22 "Анатолий Кулаков" Так вот, чтобы раньше это сделать, необходимо было в f# городить такой довольно сложный синтексис через лямбды. +2376.22 2381.78 "Анатолий Кулаков" То есть, getter там равно выписывать это из balance, там заводить back-in-field. +2381.78 2392.26 "Анатолий Кулаков" И у setter точно так же, то есть полностью расписывать, как мы там, например, все шарпи расписываем, это все с back-in-field, но мы расписываем только, если мы хотим обратиться. +2392.26 2399.70 "Анатолий Кулаков" Вот бедные ф-шарписты обязаны были расписывать, даже если они захотели поменять просто access modifier к этому методу. +2399.70 2404.58 "Анатолий Кулаков" Вот, эту несправедливость улучшили, почистили, и теперь все становится практически так же, как в шарпах. +2404.58 2408.90 "Анатолий Кулаков" Можете сказать public get, private set, и при этом все будет работать. +2408.90 2418.70 "Анатолий Кулаков" Даже более того, можно объявить какое-нибудь даже значение по умолчанию, то есть можно сказать member, while balance = 0, и значение по умолчанию прямо будет в этой же строчке. +2418.70 2422.46 "Анатолий Кулаков" То есть на одной строке можно и дефолт задать, и access modifier указать. +2422.46 2425.18 "Анатолий Кулаков" В общем, полная красота получилась. +2425.18 2445.98 "Анатолий Кулаков" Так, теперь можно стало использовать struct-based value option at для всяких опциональных параметров, так как теперь, так как это struct, теперь можно использовать это, это позволит избежать heap allocation, то есть более по памяти станет вот эта операция толерантная. +2445.98 2458.10 "Анатолий Кулаков" Появился, в шарпи 10 появился tail call, появилась оптимизация для computation expression, то есть теперь внутри computation expression тоже работает прекрасная tail call оптимизация. +2458.10 2474.46 "Анатолий Кулаков" Вот интересная штука, это attribute target enforcement, то есть представляете, так в шарпи была такая ситуация, что мы могли навесить атрибут на любой член, несмотря на то, куда этот атрибут позволял. +2474.46 2483.42 "Анатолий Кулаков" То есть у каждого атрибута есть свойства target, типа кому он применимо, к классам, к свойствам, к филдам, к методам. +2483.42 2492.38 "Анатолий Кулаков" Так вот, насколько я понял, F# вообще никак не проверял это свойство, то есть атрибут можно было навесить куда угодно. +2492.38 2497.14 "Анатолий Кулаков" Естественно, он не работал, если вы навесили неправильно, но никто вам об этом не скажет. +2497.14 2509.66 "Анатолий Кулаков" Из-за этого, например, были часто ошибки в тестах, потому что атрибут, который навешивается на метод и показывает, что это тест, иногда могли навесить на свойства. +2509.66 2517.10 "Анатолий Кулаков" Это сделать в F# достаточно просто, ибо можно убрать просто скобочки, и метод тут же превращается в свойства. +2517.10 2520.78 "Анатолий Кулаков" Вот, из-за этого были проблемы, да, тесты какие-то не находились. +2520.78 2533.90 "Анатолий Кулаков" Так вот, эту несправедливость устранили, в 10 F# компилятор наконец начал выдавать warning и говорить, что атрибут не может быть применен к свойству, допустим, он рассчитан на то, чтобы его спрятали к методу. +2533.90 2538.78 "Анатолий Кулаков" Вот, теперь, наверное, у F# приступе появляется тонна warning. +2538.78 2544.02 "Анатолий Кулаков" В превью запустили фичу, которая называется параллельная компиляция. +2544.02 2548.46 "Анатолий Кулаков" Ее можно включить с помощью специального свойства в проекте. +2548.46 2549.86 "Анатолий Кулаков" Что эта штука делает? +2549.86 2554.50 "Анатолий Кулаков" Она выстраивает граф всех типов и зависимости между ними. +2554.50 2558.78 "Анатолий Кулаков" Она делает параллельную генерацию или кода, т.е. +2558.78 2566.70 "Анатолий Кулаков" по сути компиляцию F# или, и также параллельную оптимизацию, то есть параллельно оптимизирует тот код, который сгенерировала. +2566.70 2577.82 "Анатолий Кулаков" И это, естественно, вот эта вся параллельность очень сильно увеличивает время, т.е. уменьшает время компиляции, очень сильно увеличивает скорость, с помощью которой эта вся штука запускается. +2577.82 2593.74 "Анатолий Кулаков" Это пока экспериментальная штука в превью, в планах включить ее в дотнете 11, в общем, там она должна заработать на полную катушку, а пока просят сообщество посмотреть, как она работает, как она оптимизирует тех, кого есть возможность на больших каких-нибудь проектах запустить. +2593.74 2596.86 "Анатолий Кулаков" Попробуйте, расскажите, может, потом это для C# как-то тоже будет применимо. +2596.86 2610.98 "Анатолий Кулаков" Ну, в принципе, на этом и все, вот таких вот никаких глобальных изменений нет, очень есть приятные улучшения, очень есть приятные дополнения, небольшие оптимизации, ну и, естественно, все, что мы получим от библиотек, от рантайма, перформансы, стабилити и все такое. +2610.98 2629.10 "Игорь Лабутин" Ну, только что, если, может быть, не совсем все, если джит там больше затачивается в каком-то смысле на какие-то конструкции, которые он в основном видит от Рослина, то на F#, может быть, не так будет оптимально прямо работать, но, конечно, в целом стараться будет. +2629.10 2645.90 "Игорь Лабутин" Так, давай дальше, у нас тем всяких разных много и дальше у нас на очереди SDK и Tooling, все, что касается, так скажем, того, с чем, как вы с дотнетом взаимодействуете из командной строки либо проектных файлов. +2645.90 2650.38 "Игорь Лабутин" И тут довольно много всяких разных изменений, улучшений. +2650.38 2704.98 "Игорь Лабутин" Во-первых, можно теперь, если вы создаете дотнет тулы, а я напомню, что дотнет тулы — это такие специальные NuGet-пакеты, которые вы можете собрать, поставить потом к себе либо кому-то еще на компьютер, и у вас появляется тул, который можно запустить через команду dotnet, то есть практически все расширения к команде dotnet — это как раз те самые дотнет тулы, и вы теперь можете их опубликовать сразу в один пакет вместе с несколькими рантайм-айдентифайрами в едином пакете, и в этом едином пакете будут подходящие бинарники, собранные для всех платформ, которые вы укажете, и когда вы это все будете ставить на нужный комп, соответственно, dotnet.com.online, он выберет нужный на самом деле тул, либо в момент установки, либо когда вы будете запускать, если это одноразовое выполнение, будет выбран правильный бинарничек, и именно он и запустится. +2704.98 2710.74 "Игорь Лабутин" Это удобно для авторов, кажется, потому что можно только один пакет собирать, и все. +2710.74 2733.62 "Игорь Лабутин" Дальше, если вы не хотите ставить тул, а просто вам нужно его один раз выполнить, например, такое может быть внутри какой-нибудь CI-сборки, когда вы в докер-контрейнере что-то один раз выполнили, ставить нет смысла, появилась команда dotnet.tool.exec, и дальше все то же самое, как вы обычно запускаете, указываете какой тул, все его аргументы, и он выполнится один раз. +2733.62 2758.90 "Игорь Лабутин" А если же наоборот, вы хотите запускать не через dotnet.tool что-нибудь, то у нас мы подробно рассказывали про новый скрипт, который называется dnx, который позволяет просто запустить все плюс-минус автоматически, ну в смысле что поменьше писать, dotnet.tool, это все, чтобы не писать, можно просто писать dnx и нужная команда, и она выполнится. +2758.90 2773.02 "Игорь Лабутин" Далее, теперь для всех команд можно передать аргумент --cli --schema, и вам вернется json, который описывает все возможные команды и подкоманды, и аргументы этой команды. +2773.02 2778.42 "Игорь Лабутин" Удобно, если вы хотите взаимодействовать с командочками в каком-то более автоматизированном виде. +2778.42 2810.50 "Игорь Лабутин" Дальше, если вы пишете msbuild-таски, то по-моему как раз в прошлом выпуске мы рассказывали, что они бывают двух видов, одни которые основаны на dotnet-фреймворке, другие которые основаны на обычном дотнете, и разница нужна, потому что Visual Studio все еще выполняет все на dotnet-фреймворке, теперь появилась возможность это все выполнить даже msbuild-овые таски, написанные для обычного дотнета, выполнять в фреймворковом msbuild-е с помощью специального аргумента task_factory, когда вы указываете using_task. +2810.50 2841.30 "Игорь Лабутин" При этом есть переменная, в property, точнее, если правильной терминологией следовать, называемая msbuild_runtime_type, которая принимает либо full, либо core, два значения, и соответственно можно через conditional using_task сделать так, что вы сможете запустить task in process, если вы запускаете ваш проект из-под дотнетного msbuild-а, или в out-of-process, если вы его запускаете из студийного, ну, таким образом, получится более-менее универсально. +2841.30 2877.50 "Игорь Лабутин" Для приложений, single-file-аппликейшенов, только это не которые single-file-publishers, а которые можно просто написать program.cs или application.cs, вы можете его запустить, dotnet run application.cs, а теперь вы можете даже запублишить, вы можете сказать don't publish application.cs, по дефолту выбирается native-out target, то есть у вас из вашего application.cs получится в винде, например, application.exe, который не требует ничего, то есть можно ваш небольшой скриптик на C# скомпилировать в нативный бинарничек. +2877.50 2889.98 "Игорь Лабутин" Если вам не нужен out, то можно через специальную проперти в самом cs-файле, через решеточку указать publish out false, ну и тогда не будет вам out-a. +2889.98 2916.22 "Игорь Лабутин" Можно внутри этих single-file-аппликейшенов ссылаться на проекты, можно доступаться до пути, откуда вы запустились, и можно даже прямо в этом cs-файлике указать специальным синтаксисом, так называемый shebang, то есть в первой строчке пишется специальная конструкция, которая в итоге позволит вам ваш cs-файлик запускать прямо напрямую, без необходимости писать какого-либо префикс, dotnet или dotnext или еще что-нибудь. +2916.22 2922.34 "Игорь Лабутин" Получится такой прям скрипт на C# практически. +2922.34 2942.34 "Игорь Лабутин" Дальше, если вы используете nuget-audit, мы про него тоже рассказывали где-то несколько месяцев назад, то в нем теперь есть опция убрать ненужные пакеты, которые вам поставились, точнее, независимости на которые писались у вас, потому что вы сослались на фреймворк какой-нибудь. +2942.34 2970.14 "Игорь Лабутин" То есть я напомню, что когда мы пишем проект, мы обычно не ссылаемся не просто на nuget-пакеты, а сначала у нас идет ссылка на какой-нибудь фреймворк, то есть мы там говорим, что мы будем писать ASP.NET Core-ное приложение или мы там будем писать Blazor-приложение, то есть это называется target-framework-monitor.tfm, короче, и вот он может притащить довольно много зависимостей по факту, которые вы не используете, и вот nuget-audit умеет понимать, кого вы не используете, и выкинуть такие из зависимостей. +2970.14 2980.98 "Игорь Лабутин" Соответственно уменьшается список библиотек, которые нужно проверять на допустим какие-нибудь security-проблемы, еще что-нибудь, то есть самому nuget-audit меньше работы. +2980.98 2985.94 "Игорь Лабутин" Включена эта штука по дефолту, когда вы таргетите что-то больше, чем десятка, ну либо равные десятки. +2985.94 2999.66 "Игорь Лабутин" Для собственного dotnet-тула, командлайнового, добавили некоторое количество синонимов, чтобы вы теперь не пытались вспомнить, что писать сначала. +2999.66 3008.26 "Игорь Лабутин" То есть первые команды, которые добавлялись в dotnet, они добавлялись, ну скажем так, без какой-либо системы, я бы сказал. +3008.26 3015.26 "Игорь Лабутин" То есть, например, для того, чтобы добавить nuget-пакет через command-line в ваш проект, нужно было написать dotnet-add-package, ну или указать название nuget-пакета, вот это все. +3015.26 3026.90 "Игорь Лабутин" Но для некоторых, например, подкоманд, нужно было писать наоборот, by, то есть dotnet, потом как бы сущность, над которой мы делаем действие, а потом действие. +3026.90 3042.94 "Игорь Лабутин" И поэтому, чтобы привести все к единому знаменателю, то есть они это назвали noun-first-form, то есть сначала существительное, потом глагол, для таких вот команд, как dotnet-add-package добавили теперь синонимы, можно писать теперь dotnet-package-add, или dotnet-package-delete, или что-нибудь в таком духе. +3042.94 3047.78 "Игорь Лабутин" Так что теперь, ну вы просто будете помнить, что всегда пишете сначала существительное, а потом глагол. +3047.78 3049.78 "Игорь Лабутин" Это типа правильно и единообразно. +3049.78 3068.06 "Игорь Лабутин" Для всяких ли команд, которые поддерживают флаг интерактив, он теперь по дефолту включен, если dotnet понял, что вы в терминале, который позволяет что-то интерактивное, он будет вас спрашивать всякие вопросы, ну примерно как вот dotnet new делает, он там может позадавать вопросы. +3068.06 3072.50 "Игорь Лабутин" Вот теперь по дефолту будут другие команды так делать, если им есть что спросить. +3072.50 3092.54 "Игорь Лабутин" Вы можете с помощью команд dotnet-completions-generate и указав название shell, сгенерить completion, тап-completions, т.е. скрипты, которые нужно выполнить в скрипте инициализации вашего shell, чтобы у вас появился нормальный completion для dotnet-команд. +3092.54 3110.86 "Игорь Лабутин" Если вы публикуетесь из командной стройки, то теперь не нужно в project-файле ставить проперцию enable-sdk-container-support, можно просто написать dotnet-publish/tdv.publish-container, и у вас получится container-image прямо сразу из команд-лайна, раньше так нельзя было. +3110.86 3139.90 "Игорь Лабутин" При этом, если вы хотите контролировать, какой формат имиджа вы генерите, docker или oci, то это все еще надо делать через, то это теперь можно сделать через проперцию внутри csprojump, называется container-image-format, ну и microsoft-testing-platform, я не помню, рассказывали ли мы что-то про testing-платформ или нет, мне кажется, мы немножко где-то это затрагивали, в общем, теперь эта штука поддержана в dotnet-test, поэтому просто будет работать. +3139.90 3166.42 "Игорь Лабутин" В общем, вот так вот, в tool-ах, как всегда, каких-то прям супербольших нововведений или мега-фичей нет, мелочь тут, мелочь там, ну полируют, наводят порядок, убирают какие-то старые последствия немножко может быть бездумного раннего добавления команд типа dotnet-add-package, чтобы все это было более консистентно и понятно и удобно для использования. +3166.42 3185.42 "Анатолий Кулаков" Ну, среда вокруг становится более приятная для этих мелочей и удобнее им пользоваться, в принципе, что тоже самое можно сказать и про библиотеки, они такие невидимые наши помощники, мы их каждый день может быть и не замечаем, но на самом деле они есть, они вокруг нас и мы их каждый день используем. +3185.42 3192.06 "Анатолий Кулаков" Давайте же посмотрим, что изменилось в библиотеках, когда к нам поставили dotnet-10. +3192.06 3226.40 "Анатолий Кулаков" Прежде всего, не знаю почему, а, знаю почему, security, у нас много чего интересного там произошло, но можно отметить постквантум-криптографию, которая появилась в dotnet-10, про нее писали опять же много статей, про то, что наконец есть постквантум-криптография и ее уже рекомендуется всем использовать, потому что как только появятся квантовые компьютеры, мы все умрем, а квантовую криптографию, то есть антиквантовую криптографию можно уже использовать сейчас, то есть можно готовиться к этому моменту, чтобы все-таки не умереть. +3226.40 3249.18 "Анатолий Кулаков" И в dotnet-10 у нас есть три новых асимметричных алгоритма – mlchem, mldsa и slhdsa, вот их можно вязать, ими можно пользоваться, есть примеры, может быть, смотрите, если вы истинный параноик, то может быть стоит присмотреться и поменять все ваши шифрования, все ваши пароли, все ваши алгоритмы, перехешировать все на новый постквантум алгоритм. +3249.18 3259.74 "Анатолий Кулаков" Так, пойдем более к житейским вещам, это numeric ordering для сравнения строк, прекрасная штука, тоже удивительно, почему ее так долго не было, давно ждал, давно хотел. +3259.74 3343.68 "Анатолий Кулаков" А что из себя эту представляет, ну, представим, вам нужно отсортировать строки, и в этих строках иногда встречаются чиселки, ну, допустим, число 2 и число 10, ну, очевидно, что 2 меньше 10, значит, если мы сортируем по возрастанию, то 2 должно идти перед 10, ну, с точки зрения строк, мы сравним сначала первый чар, то есть первый символ, и символ единичка из числа 10, оно меньше двойки, и по факту будет 10 идти первым, потому что единичка меньше двойки, вот, визуально, ну, то есть логически это, логично, это правильно, но визуально это смотрится довольно странно, именно поэтому в современных операционных системах, допустим, если вы хотите отсортировать какие-нибудь ваши файлики или картинки, то сейчас обычно отсортируется все именно в Numeric Ordering, то есть у вас там будет Image, и будет 01, 02, 03, 04, и так по порядочку, несмотря на то, что с точки зрения строк называется, ну, то есть сортируются они совершенно не так, потому что Numeric сортировка, она очень приятна для пользователей, то есть на практике она очень хороша, то же самое она сделает, например, с строчкой 2 и 02, с точки зрения Numeric Ordering, это одинаковые числа, с точки зрения какого-нибудь не Numeric Ordering, а это строки абсолютно разные, и сортироваться они тоже будут абсолютно по-другому. +3343.68 3352.32 "Анатолий Кулаков" Вот, теперь мы можем это сделать, то есть раньше и существовали, естественно, алгоритмы, которые можно было скачать в библиотеке, которые можно было подключить, а теперь мы можем это делать прямо из коробки. +3352.32 3368.56 "Анатолий Кулаков" Для этого достаточно создать стринг Comparer, специальным Comparer Options Numeric Ordering, и вы получите Comparer, который можете передавать вам многие места, которые требуют сравнения, сортировки, поиска и прочего-прочего. +3368.56 3382.28 "Анатолий Кулаков" Так, пойдем к JSON, в JSON много всего интересного появилось, например, можно задать Reference Handling для JSON Source Generator. +3382.28 3383.54 "Анатолий Кулаков" Зачем это может быть нужно? +3383.54 3394.00 "Анатолий Кулаков" Когда вы пользуетесь Source Generator для создания JSON стерилизатора, то сгенерированный код, находя циклы во время стерилизации, бросает исключение. +3394.00 3401.68 "Анатолий Кулаков" Это не всегда нам нужно, поэтому появилась возможность настраивать это поведение с помощью как раз свойства Reference Handler. +3401.68 3407.44 "Анатолий Кулаков" Вы можете настраивать там, стоит бросать исключение или не стоит. +3407.44 3412.56 "Анатолий Кулаков" Появилась опция, которая позволяет запретить дублирование свойств в JSON. +3412.56 3423.88 "Анатолий Кулаков" Дело в том, что JSON-спецификация никак нам не рассказывает о том, а что же делать, если вдруг в JSON появится в одном объекте несколько свойств с одинаковыми именами. +3423.88 3433.92 "Анатолий Кулаков" Если мы представим C# класс, то там два свойства с одинаковым именем существовать не могут, компилятор сразу нам выдаст предупреждение, ошибку и всячески поругает. +3433.92 3441.80 "Анатолий Кулаков" В JSON, естественно, можно, через строчку или даже рядышком, никто не запрещает, и поведение здесь абсолютно недетерминированное. +3441.80 3445.52 "Анатолий Кулаков" То есть, какое значение мы должны взять, если значение этих свойств различается? +3445.52 3449.60 "Анатолий Кулаков" Первое, второе, десятое или может быть среднее арифметическое высчитать? +3449.60 3451.32 "Анатолий Кулаков" Абсолютно непонятно. +3451.32 3458.48 "Анатолий Кулаков" Поэтому в DotA 10 появилось специальное JSON-serialized options, которое называется allow-duplication-properties. +3458.48 3467.16 "Анатолий Кулаков" И если вы позволите duplication-property сам существовать, то это будет то же самое поведение, которое сейчас там по умолчанию. +3467.16 3474.08 "Анатолий Кулаков" Если вы не позволите такой штуки происходить, то будет выброшена JSON-exception, то есть будет выброшена ошибка. +3474.08 3479.16 "Анатолий Кулаков" Это нужно для того, чтобы как раз более строгие модельки держать, более строгие модельки дистиллизовать. +3479.16 3487.00 "Анатолий Кулаков" Появилась еще такая прекрасная штука, как strict JSON-serialization options. +3487.00 3488.36 "Анатолий Кулаков" Что это такое? +3488.36 3497.32 "Анатолий Кулаков" Мы знаем, что в JSON-е существует очень много опций, вы можете настроить там, как отображаются свойства, как сериализуются различные значения и множество-множество всего другого. +3497.32 3502.96 "Анатолий Кулаков" В общем, этих опций там уже десятки, если может тоже даже и не сотни. +3502.96 3505.40 "Анатолий Кулаков" Все их настраивать обычно люди ленятся. +3505.40 3515.68 "Анатолий Кулаков" Обычно в компаниях есть какой-то специальный JSON-serialization options для компаний, он там где-то настроен один раз, в какую-то библиотеку заложен и все его используют. +3515.68 3520.20 "Анатолий Кулаков" Такие же точно преднастроенные пресеты есть и в дотнете. +3520.20 3533.32 "Анатолий Кулаков" Их сейчас по-моему там два или три, и вот добавился новый пресет, который называется strict, то есть это пресет опций, который вам позволяет использовать себя в определенных условиях. +3533.32 3542.70 "Анатолий Кулаков" Данный именно пресет strict позиционируется для того, чтобы использовать его как best practices для как раз децерализации. +3542.70 3546.12 "Анатолий Кулаков" Что же он из себя такого представляет? +3546.12 3551.00 "Анатолий Кулаков" Ну, у него включены или выключены, настроены определенные свойства. +3551.00 3552.00 "Анатолий Кулаков" Какие? +3552.00 3559.28 "Анатолий Кулаков" JSON Unmapped Member Handling, то есть выключен, да, этот флажок выключен. +3559.28 3569.68 "Анатолий Кулаков" Это нам значит, что если мы вдруг встретим какой-то объект со свойствами, про который мы не знаем, то есть мы не знаем, как децерализировать, как их читать, куда их складывать, то будет выпущено исключение. +3569.68 3578.24 "Анатолий Кулаков" Allow Duplicate Properties – это как раз новое свойство, про которое я сегодня упоминал, оно выключено, то есть никаких дублирующихся со свойств быть не может. +3578.24 3581.64 "Анатолий Кулаков" Если дублирующиеся свойства, значит к нам пришла какая-то кривая моделька. +3581.64 3583.80 "Анатолий Кулаков" Идите и почините модельку. +3583.80 3596.20 "Анатолий Кулаков" Также включен Binding Preserve Case-Sensitive Properties, то есть соблюдается, не меняется case-sensitive режим, то есть именно регистр имен весь сохраняется. +3596.20 3605.32 "Анатолий Кулаков" Разрешен флаг Respect Nullable Annotations, то есть мы учитываем те nullable атрибуты, которые у нас навешаны над нашей моделью. +3605.32 3613.52 "Анатолий Кулаков" И Respect Required Constructor Parameters, то есть обязательные параметры в конструкторе тоже должны учитываться. +3613.52 3623.68 "Анатолий Кулаков" В общем, вот такой набор интересный, который включает максимум вообще строгости, которая сейчас есть, у нас только в G7 Options. +3623.68 3642.36 "Анатолий Кулаков" Кстати, обратите внимание, очень многие разработчики наивно полагают и рассказывают на собеседованиях, что якобы Required Keyword что-то обозначает в рантайме, то есть как будто там кто-то будет проверять, что это свойство обязательно заполнится после создания объекта. +3642.36 3647.80 "Анатолий Кулаков" Или допустим Init свойство тоже будет обязано заполниться сразу после создания объекта. +3647.80 3652.52 "Анатолий Кулаков" В общем, все это чушь полная, никто вам ничего в рантайме не гарантирует. +3652.52 3663.76 "Анатолий Кулаков" В частности, дистиллизатор по умолчанию ничего этого не учитывает, ни Required, ни Init, ничего, до тех пор пока вы опять же не включите вот это свойство, Respect Required Constructor Parameters. +3663.76 3677.40 "Анатолий Кулаков" Вот, поэтому, если вы рассчитываете на нормальную nullable reference type обработку, то про вот эти два кейворда можете в принципе вообще забыть, они ничего не делают, они только в Compile Time как-то помогают разработчикам. +3677.40 3680.12 "Анатолий Кулаков" Все довольно простая мелочь. +3680.12 3681.12 "Анатолий Кулаков" Вернемся к нашему пресету. +3681.12 3690.88 "Анатолий Кулаков" Так, вот этот пресет, Strict который, он совместим на чтение с другим пресетом, который называется Default. +3690.88 3692.12 "Анатолий Кулаков" Что это значит? +3692.12 3709.40 "Анатолий Кулаков" Это значит, что объект засилизованный с помощью дефолтного пресета, что происходит по дефолту естественно, может быть дистиллизован Strict, то есть наш дефолтный пресет такой прекрасный и такой хороший, что он не добавляет случайно дублирующиеся свойства или не добавляет тех свойств, которых у него нет. +3709.40 3712.60 "Анатолий Кулаков" То есть, по сути, все, что он записал, Strict может прочитать. +3712.60 3718.08 "Анатолий Кулаков" Поэтому такая хорошая пара, хороший вариант, когда вы дефолтом допустим пишете, а Strict читаете. +3718.08 3721.88 "Анатолий Кулаков" Ну, я думаю, если вы запишите Strict, то тоже ничего страшного не произойдет. +3721.88 3726.24 "Анатолий Кулаков" Так, JSON-силизатор начал поддерживать PipeReader. +3726.24 3734.00 "Анатолий Кулаков" PipeReader, это... вообще нужны PipeReader, мало мы сталкиваемся в подкастах с пайпами почему-то. +3734.00 3736.08 "Анатолий Кулаков" Надо бы, наверное, как-то их просветить получше. +3736.08 3744.00 "Анатолий Кулаков" Но если кратко, то пайплайны - это специальная такая штука, которая создана для high-performance и put-output операций. +3744.00 3748.40 "Анатолий Кулаков" То есть какие-то сложные вводы, выводы, и которые нужно сделать очень-очень быстро. +3748.40 3750.16 "Анатолий Кулаков" Вот тогда вы идете в пайплайны. +3750.16 3758.04 "Анатолий Кулаков" Ну, так вот, если сложно очень много, быстро-быстро, то разумно, что силизатор обязан поддерживать нам быстро-быстро. +3758.04 3765.76 "Анатолий Кулаков" Так вот, PipeLineReader теперь поддерживается в JSON. +3765.76 3768.16 "Анатолий Кулаков" Теперь можно очень быстро из пайплайна читать и писать. +3768.16 3774.52 "Анатолий Кулаков" Раньше для того, чтобы читать из пайплайна необходимо было, то есть необходимо было сконвертировать это все в стрим. +3774.52 3775.88 "Анатолий Кулаков" И мы начинали читать из стрима. +3775.88 3783.44 "Анатолий Кулаков" В общем, API-стримы не такие прекрасные, как у PipeReader, поэтому мы, естественно, теряли в каком-то перфомансе. +3783.44 3785.52 "Анатолий Кулаков" Нововведения коснулись также системномерика. +3785.52 3795.36 "Анатолий Кулаков" Тогда добавились больше трансформаций матриц, а самое интересное это то, что TensorFlow API теперь выведен из экспериментального режима. +3795.36 3799.48 "Анатолий Кулаков" То есть теперь он стабильный, теперь можно его официально использовать и использовать в ваших приложениях. +3799.48 3805.40 "Анатолий Кулаков" Zip-архивы тоже немножко обновились. +3805.40 3808.04 "Анатолий Кулаков" Я что-то не помню, когда последний раз использовал Zip-архивы. +3808.04 3827.72 "Анатолий Кулаков" Ну, наверное, команда Microsoft тоже не помнила, поэтому у Zip-ов не было даже Async API, то есть, несмотря на то, что Zip-ы работают с файлами, казалось бы, это первая вещь, где должны появиться Async, но нет, оказывается у Zip-а не было Async API, и вот как раз только сейчас Microsoft все исправились. +3827.72 3837.28 "Анатолий Кулаков" Они добавили, соответственно, Async-методы, которые реализуют неблокирующие операции по чтению и записи Zip-овых файлов. +3837.28 3840.92 "Анатолий Кулаков" Ну, что, наверное, давно пора было добавить, странно, что не было. +3840.92 3849.38 "Анатолий Кулаков" Это увеличило, соответственно, скорость, уменьшило использование памяти и так далее и тому подобное. +3849.38 3856.80 "Анатолий Кулаков" Так еще сделали в JSON-стриме, прооптимизировали кодкоденейты стримы. +3856.80 3862.24 "Анатолий Кулаков" Они стали теперь на 35% быстрее, ну, прям-прям, Zip-ы развиваются. +3862.24 3875.92 "Анатолий Кулаков" Новый классик, который появился, это WebSocketStream, тоже безумно полезная вещь, потому что, ну, это обертка прежде всего, это новая обертка над WebSocket, то есть новый API, который призван упростить работу с WebSocket. +3875.92 3880.72 "Анатолий Кулаков" В WebSocket основная сложность в том, что он слишком низкоуровневый, ну, как обычный сокет, по сути. +3880.72 3892.00 "Анатолий Кулаков" То есть, если вы хотите какой-нибудь буферинг, фрейминг или, может быть, энкодинг, декодинг какой-то кастомный, все это вам нужно будет реализовать сверху, над WebSocket, и очень часто все это люди реализовывали. +3892.00 3903.28 "Анатолий Кулаков" В общем, так делать, ну, это сопровождалось множеством ошибок, так делать не хочется, нужно как-то все так, что-то более высокоуровневое, и вот появился WebSocketStream. +3903.28 3923.16 "Анатолий Кулаков" Это как раз привычный нам интерфейс Stream, то есть такая абстракция, стримовая абстракция, но над WebSocket, и она дает как раз-таки высокоуровневый какой-то API, который, в принципе, всем знаком, все его умеют принимать, со всеми он умеет работать, и он под капотом делает всю вот эту грязную работу, которую раньше приходилось делать ручками. +3923.16 3927.68 "Анатолий Кулаков" Тоже хорошая полезная вещь, если вдруг с WebSocket в WebSocket общаетесь. +3927.68 3930.92 "Анатолий Кулаков" На этом, наверное, все, вот такие основные нововведения. +3930.92 3939.86 "Анатолий Кулаков" Естественно, появилась куча всяких оптимизаций, каких-то мелких методов, каких-то мелких эверайдов, но вот ключевые вещи, на которых надо обязательно знать, это вот такой списочек. +3939.86 3967.16 "Игорь Лабутин" Угу, а одна из основных библиотек, которые, наверное, мы чаще всего используем, ну, по крайней мере, те, кто пишет для Web, это, конечно же, SP.Net Core, и это следующий наш кусочек, где на самом деле не так много изменений, так, изменений много, но они довольно нишевые и мелкие, как мне показалось, по крайней мере, в мелкие в смысле, что каких-то, опять же, революционных штук вроде как особо и не видно. +3967.16 4124.32 "Игорь Лабутин" Развивается потихонечку, Blazor продолжает, значит, там добавили новые Security Sample, если вы хотите всякие OpenID Connect и прочее, Blazor Script теперь нужен, сервится из сервера как статический WebAsset, а не как Embedded Resource, как раньше, можно кастомизировать теперь UI-компоненту Reconnect, это очень важно, потому что в Blazor, особенно если вы используете сервер Blazor, это принципиально важно для живости вашего приложения, для HTTP-клиента Streaming включен по умолчанию, можно теперь декларативно описывать, что какие-то компоненты должны персистить свой State, из такого довольно интересного добавили новый фичи по интеропу с JS, потому что Blazor Blazor, но с JS приходится иногда взаимодействовать, т.е. надо создать JS-объект и после этого можно вызывать методы, для WebAssembly варианта Blazor добавили профилирование и всякие счетчики для диагностик, добавили метрики, трейсинги, чуть лучше подружились с JS-бандлерами и добавили ход reload, в общем Blazor потихонечку развивается, я не то чтобы сильно слышу, что он был супер как-то популярен, но свою нишу видимо занял таких, грубо говоря, админок, не знаю, чего-то такого, ну и вроде неплохо себя там чувствует, в Blazor Hybrid, это который с Maui, ну там добавили просто немножко всяких примеров, в статье про новости есть даже раздел SignalR, я подумал, о, интересно, что же добавили в SignalR, правильный ответ - ничего, заголовок есть, контента нет, в SignalR изменений нету, по крайней мере по статье судя, в Minimal API есть некоторые изменения, во-первых, если у вас есть какой-нибудь nullable value тип, ну например DateTime, то раньше вы можете туда, понятно, передать строчку, в которой есть, ну в смысле JSON, если придет или какой-нибудь FormData, в котором это поле заполнено валидной строкой, ну оно естественно образуется в ValueType.DateTime, а вот если придет null, понятно, будет null, поскольку у вас nullable поле, а вот если придет пустая строка, то раньше была ошибка в валидации, теперь будет null, то есть пустая строка теперь равносильна null, в таком случае, вероятно, это можно как-то поменять и отключить, но дефолтное теперь такое. +4124.32 4140.64 "Игорь Лабутин" Для Minimal API можно теперь написать BuilderService.SetValidation и тогда и для классов, и для рекордов можно все разметить всякими DataAnnotation атрибутами и все будет валидироваться и кидаться в ошибочки, причем это все интегрировано с iProblemDetailsService и можно все это тонко настраивать. +4140.64 4155.40 "Игорь Лабутин" Добавилась поддержка ServerSendEvents и вот эти Validation APIs, они переехали в отдельный namespace MicrosoftExtensionsValidations и вообще говоря, в свой NuGet пакет, который позволит их использовать не только в S/4HANA Core, а еще вообще где угодно. +4155.40 4189.12 "Игорь Лабутин" OpenAPI сделали поддержку версии 3.1, теперь можно не только JSON-вариант, но и YAML-вариант наружу выставлять, можно для атрибута ProducesResponseType для API-контроллеров указывать теперь Description, который попадет в OpenAPI-спеку, причем кроме того будут использоваться XML-документы на методах, классах для того, чтобы генерить OpenAPI-спеку. +4189.12 4209.40 "Игорь Лабутин" В DI-контейнере доступна штука под названием iOpenAPIDocumentProvider, которая позволяет доступиться к OpenAPI, который для вашей API доступится изнутри вашей же API, например, чтобы что-то про себя узнать, не знаю, зачем это надо, но допустим, вот. +4209.40 4225.28 "Игорь Лабутин" И напомню, что в OpenAPI-поддержке и .NET была такая концепция под названием трансформеры, то есть вы можете, прежде чем OpenAPI какое-то описание попадет в реальную спеку, написать код, который его трансформирует на лету во что-то другое. +4225.28 4236.28 "Игорь Лабутин" Ну вот теперь есть endpoint-специфик трансформера, то есть можете на каждый endpoint навесить хоть каждый свой собственный трансформер, который будет его OpenAPI-кусочек спеки преобразовывать, вот. +4236.28 4249.28 "Игорь Лабутин" И довольно, наверное, важное изменение — это nullable-типы теперь моделируются с помощью конструкции one-off, то есть one-off, и там указывается либо тип конкретный, либо null. +4249.28 4258.08 "Игорь Лабутин" Ну, соответственно, это довольно, наверное, важное изменение, которое может изменить то, как у вас клиенты это дело употребляют. +4258.08 4272.16 "Игорь Лабутин" В идентификации-авторизации добавились метрики, то есть теперь можно посчитать, Aspire.Net Core сразу выводит, сколько там всяких логинов, логаутов и прочих связанных с этим процессом метрик. +4272.16 4282.84 "Игорь Лабутин" Также, если вы используете Aspire.Net Core Identity, то там тоже есть свой набор метрик, сколько там юзеров зарегистрировалось, удалилось и так далее, это все считается. +4282.84 4312.28 "Игорь Лабутин" И для известных API-эндпоинтов, в смысле для эндпоинтов, для которых известно, что это эндпоинты, которые используются как условный REST API, а не как что-то, что генерирует там Razor страничку или что-нибудь в таком духе, для них теперь не делается редирект на логин-страничку, если вы поняли, что запрос не авторизован. +4312.28 4323.48 "Игорь Лабутин" В такие известные входит все, что отмечено как API-контроллер, весь минимал API, который принимает либо возвращает JSON, и все, что возвращает Typed Results, ну и весь сигналар. +4323.48 4334.32 "Игорь Лабутин" Там более-менее понятно, что редиректить клиента, который пришел в такую API-шку на HTML-страничку логина, особого смысла не имеет, ему нужно просто вернуть 401 или 403 и на этом закончить. +4334.32 4346.96 "Игорь Лабутин" Ну и по мелочи, у нас есть глобальный exception handler, который можно было написать, а теперь его еще можно и настроить. +4346.96 4359.12 "Игорь Лабутин" Он принимает suppress-diagnostics-callback, который позволяет вернуть true или false, и в зависимости от того, что он вернет, будет или не будет писаться в логах глобальное исключение, потому что вот мы там поймали. +4359.12 4364.36 "Игорь Лабутин" Может быть вы его уже и так поймали, обработали, куда надо отдали, и в логе писать не нужно. +4364.36 4375.52 "Игорь Лабутин" Поддерживается теперь домен .localhost, автоматически резолвится в 27001, это топ-левел домен для любых своих тестовых целей можно использовать, но работать только в рамках .localhost. +4375.52 4393.40 "Игорь Лабутин" Для приложений, которые используют топ-левел-стейтменты, это, напомню, там, где вы не пишете теперь никакой там программ-класс и внутри main функцию, просто сразу начинаете писать c#-код. +4393.40 4403.80 "Игорь Лабутин" Раньше для того, чтобы, например, потестировать такой код, вам нужно было как-то на него сослаться, и для этого вам приходилось явно написать public partial class program, теперь этого не надо делать, за это вам source-генератор все сделает. +4403.80 4426.56 "Игорь Лабутин" Ну и, пожалуй, наверно все, но внутри system.json появилась поддержка jsonpatch, новая, точнее, реализация, но это уже такие совсем нишевые штуки, которых много наверняка в спин-адкоре, но которые все просто не попали в спин-адкор, конкретно jsonpatch довольно большой кусок. +4426.56 4431.80 "Игорь Лабутин" Кстати, я откушивал себе, хотя я не уверен, что это довольно частая штука, которая используется. +4431.80 4439.00 "Игорь Лабутин" Ну вот как-то так, нет ничего какого-то вообще, революционный спин-адкор просто какое-то, ну, полномерное развитие, причем не очень большое за год. +4439.00 4446.80 "Анатолий Кулаков" Ну, капец же, стабильность, improvements наше все, у стабильных фреймворков все должно быть именно такое. +4446.80 4449.80 "Анатолий Кулаков" Ну, с другой стороны, да. +4449.80 4460.52 "Анатолий Кулаков" У Entity Framework, второго, наверное, инструмента, второго фреймворка, который мы чаще всего пользуемся, тоже вышло немножко обновлений. +4460.52 4467.16 "Анатолий Кулаков" Ребята тоже не сидели там весь год, все импровили, все перфомали, давайте же посмотрим, что они нам интересного наделали. +4467.16 4471.28 "Анатолий Кулаков" Ну, прежде всего, хотелось бы отметить улучшение в комплекс-тайпах. +4471.28 4482.52 "Анатолий Кулаков" Напомню, недавно ввели, буквально пару релизов назад ввели комплекс-тайпы, то есть это способ, каким образом мы можем внутрь какого-то большого типа запихнуть информацию о более мелком типе. +4482.52 4491.48 "Анатолий Кулаков" Обычно это какой-нибудь value object, ну, например, адрес, который содержит в себе страну и город, и улицу. +4491.48 4501.12 "Анатолий Кулаков" А вот у нас тут какие-нибудь три поля есть, и мы его хотим запихнуть в сущность, которая называется там письмо или пользователь, пользователь лучше, где он проживает. +4501.12 4503.80 "Анатолий Кулаков" Вот, для этого необязательно заводить какую-то отдельную таблицу. +4503.80 4513.68 "Анатолий Кулаков" Допустим, Entity Framework может все это смапить в обычных три колонки из таблицы пользователя, вот, и для этого как раз применяется комплекс-тайпы. +4513.68 4522.32 "Анатолий Кулаков" То есть это способ записать, по сути, какой-нибудь value object в таблицу параметра. +4522.32 4532.48 "Анатолий Кулаков" Можно теперь сделать не только разложить его там на три колоночки, допустим, но и записать это в одну колонку, но при этом сервизовать весь этот value object в JSON. +4532.48 4541.60 "Анатолий Кулаков" Тоже очень полезная штука, потому что если вам не нужно доступаться к этим свойствам, не нужно по ним индексировать, искать или еще что-то, вы можете просто засервизовать это в JSON. +4541.60 4554.12 "Анатолий Кулаков" А если ваша база данных вдруг поддерживает JSON column, то есть специальный тип данных JSON, который интерпретируется движком базы данных, то в принципе индексировать и искать вы по ней, сортировать тоже можете без всяких проблем. +4554.12 4559.52 "Анатолий Кулаков" Вот, поэтому есть такая поддержка, есть такие комплекс-тайпы. +4559.52 4569.60 "Анатолий Кулаков" Еще в Entity 10 добавили поддержку опциональных типов, то есть раньше можно было создать такой примитивный тип или он здесь даже называется комплекс-тайп. +4569.60 4570.60 "Анатолий Кулаков" Как раз наоборот. +4570.60 4578.24 "Анатолий Кулаков" В общем, можно было создать такой комплекс-тайп, но к сожалению, он не поддерживал опциональность, то есть все свойства должны были быть обязательными. +4578.24 4585.04 "Анатолий Кулаков" В общем, это очень часто приводило к тому, что невозможно было использовать этот тип. +4585.04 4592.44 "Анатолий Кулаков" В общем, сейчас вроде эту, можно сказать, даже багу пофиксили, даже не фичу, эта бага была чистой воды. +4592.44 4598.16 "Анатолий Кулаков" Вот поэтому можно теперь опциональные комплекс-тайпы делать, и что очень хорошо. +4598.16 4607.02 "Анатолий Кулаков" Дальше вы добавили поддержку структур, то есть теперь комплекс-тайпы можно делать не только классами, но и структурами. +4607.02 4617.68 "Анатолий Кулаков" Например, когда у вас нет какого-то, какая-то сущность, у которой нет идентификатора, то же самое адрес, деньги, то есть сумма плюс валюта, допустим. +4617.68 4622.36 "Анатолий Кулаков" В общем, это все не идентифицируемые по сути сущности, опять же, комплекс-тайпы. +4622.36 4630.00 "Анатолий Кулаков" И можно вполне сделать их структурами, но на данный момент не поддерживается коллекция структур, поэтому здесь есть небольшое ограничение. +4630.00 4635.32 "Анатолий Кулаков" Так, по комплекс-тайпам все, дальше интересное нововведение. +4635.32 4640.28 "Анатолий Кулаков" Это относится к параметризированным коллекциям, вот это целая эпопея. +4640.28 4641.64 "Анатолий Кулаков" Давайте начнем сначала. +4641.64 4648.72 "Анатолий Кулаков" В общем, есть такой прекрасный шаблон проектирования, даже не шаблон проектирования, а такой юзкейс, часто юзкейс у разработчиков. +4648.72 4659.44 "Анатолий Кулаков" Допустим, представьте, у вас есть ваш какой-то блогик, у блогика есть статьи, и вам нужно выбрать статьи по определенным айдишникам. +4659.44 4667.56 "Анатолий Кулаков" Вот, допустим, у вас есть 10 айдишников, какие статьи вы хотите видеть, как это транслируется в NFT-фреймворк. +4667.56 4668.92 "Анатолий Кулаков" Ну, для начала в линку. +4668.92 4683.32 "Анатолий Кулаков" В линку мы обращаемся, контекст, блог, блог вео, и у этого вео ставим предикат, в предикате мы, скорее всего, напишем массив вот этих айдишников, которые у нас известны заранее. +4683.32 4684.32 "Анатолий Кулаков" Contains_blog_id. +4684.32 4694.28 "Анатолий Кулаков" То есть мы пытаемся выбрать все блоги, все статьи, айдишники которых содержатся в нашем списке константа. +4694.28 4697.00 "Анатолий Кулаков" Допустим, вот там у нас 10 айдишников. +4697.00 4710.40 "Анатолий Кулаков" Типичный случай, абсолютно часто, в общем, приходится вот таким айдишником фильтровать, в общем, и поэтому как бы очень-очень жаркий, очень голосуемый и очень запрашиваемый Майкрософт. +4710.40 4713.12 "Анатолий Кулаков" В чем, собственно, проблема? +4713.12 4722.76 "Анатолий Кулаков" Проблема в том, что реляционные базы данных не очень хорошо приспособлены к вот таким вот запросам, типа Contains_blog_id. +4722.76 4729.36 "Анатолий Кулаков" Ну и, соответственно, нет какой-то понятной, хорошей структуры, которая может это все дело обеспечить. +4729.36 4739.68 "Анатолий Кулаков" Проблема заключается в том, что каждый раз, когда мы передаем вот этот айдишники, то айдишники, они все время будут разные. +4739.68 4753.40 "Анатолий Кулаков" Ну, соответственно, у нас там один массив - blog_id, другой массив - blog_id и изначально Entity Framework до восьмой версии слал вот этот массив как константы. +4753.40 4767.96 "Анатолий Кулаков" То есть в SQL это раскладывалось в the выражение, у которого проверялся blog_id, применялся in и в in передавались в скобочках просто идентификаторы всех этих блогиков. +4767.96 4773.48 "Анатолий Кулаков" Ну, кажется, вот такая интуитивная структура для SQL, как бы это все могло бы разложиться. +4773.48 4775.28 "Анатолий Кулаков" И действительно, ну, это так. +4775.28 4779.40 "Анатолий Кулаков" В SQL это самая оптимальная, самая красивая, самая понятная структура. +4779.40 4783.96 "Анатолий Кулаков" И поэтому Entity Framework прям с первых своих версий генерил именно такой подход. +4783.96 4788.56 "Анатолий Кулаков" Но на практике этот подход оказался плох в некоторых ситуациях. +4788.56 4796.08 "Анатолий Кулаков" Он плох тем, что, допустим, у нас есть 10 запросов, каждый раз из этих 10 запросов мы выбираем блогики. +4796.08 4799.84 "Анатолий Кулаков" И каждый раз в эти 10 запросах у нас разные айтишники приходят. +4799.84 4807.12 "Анатолий Кулаков" Соответственно, сгенерированный SQL у нас будет разный, то есть у нас будет 10 сгенерированных SQL. +4807.12 4816.32 "Анатолий Кулаков" И это означает, что в SQL пойдет запрос, который уже не будет находиться в кэше планов. +4816.32 4821.24 "Анатолий Кулаков" То есть каждый раз необходимо будет строить новый план для этого SQL-запроса. +4821.24 4826.56 "Анатолий Кулаков" А построение нового плана – это большие performance issue, если мы говорим про оптимизацию. +4826.56 4829.80 "Анатолий Кулаков" То есть, по сути, это очень медленный подход. +4829.80 4835.00 "Анатолий Кулаков" В восьмом Entity Framework посмотрели на это все и подход немножко поменяли. +4835.00 4838.20 "Анатолий Кулаков" Они стали строить по-другому. +4838.20 4851.84 "Анатолий Кулаков" Взяли вот эти все значения, вот этот весь массив, вот этот список, по которому мы ищем, засериализовали в JSON, в массив JSON, и передали это как один единственный аргумент. +4851.84 4855.68 "Анатолий Кулаков" А уже непосредственно в запрос получился следующий. +4855.68 4869.80 "Анатолий Кулаков" То есть мы берем специальный оператор OpenJSON и говорим, что мы хотим выбрать все блогики from OpenJSON, и в этом OpenJSON выбираем из массива идентификаторы наших блогиков, которые мы хотим выбрать. +4869.80 4874.24 "Анатолий Кулаков" То есть мы решили проблему, у нас появился один query план. +4874.24 4879.60 "Анатолий Кулаков" То есть план, у которого аргументом является вот этот строковой JSON массив. +4879.60 4889.48 "Анатолий Кулаков" Аргумент один, это значит, что выполнив 10 запросов на выборку блогиков по идентификаторам, мы получим стопроцентное попадание в кэш. +4889.48 4894.36 "Анатолий Кулаков" Это быстро, это прекрасно, но есть подводные камни. +4894.36 4904.60 "Анатолий Кулаков" Потому что, несмотря на то, что планера мы немножко удовлетворили, он всегда пользуется своим кэшом и ему хорошо, но при этом мы потеряли очень важную информацию. +4904.60 4917.72 "Анатолий Кулаков" Если мы делаем OpenJSON из строковой переменной, потом десериализуем ее и вытаскиваем оттуда какие-то идентификаторы массивов, планер ничего не знает про длину этого массива. +4917.72 4919.64 "Анатолий Кулаков" То есть сколько элементов-то там внутри. +4919.64 4929.28 "Анатолий Кулаков" А на самом деле длина - это один из самых ключевых параметров, на которые смотрит планер для того, чтобы выбрать правильную стратегию, которую он будет использовать. +4929.28 4936.16 "Анатолий Кулаков" То есть очень сильно отличаются SQL-запросы, когда планер понимает, что ему нужно выбрать 2-3 элемента и какие-нибудь тысячи элементов. +4936.16 4946.92 "Анатолий Кулаков" Это абсолютно разные могут быть запросы, они по-разному гуляют по индексам, по-разному загружают страницы, в общем все у них может сильно-сильно различаться. +4946.92 4954.24 "Анатолий Кулаков" Поэтому использование кэша мы, конечно, улучшили, но информацию о длине потеряли и тоже это дало какие-то перформанс-просадки. +4954.24 4958.52 "Анатолий Кулаков" Но неугомонные микрософтовские программисты не сдаются. +4958.52 4965.48 "Анатолий Кулаков" Они в девятом Entity Framework позволили сделать следующее. +4965.48 4969.04 "Анатолий Кулаков" Они позволили пользователю выбирать, какую стратегию использовать. +4969.04 4974.40 "Анатолий Кулаков" То есть вы хотите количество элементов, тогда вот, пожалуйста, используйте константы. +4974.40 4977.76 "Анатолий Кулаков" Вы хотите больше попадать в кэш, тогда, пожалуйста, используйте OpenJSON. +4977.76 4984.72 "Анатолий Кулаков" Ну, что сказать, они, по сути, переложили вот эту ответственность за принимаемое решение на плечи пользователя. +4984.72 4986.58 "Анатолий Кулаков" При этом проблема как бы не решена. +4986.58 4995.16 "Анатолий Кулаков" Разумеется, ни один из разработчиков не будет сидеть и в каждом фильтре задумываться, а как бы мне поднастроить именно вот сейчас текущий фильтр. +4995.16 5001.60 "Анатолий Кулаков" Поэтому неугомонные микрософтовские разработчики в десятой версии Entity Framework придумали еще один режим. +5001.60 5016.36 "Анатолий Кулаков" Режим вот такой, немножко гибридный, в общем, они отказались от OpenJSON, потому что там вообще без шансов, но при этом не могли вернуться полностью к константным методам. +5016.36 5019.96 "Анатолий Кулаков" Поэтому они придумали такой гибридный режимчик. +5019.96 5029.48 "Анатолий Кулаков" Они применяют обычный SQL-оператор var_in, и при этом в скобочках задают параметризированные значения. +5029.48 5034.24 "Анатолий Кулаков" Таким образом параметризированные значения задаются, значит, он попадает в кэш. +5034.24 5040.40 "Анатолий Кулаков" Как же нам теперь сделать так, что мы же по сути не знаем, какие параметризированные значения будут. +5040.40 5041.40 "Анатолий Кулаков" Все очень просто. +5041.40 5047.74 "Анатолий Кулаков" Entity Framework предлагает нам генерить столько параметризированных значений, сколько элементов у нас будет на входе. +5047.74 5057.32 "Анатолий Кулаков" То есть мы знаем, что вот к нам пришел какой-то лист, мы этого листа можем сделать count, и по числу этого count сгенерить параметры в in-операторе. +5057.32 5061.68 "Анатолий Кулаков" То есть пришло три элемента, сгенерили in в трех элементах в скобочках. +5061.68 5064.16 "Анатолий Кулаков" Пришло 10, сгенерили 10 в скобочках. +5064.16 5065.16 "Анатолий Кулаков" Вот. +5065.16 5069.00 "Анатолий Кулаков" Это в принципе дает плюсы и того, и сего подхода. +5069.00 5075.96 "Анатолий Кулаков" То есть у нас есть количество, теперь планер как бы счастлив, и мы попадаем в кэш, потому что элементы на месте. +5075.96 5083.52 "Анатолий Кулаков" SQL-запрос более-менее всегда одинаковый, ну потому что параметр-то, количество параметров только отличается. +5083.52 5090.68 "Анатолий Кулаков" То есть если у нас будет всегда приходить запрос с 10 параметрами, то это будет 100% попадание в кэш. +5090.68 5094.72 "Анатолий Кулаков" Потому что мы сгенерим один раз план для 10 параметров, и все будут счастливы. +5094.72 5099.56 "Анатолий Кулаков" Но на практике, разумеется, не всегда мы приходим с 10 параметрами. +5099.56 5101.08 "Анатолий Кулаков" Количество параметров очень сильно варьируется. +5101.08 5109.16 "Анатолий Кулаков" Мы можем приходить с одним, потом с двумя, потом с тремя, потом с четырьмя, и в таком случае, то есть это самый плохой вариант, в таком случае мы постоянно будем генерить новый план. +5109.16 5118.72 "Анатолий Кулаков" Ну потому что у нас для трех параметров появится новый запрос, для четырех параметров появится новый запрос, для пяти - новый, таким образом мы снова попадаем мимо кэша. +5118.72 5123.60 "Анатолий Кулаков" В общем, здесь вот такая вот интересная дилемма получается. +5123.60 5126.80 "Анатолий Кулаков" Как же ее решать? +5126.80 5131.36 "Анатолий Кулаков" Опять же, слишком много планов, слишком много планов, которые не попадают в кэш. +5131.36 5132.36 "Анатолий Кулаков" Вот. +5132.36 5137.44 "Анатолий Кулаков" Entity Framework решает ее с помощью паддингов, то есть у него есть какие-то определенные шаги. +5137.44 5145.32 "Анатолий Кулаков" Допустим, он считает, что если к нам пришло 8 параметров, то Entity Framework добивает их до десяточки. +5145.32 5148.96 "Анатолий Кулаков" То есть у нас вот такие вот получаются ступеньки. +5148.96 5154.36 "Анатолий Кулаков" Если вы не дотягиваете до ступеньки, то Entity Framework сам догенерирует необходимые параметры. +5154.36 5166.52 "Анатолий Кулаков" В общем, когда приходит 8 параметров, он генерирует еще два, чтобы вместе было 10, а десятые планы, то есть планы с 10 параметрами уже там кэшируются, уже кэшируются в планере. +5166.52 5177.74 "Анатолий Кулаков" Естественно, если придет какое-то другое значение, например 200, то ему придется сгенерить новый SQL, но все равно это выравнивание немножко поможет нивелировать вот этот кэш-мисс. +5177.74 5182.16 "Анатолий Кулаков" В общем, вроде стратегия вполне нормальная. +5182.16 5185.98 "Анатолий Кулаков" Давайте немножко посмотрим на вот эти два параметра, которые он добавляет, потому что это интересно. +5185.98 5192.32 "Анатолий Кулаков" Опять же, у нас мы попросили выбрать блоги с 8 идентификаторами. +5192.32 5204.04 "Анатолий Кулаков" Если Entity Framework добавит туда еще каких-то два параметра, то у нас, по идее, ответ будет с 10 блогами, потому что теперь мы фильтруем по 10 идентификаторами. +5204.04 5206.44 "Анатолий Кулаков" Он поступает немножко хитрее. +5206.44 5213.12 "Анатолий Кулаков" Естественно, он не может добавить какое-то произвольное число, даже 0 или null, нет, не может, потому что это может сбить выходной результат. +5213.12 5220.28 "Анатолий Кулаков" Он берет последний параметр, который он знает, например восьмой, и его дублирует и просто-напросто еще два раза. +5220.28 5225.56 "Анатолий Кулаков" Это приводит к тому, что SQL ищет по восьмому идентификатору три раза. +5225.56 5235.28 "Анатолий Кулаков" Но это не страшно, потому что SQL умеет правильно и грамотно это делать, поэтому для SQL никаких накладных расходов по этому поводу нет, а вот для Entity Framework интересный такой хак получился. +5235.28 5243.48 "Анатолий Кулаков" И после этого, если он даже три раза проищет по одному параметру, результат будет один и тот же на выходе. +5243.48 5252.60 "Анатолий Кулаков" Несмотря на то, что эта стратегия, казалось бы, наконец-то решили все проблемы, те, что были раньше, те, что оказались впереди, в общем, эта стратегия кажется золотой и красивой, на самом деле нет. +5252.60 5255.92 "Анатолий Кулаков" Естественно, она тоже не лишна недостатков. +5255.92 5265.84 "Анатолий Кулаков" Опять же, например, если у вас очень большое разнообразие запросов по количеству аргументов, то у нее тоже будет очень частые кэш-миссы в планере и происходит performance degradation. +5265.84 5272.20 "Анатолий Кулаков" Поэтому Entity Framework выставляет наружу возможность конфигурирования. +5272.20 5275.80 "Анатолий Кулаков" Пользователь должен сам решить, то есть не пользователь, а программист у нас. +5275.80 5277.68 "Анатолий Кулаков" Программисты умные, они должны уметь решать. +5277.68 5280.56 "Анатолий Кулаков" Должен сам уметь решить, какую стратегию ему использовать. +5280.56 5283.32 "Анатолий Кулаков" Ну, во-первых, мы можем решить на глобальном уровне, т.е. +5283.32 5285.04 "Анатолий Кулаков" по дефолту, какая будет стратегия. +5285.04 5295.08 "Анатолий Кулаков" Для этого нам нужно выставить специальные свойства вызова метод useParameterizedCollectionMode в конфигурации в то время, как мы конфигурируем контекст. +5295.08 5300.36 "Анатолий Кулаков" Или можно у каждого конкретного запроса указывать, а что мы в данном конкретном запросе хотим. +5300.36 5302.72 "Анатолий Кулаков" Это мы делаем с помощью класса EF. +5302.72 5316.64 "Анатолий Кулаков" У него есть метод constant, который принимают идентификаторы, и уже от этого constant-идентификатора у него есть contents, который мы можем явно намекнуть Entity Framework, что мы хотим в виде constant зациализовать, по сути, загенерировать SQL-запросы. +5316.64 5331.96 "Анатолий Кулаков" Вот, поэтому, если вам нужна такая тонкая настройка, если вы четко понимаете, насколько ваши запросы отличаются, и как часто будут меняться длины запрашивающих идентификаторов, contents, то можете попробовать такую вручную подтюнить. +5331.96 5338.64 "Анатолий Кулаков" Так, это мы поговорили только про параметризованные коллекции. +5338.64 5340.32 "Анатолий Кулаков" Пойдем дальше, посмотрим, что у нас интересного есть. +5340.32 5345.04 "Анатолий Кулаков" Так, добавился еще поддержка left-join и right-join операторов. +5345.04 5347.84 "Анатолий Кулаков" Вот это тоже из цикла, почему этого не было раньше. +5347.84 5376.24 "Анатолий Кулаков" В общем, если вы когда-нибудь пытались написать на линке left-join, то это, безусловно, возможно, но сделать это абсолютно непросто, потому что для того, чтобы сделать left-join на линке, вам необходимо будет использовать select many, group join и default if empty, то есть вот таких специальных три ключевых метода для того, чтобы реализовать казалось банальный left-join, который как бы в сиквеле самых первых его версий существует просто всегда, уже десятки-десятки лет. +5376.24 5381.72 "Анатолий Кулаков" Непонятно, почему не делали нормальный left-join для линков. +5381.72 5383.08 "Анатолий Кулаков" Так вот, наконец, сделали. +5383.08 5398.28 "Анатолий Кулаков" Сделали, в 10.NET у нас теперь у линк появился left-join и right-join, и теперь его, естественно, научился транслировать Entity Framework, все он это прекрасно понимает, все это транслируется в сиквел, все это поддерживается, и оператор более-менее стал более читабельным. +5398.28 5404.12 "Анатолий Кулаков" Еще интересная тема, это появились именованные query фильтры. +5404.12 5407.92 "Анатолий Кулаков" У Entity Framework есть такое понятие, как глобальные фильтры. +5407.92 5409.32 "Анатолий Кулаков" Они очень полезны. +5409.32 5421.44 "Анатолий Кулаков" Глобальные фильтры позволяют вам законфигурировать такой фильтр, который будет применяться каждый раз, когда вы запрашиваете коллекцию этих элементов, ну или даже один элемент, не обязательно коллекцию, в общем всегда когда вы запрашиваете элемент. +5421.44 5449.00 "Анатолий Кулаков" Типичный случай, это, например, soft-delete, если вы не хотите запись физически удалять из базы данных, то обычно заводится какая-нибудь колонка, которая называется из delete, и проставляют ей флажочек true или false, и когда у тебя запись удалена, естественно пользователю по умолчанию не хочется ее показывать на экран, если он просит всю коллекцию, дайте мне всех пользователей, давайте не пользователей, дайте мне коллекцию всех ордеров, то естественно удаленные ордеры он видеть не хочет. +5449.00 5460.44 "Анатолий Кулаков" Тогда программисты делают query фильтр, ставят по дефолту, те ордеры, у которых из delete уже выставлен, мы возвращать по дефолту не хотим, мы хотим отфильтровать. +5460.44 5474.44 "Анатолий Кулаков" И теперь, когда мы обращаемся к ордерам, в любом выражении, даже если бы явно этого не указали, подставляется вот этот неявный query фильтр, то есть он неявно все элементы, все ордеры фильтрует. +5474.44 5489.30 "Анатолий Кулаков" Очень удобная штука, кроме soft-delete, например, она часто применяется в multi-tenancy, то есть если вам нужно ограничить все запросы каким-то одним тенентом, и чтобы мы всегда были только в рамках этого тенента, естественно, делается просто глобальный query фильтр и все счастливы. +5489.30 5502.80 "Анатолий Кулаков" Подход хороший, но хочется больше, у него есть глобальный недостаток, в том, что этот фильтр глобальный, то есть мы можем только один фильтр выставить на сущность и все. +5502.80 5507.88 "Анатолий Кулаков" А часто бывает несколько use-cases, когда мы хотим выставлять этот фильтр. +5507.88 5513.44 "Анатолий Кулаков" Ну вот я вам уже два их назвал, во-первых, мы хотим отфильтровать по soft-delete, а во-вторых, мы еще хотим отфильтровать по multi-tenancy. +5513.44 5522.52 "Анатолий Кулаков" И иногда мы хотим их регулировать, то есть иногда пользователь хочет увидеть удаленные ордера, те, которые закончились, допустим, нормальное желание. +5522.52 5526.60 "Анатолий Кулаков" Или иногда администратор хочет посмотреть данные другого тенента. +5526.60 5528.48 "Анатолий Кулаков" В общем, иногда мы хотим это разрешить. +5528.48 5541.60 "Анатолий Кулаков" Для этого был метод в Entity Framework, который назывался Ignore Query Filters, и мы могли запросить, но, опять же, мы могли только проигнорировать один глобальный фильтр. +5541.60 5550.00 "Анатолий Кулаков" Если же мы хотим сделать несколько разных стратегий заимплементить, то тут у нас руки связаны и приходилось только руками это все дело делать. +5550.00 5557.40 "Анатолий Кулаков" Теперь же ситуация изменилась, мы теперь можем указывать много вот этих query-фильтров и давать им имена. +5557.40 5586.64 "Анатолий Кулаков" Соответственно, мы можем наложить на наш ордер фильтр, который фильтрует ордеры по soft-delete, и фильтр, который фильтрует ордеры по multi-tenancy, и пусть они, допустим, по умолчанию оба есть, но в тот момент, когда мы хотим просто посмотреть удаленные все закрытые ордера, мы можем отключить только soft-delete фильтр с помощью Ignore Query Filters, передав имя этого фильтра и получить удаленные ордера, но оставаясь в рамках все еще нашего тенента. +5586.64 5589.64 "Анатолий Кулаков" В общем, что тоже очень удобно и прекрасно. +5589.64 5623.04 "Анатолий Кулаков" Из других нововведений, в частности для SQL-сервера 2025, у него появилась недавно поддержка VectorDataType, и Entity Framework 10 поддерживает этот VectorDataType и поддерживает функцию VectorDistance, которая очень часто используется и тип этот очень часто используется в embedding, то есть мы когда рассказывали про аишечку, мы всегда говорили, что там есть embedding, которым она хранится, тракторизованные данные, по которым надо искать, тот же самый RAC здесь, который можно упомянуть. +5623.04 5628.20 "Анатолий Кулаков" В общем, для того, чтобы это все хранить, нужна векторная база данных. +5628.20 5638.80 "Анатолий Кулаков" И вот Microsoft SQL Server 2025 теперь является в том числе и векторной базой данных, потому что просто-напросто поддержал векторный тип и сделал пару полезных функций. +5638.80 5655.88 "Анатолий Кулаков" И в 2025 SQL-сервере появился JSON DataType, и естественно новый Entity Framework прекрасно поддерживает JSON-овские запросы, фильтры и сортировки, то есть тоже поддерживает сервер 25-й. +5655.88 5663.00 "Анатолий Кулаков" 25-й сервер можно встретить или если вы поставите его к себе, или если вы пользуетесь Ажурой, то там тоже оно есть. +5663.00 5677.08 "Анатолий Кулаков" В общем, полезные штучки, Entity Framework становится красивше и красивше, как бы медленно, но стабильно идет по пути того, что как можно больше интересных маппингов, операций и запросов, оптимизирует, поддерживает. +5677.08 5678.08 "Анатолий Кулаков" Вообще красота. +5678.08 5680.40 "Анатолий Кулаков" В общем, мне вектор развития вам нравится. +5680.40 5683.56 "Анатолий Кулаков" Можно было бы, конечно, побыстрее, но и так вроде хорошо. +5683.56 5687.36 "Игорь Лабутин" Ну, надо сказать, что довольно много нововведений. +5687.36 5707.68 "Игорь Лабутин" Мы довольно немного слышали про EF Core в течение года, то есть они как-то не так активно публикуют статьи для превьюшек и ревиз кандидатов, но прямо по итоговым заметкам видно, что много поработали хорошо, учитывая размер команды, там, как всегда, полтора-два человека, или сколько их там сейчас, довольно много изменений. +5707.68 5715.04 "Анатолий Кулаков" Ну да, тем более, если сравнивать с другими анонсами, то параллельные команды, кажется, вообще ничего не делали весь год. +5715.04 5717.52 "Игорь Лабутин" Ну, не совсем ничего, но тем не менее. +5717.52 5718.52 "Анатолий Кулаков" Давай дальше. +5718.52 5721.44 "Анатолий Кулаков" Ну как там, обычно у нас в Маюке там перформансы, прумансы, все, и больше ничего. +5721.44 5746.64 "Игорь Лабутин" Вот, вот мы сейчас к ней перейдем, к Мауи, Мауи, ну давай так, здесь довольно много изменений во всяких разных контролах, то есть какие-то удалены, какие-то заменены на новые, добавлены какие-то фичи, типа там в WebView можно теперь перехватывать вебреквесты и писать респонс так, как будто запрос дошел до сервера и вы что-то ответили. +5746.64 5763.08 "Игорь Лабутин" Для, там, анимации все синхронные методы выкинуты, ну естественно из-за деприкейчина и сказано использовать асинхронные, но это все такие, как бы, точечные изменения в каждом конкретном контроле или в каких-то логических блоках. +5763.08 5799.80 "Игорь Лабутин" Из глобального, из глобального появилась интеграция со спайром, то есть если вы теперь в DotNet Мауи приложении допишите правильную строчку add service defaults, то там появится набор специальных, как это, не то что появится, в приложении будет зарегистрированы нужные компоненты для корректной телеметрии и сервис дискавери в вашем приложении, и тогда ваше Мауи приложение сможет работать нормально со спайром, отдавать телеметрию, либо подключать к себе какие-то зависимости, которые в спайре-приложении определены про спайр, мы как-нибудь поговорим отдельно. +5799.80 5848.72 "Игорь Лабутин" С точки зрения диагностики, в целом там добавили всякие разные activity sources, метрики, фичи свечей, включать-выключать, все это заинструментено вокруг двух главных методов, iViewMeasure и iViewArrange, это два обычно самых дорогих метода, то есть layouting всех компонент, причем это все гордо написано, что это сделано zero-location-struct-based implementation, то есть короче там все бодро, быстро и так далее, из такого еще интересного в XAML-е добавили source-генератор для того, чтобы его корректно преобразовывать перед компиляцией, и добавили тоже в XAML для упрощения неявной и глобальной XAML-инспекции, как у нас в C#, сделано global-using, и такое теперь и в XAML-е есть. +5848.72 5868.84 "Игорь Лабутин" Ну и для андроида, мы это упоминали в последнем выпуске, в качестве экспериментального пока решения вместо Mono добавили core-CLR-runtime, то есть если пойдет хорошо, то Mono, по крайней мере на андроиде, выпилится из-за MAUI и .NET. +5868.84 5875.64 "Игорь Лабутин" Это то, что касается основных изменений по MAUI, но это еще не все. +5875.64 5883.92 "Игорь Лабутин" Я напомню, что MAUI это кроссплатформенный фреймворк, который должен работать вообще везде, на всех платформах и так далее, но везде да не везде. +5883.92 5903.92 "Игорь Лабутин" Майкрософт сказала, что ну типа, а линксом мы заниматься не будем, это типа комьюнити работа, если вам надо, вы и делайте, грубо говоря, и так оно как-то так, если надо, вы и делайте, весело, особо никто ничего не делает, пока не делал, пока не пришли ребята и внезапно Авалоний и сделали. +5903.92 5917.60 "Игорь Лабутин" Значит, это не совсем относится прям к новостям dotnet.conf по большому счету и релиза .NET, но как-то уж больно удачно совпало, что команда Авалонии сделала следующую штуку. +5917.60 5992.64 "Игорь Лабутин" Они взяли MAUI, притащили его на линукс и на самом деле в браузер, заменив внутренний бэкэнд на Авалонию, то есть, ну грубо говоря, у вас есть фронтенд, да, это на экзамбле, вы пишете там, всякий лэйаузинг и так далее, есть бэкэнд, который собственно все это решует, грубо говоря, соответственно, вот этот рендеринг теперь делается Авалонией, но в качестве экспериментального режима, все это поддержано на дисклопном линуксе, на импедат линуксе, в fb-ассембле, более технически это все работает и на винде и на макоси, потому что Авалония там работает нормально, при этом если попробовать это на макоси по сравнению с базовым MAUI, то появляется ускорение чуть ли не в два раза в определенных сценариях, ну потому что Авалония рисует сама, я помню, что MAUI он базируется на стандартных контроллах, Авалония все рисует сама, может это делать быстро, оптимально и так далее, показывает единый естественно UI теперь на всех платформах в данном случае, но ценой того, что это UI все-таки не нативный, а все-таки отрисованный самим Авалонией, но если вам нужно, чтобы ваше приложение смотрелось одинаково, то вот, вполне вариант. +5992.64 6011.80 "Игорь Лабутин" Возникает интересный вопрос, а нафига, так сказать, то есть зачем, зачем Авалонии, которую я как-то всегда, по крайней мере мы, ну я по крайней мере смотрел на нее как такого, альтернативный кроссплатформенный UI, да, который ты как бы будешь рассматривать как альтернатива MAUI. +6011.80 6018.96 "Игорь Лабутин" Зачем тащить это все в MAUI и зачем делать отдельный бэкэнд в MAUI? +6018.96 6111.72 "Игорь Лабутин" Ну, как у них написано, что честный ответ заключается в том, что мы очень хотим, значит, позаботиться о тех, кто разрабатывает на дотнете всякие клиентские приложения, вот, команды многие уже выбрали MAUI, как там либо историческую альтернативу Xamarin.Forms, ну не альтернативу, а исторического наследника Xamarin.Forms, и хочется, чтобы в MAUI появлялось больше всего интересного, при этом если получится сделать такую штуку, чтобы MAUI-приложение заработало на Линуксе, ну как бы команда будет рада, возможно она не будет использовать Авалонийский бэкэнд на других платформах, но по крайней мере на Линуксе будет работать, вот, а это с одной стороны, то есть вроде как комьюнити с этого выигрывает, с другой стороны выигрывает сама Авалония, потому что это некоторые, ну скажем так, внутренний тест для понимания, чего самой Авалонии не хватает, вот, то есть запуская MAUI поверх Авалонии, можно понять, чего не хватает в самом ядре Авалонии и чего нужно туда добавить, вот, и какие есть проблемы в тулинге, какие есть проблемы в скорости или еще где-то, поскольку чтобы Авалонии тоже со всеми конкурировать, нужно быть, ну скажем так, хорошо развитым во всех областях, ну и соответственно такая вот попытка внедриться в другую экосистему, ну экосистема, наверное, громко сказано, в другой фреймворк покажет, возможно, какие-то слабые места, вот. +6111.72 6135.36 "Игорь Лабутин" Ну и, соответственно, есть некоторая надежда, что, например, если у вас есть какое-то MAUI-приложение, вам нужно его на Linux, вы возьмете Авалонию, попробуете таким образом ее запустить, все запустится, хорошо, это приложение продолжит работать на связке MAUI с Авалонией, но может быть для совсем продукта вы рассматриваете уже чистую Авалонию, почему нет, тоже как бы команде будет хорошо и приятно. +6135.36 6139.96 "Анатолий Кулаков" Да, потому что у тебя опыт под MAUI, зачем тебе рассматривать Авалонию? +6139.96 6144.24 "Анатолий Кулаков" Мне кажется, наоборот, если ты понимаешь, что MAUI работает теперь кроссплатформенно, то кому нужна Авалония? +6144.24 6146.64 "Игорь Лабутин" Ну, кроссплатформенно, но без Линукса. +6146.64 6150.52 "Анатолий Кулаков" Не, ну погоди, мы ее запустили на Линуксе с помощью Авалонии. +6150.52 6151.52 "Анатолий Кулаков" Да. +6151.52 6152.52 "Анатолий Кулаков" Теперь на Линуксе тоже. +6152.52 6153.52 "Анатолий Кулаков" Ну, теперь на Линуксе. +6153.52 6154.52 "Игорь Лабутин" Кроссплатформенно. +6154.52 6159.04 "Игорь Лабутин" Ну, например, потому что у тебя на MAUI ты не получишь единый look and feel, если тебе это надо. +6159.04 6160.56 "Анатолий Кулаков" Ну, если не надо. +6160.56 6162.84 "Игорь Лабутин" Ну, если не надо, то не надо, а кому-то надо. +6162.84 6166.80 "Анатолий Кулаков" Ну, похоже, Авалония прям реально себе ноги отстреливает. +6166.80 6175.96 "Игорь Лабутин" Либо ноги отстреливает, либо пытается таким образом себе зайти нестандартным путем на другой рынок, так скажем. +6175.96 6179.56 "Игорь Лабутин" Ну, показать другим, что ее тоже можно использовать. +6179.56 6180.56 "Игорь Лабутин" Почему нет? +6180.56 6183.76 "Анатолий Кулаков" Ладно, надо как-то в будущих выпусках этот вопрос получше +6183.76 6184.76 "Игорь Лабутин" открыть. +6184.76 6185.76 "Игорь Лабутин" Да, надо посмотреть, надо почитать. +6185.76 6186.76 "Игорь Лабутин" Интересная тема. +6186.76 6191.88 "Игорь Лабутин" Я вот только увидел пока эту одну статью, посмотрим, что будет, к чему приведет. +6191.88 6196.68 "Игорь Лабутин" Я не смотрел никакую там, какая там реакция комьюнити, вот это все. +6196.68 6199.16 "Игорь Лабутин" Почитаем, поищем, если что найдется, еще обязательно доложим. +6199.16 6204.40 "Игорь Лабутин" Вот такие у нас дела про Мауи и внезапно про Авалонию. +6204.40 6213.12 "Анатолий Кулаков" Слушай, ну у нас там еще полбэклога, я, наверное, предлагаю все это пока разрезать и оставшуюся часть рассказать в следующем выпуске. +6213.12 6216.20 "Анатолий Кулаков" Или ты какую-нибудь тему хочешь сегодня задумать? +6216.20 6220.80 "Игорь Лабутин" Давай мы, наверное, да не, наверное, в принципе, в основном все. +6220.80 6230.84 "Игорь Лабутин" Кажется, что все остальное это всякий тулинг вокруг, мы там Visual Studio, Spire и прочее, давай действительно отнесем на следующий выпуск. +6230.84 6236.88 "Игорь Лабутин" Вот, они немножко отдельно от Дотнета в каком-то смысле. +6236.88 6242.08 "Игорь Лабутин" А там, глядишь, может еще что новенького появится про десятку после релизного. +6242.08 6243.08 "Игорь Лабутин" Добавим. +6243.08 6245.20 "Анатолий Кулаков" Я думаю, обязательно появится, да. +6245.20 6261.00 "Анатолий Кулаков" Основные вещи мы сегодня успели, оборзели, поэтому смотрите, используйте, ставьте, а на следующий выпуск мы еще вам принесем много интересного, опять же, тулинга вокруг и все еще нового релиза и все еще каких-то новых инструментов, поэтому не переключайтесь, +6261.00 6262.00 "Игорь Лабутин" приходите. +6262.00 6263.00 "Игорь Лабутин" Обязательно. +6263.00 6266.48 "Игорь Лабутин" А на сегодня, на этом 126 выпуск мы заканчиваем. +6266.48 6269.08 "Игорь Лабутин" Погоди, а по темкам, по темкам? +6269.08 6270.08 "Игорь Лабутин" По темкам? +6270.08 6300.76 "Игорь Лабутин" Ну давай я еще раз перечислю, что мы посмотрели, что новенькое в C# 14-м, в .NET 10-м рантайме, в F# 10-м, в SDK и тулинге для 10-го .NET, в библиотеках для 10-го .NET, в S/4 для 10-го .NET, в EF Core для 10-го .NET, в MAUI для 10-го .NET и в самом конце остались, возможно, немножко удивлены тем, на фига в Алонии идти в бэкэн для Linux MAUI, но вот на этой загадочной ноте мы тогда, видимо, и попрощаемся на сегодня. +6300.76 6310.16 "Анатолий Кулаков" Да, хорошее, хорошее количество прям тем успели успеть, не каждый выпуск такой бывает, и темы все интересные и прекрасные. +6310.16 6318.04 "Анатолий Кулаков" Друзья, не забывайте, там шары, репосты, лайки, заходите рассказывать о нас друзьям и все такое, все, что вы знаете. +6318.04 6325.84 "Анатолий Кулаков" До новых встреч, в следующем выпуске еще поговорим о .NET 10-м, да и не только, там много всего интересного появилось, о чем мы еще не успели сегодня рассказать. +6325.84 6326.84 "Анатолий Кулаков" Пока. +6326.84 6327.36 "Игорь Лабутин" Пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-127.txt b/input/Radio/Transcriptions/RadioDotNet-127.txt new file mode 100644 index 0000000..d805a8a --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-127.txt @@ -0,0 +1,581 @@ +0.00 10.98 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Радио.нет выпуск 127. +10.98 14.66 "Анатолий Кулаков" И в нашей студии его постоянные ведущие Анатолий Кулаков. +14.66 15.66 "Игорь Лабутин" И Игорь Лабутин. +15.66 16.66 "Игорь Лабутин" Всем привет. +16.66 20.86 "Анатолий Кулаков" А также за нашими спинами наши прекрасные помогаторы. +20.86 29.38 "Анатолий Кулаков" Среди них Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко. +29.38 31.54 "Анатолий Кулаков" Уже выздоравливает, молодец, Оленька. +31.54 48.60 "Анатолий Кулаков" Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев, Юрий Лодейкин, Котков Михаил и Михаил Королев. +48.60 58.54 "Анатолий Кулаков" Друзья, всем спасибо большое, и если вы захотите вдруг нас тоже поддержать, то можете сделать нам новогодний подарочек и зайти на Boosty, посмотреть, что там интересного творится. +58.54 66.34 "Игорь Лабутин" А задумывались ли вы, как синоптики предсказывают дожди, страховые компании рассчитывают страховые коэффициенты, а экономисты потенциально рост показателей. +66.34 73.30 "Игорь Лабутин" Все они используют теорию вероятности и комбинаторику, чтобы составить все возможные исходы событий, а также это применимо и для прогнозов на спорт. +73.30 79.38 "Игорь Лабутин" Ребята из Altenar, где разрабатывают платформы для зарубежных бейтинг-операторов, весной делали об этом доклад на дотнет метапе. +79.38 91.50 "Игорь Лабутин" В компании есть целая команда математиков, которые проектируют мат-модели для десятков видов спорта, а одна из дотнет команд, которая как раз и делала доклад, описывает эти модели на C#, используя глубинные средства языка и оптимизирует алгоритм расчета коэффициентов. +91.50 97.50 "Игорь Лабутин" Затем их код встраивается в систему других команд, чтобы пересчитывать сотни тысяч вероятностей для спортивных матчей в софт-реал тайме. +97.50 120.38 "Анатолий Кулаков" Ну что ж, а мы в прошлом выпуске обсудили самую главную тему за весь год — это релиз основных инструментов, языков, тулзов, SDK-ов и прочего такого, и у нас немножко еще осталось хвостов, которые мы недообсудили, ну и одним из самых главных номерах хвостов, которые наконец зарелизились за многие-многие годы — это Visual Studio 2026. +120.38 125.58 "Анатолий Кулаков" Ну, релизы у нее были до этого, но они были все-таки не 26. +125.58 130.02 "Анатолий Кулаков" А тут наконец-то ей дали новый мажорный номер, посмотрим, сколько он продержится. +130.02 134.34 "Игорь Лабутин" Ну да, прошлый продержался 4 года, получается, 22-я студия у нас была. +134.34 136.26 "Игорь Лабутин" Посмотрим, что появилось в 26-м. +136.26 143.30 "Игорь Лабутин" На самом деле, опять же, мы частично про это рассказывали, превью, или как они там, инсайдер превью версии выходили, но давайте еще раз пробежимся. +143.30 147.14 "Игорь Лабутин" Как обычно, все разделено на разделы, и первый раздел — это IDE. +147.14 152.54 "Игорь Лабутин" Хотя, казалось бы, в Visual Studio и так есть IDE, но что появилось в IDE в целом? +152.54 181.66 "Игорь Лабутин" Во-первых, появилась в поиске или в навигации такая фича, они ее называют Did You Mean, в описании написано «помогает находить файлы, про которые вы забыли», то есть смысл в том, что вы иногда, когда редактируете код, вспоминаете, что, блин, был какой-то файл, где было написано вот что-то такое, и теперь вот это что-то такое можно попытаться ввести в окно поиска, и студия попытается вспомнить или найти, на самом деле, где же вы были, где вы могли видеть что-то подобное. +181.66 196.72 "Игорь Лабутин" Дальше, небывалая штука, долгое время было доступно в IDE фича под названием код-каверидж, можно было запустить тесты, например, и посмотреть, какой каверидж вашего кода получается. +196.72 203.14 "Игорь Лабутин" Теперь это доступно и в комьюнити, и в профессиональной сфере, совершенно так сказать, бесплатно, если речь о комьюнити. +203.14 250.66 "Игорь Лабутин" Естественно, с новой версии не могли не обновить дизайн, ну или как это по-английски называется, look and feel, и естественно самая важная фича это то, что у нас теперь есть 11 новых тем, не только стандартные там, темненькая, светленькая и синенькая, или какая-то там была сиреневенькая, их теперь 11 разноцветных, при этом можно отдельно настроить окно редактора, то есть независимо от того, как у вас будет выглядеть остальное обвесо в студии, редактор можно настроить так, как нужно, потому что это основное окно, с которым вы работаете, пишете код, она будет пытаться сохранить шрифты, даже если вы меняете какой-то layout, ну в общем, или тему, ну в общем, поиграйте с новым look and feel, говорят, ну в целом, нормально. +250.66 273.02 "Игорь Лабутин" Изменили окошко сеттингов, там теперь все по-умному, короче можно поискать, не стандартное, мне казалось даже смахивающе на винформочку практически, окошко настрой, которое было раньше, теперь там мандариновое дерево слева, в котором можно пофильтровать, поискать, короче, выглядит посовременнее, хотя говорят, что поиск работает так себе. +273.02 276.90 "Игорь Лабутин" Ну и setup assistant, когда вы настраиваете студию, чуть-чуть попроще workload ставить. +277.50 290.50 "Игорь Лабутин" С точки зрения productivity, естественно, не могли не сунуть туда AI в каком-либо виде, сунули его в разных видах, и один из видов это adaptive paste, ну то есть адаптивная вставка кода. +290.50 301.14 "Игорь Лабутин" Когда вы вставляете какой-то кусочек кода, этот самый копайлот смотрит на то, что вы вставляете, смотрит на то, куда вы вставляете, и начинает немножко этот код преобразовывать. +301.14 309.82 "Игорь Лабутин" То есть, например, он может добавить всякие недостающие интерфейсы или абстрактные мемберы, он может пофиксить за вас быстренько какие-то мелкие ошибки в коде, если они вдруг есть. +309.82 320.54 "Игорь Лабутин" Вы там в локноте что-нибудь написали, сделаете ctrl+v в Visual Studio, она за вас фиксит ошибки, тут же применит, естественно, тот же стиль информатирования, который есть в том коде, в который вы это все вставляете. +320.54 330.58 "Игорь Лабутин" Более того, вы можете взять кусочек кода на плюсах, сказать его ctrl+v в файлик на C#, и он преобразует алгоритм с плюсов на C#, например. +330.58 341.30 "Игорь Лабутин" Ну то есть там про плюсы был просто пример, возможно, это работает с другими языками, вероятно, это работает с не слишком сложной логикой и не слишком сложными алгоритмами, но тем не менее фича интересная. +341.30 357.62 "Игорь Лабутин" Ну и, естественно, он умеет делать повтор, так сказать, заполнения по шаблону, то есть если вы вставили какой-нибудь там повторяющийся кусочек кода, он может вполне сообразить, что вы хотите дальше дописать его сообразно вашему шаблону. +357.62 363.86 "Игорь Лабутин" Например, обработали вставленный кусочек кода одно значение кенума, он пишет код до остальных значений кенума. +363.86 367.50 "Игорь Лабутин" Ну в общем, звучит прям очень мощно, посмотрим, как будет работать на самом деле. +367.50 371.58 "Игорь Лабутин" И с Капайлотом теперь можно общаться из контекста. +371.58 380.94 "Игорь Лабутин" Меню стало гораздо удобнее, говорят, не знаю, насколько это прям удобно работать с клавиатурой, вероятно, шорткатами будет еще быстрее, но посмотрим. +380.94 396.34 "Игорь Лабутин" В Markdown редакторе и в Капайлот чате теперь нормально рендерятся Mermaid диаграммы, мне, правда, казалось, что в Markdown они давно до рендерятся, но почему-то это прям фичей заявлено, может быть, как-то отдельно рендерились. +396.34 413.34 "Игорь Лабутин" На нижней границе редактора появились всякие такие улучшенные контроллы, которые туда пытались впихнуть, и при этом не сделать так, чтобы горизонтальный скролл бар, мы это, я помню, обсуждали, не стал шириной пару пикселей, в общем, как-то это все поместилось. +413.34 423.46 "Игорь Лабутин" Там теперь можно посмотреть на позицию курсоров, какой кодировки текущий файл, можно вызвать контекст-меню, чтобы все это закастомизировать, короче, все стало совсем здорово. +423.46 440.18 "Игорь Лабутин" В поиске можно исключать различные файлы, ну и поменяли немножко шорткаты, то есть, например, ну все, наверное, уже привыкли, что Ctrl+W закрывает вкладку в браузере и так далее, но она не закрывала вкладку в редакторе Visual Studio, теперь закрывает. +440.18 447.70 "Игорь Лабутин" Ну и также как Ctrl+P, по аналогии с VS Code, открывает теперь код Search, ну и команды. +447.70 465.14 "Игорь Лабутин" В Capilote, соответственно, там чуть-чуть чат улучшился, он теперь понимает ссылки на внешние символы, чуть более точно указывает, или можно ему сослаться на определенные строки в исходных файлах, он это лучше теперь воспринимает. +465.14 468.90 "Игорь Лабутин" Довольно много улучшений в дебаггинге и в диагностике. +468.90 482.86 "Игорь Лабутин" Во-первых, появился дебаггер-эджент, естественно, AI-эджент, куда же без него, для юнит-тестов, он теперь может посмотреть на упавший юнит-тест и пойти пофиксить код, который, так сказать, падает. +482.86 496.22 "Игорь Лабутин" Более улучшенный анализ исключений, точно также смотрит на контекст репозитория и AI-кой понимает, что не так с этим исключением и почему оно возникло. +496.22 522.46 "Игорь Лабутин" Ну и куча всяких разных мелких физуализаций, которые, давным-давно доступны в ReSharper, всякие там подсветка реальных, так скажем, значений, которые получились внутри выражений типа if-стейтментов, после возвращения значений, в параметрах, то есть теперь можно это все видеть без необходимости копировать какие-то кусочки в watch. +522.46 527.46 "Игорь Лабутин" Улучшили скорость запуска для дебаггинга примерно на 30%, когда вы F5 жмете, теперь будет быстрее. +527.46 533.38 "Игорь Лабутин" Ну и всякое разное по мелочи. +533.38 556.90 "Игорь Лабутин" Из интересного появился project-темплейт для бенчмарк.нета, то есть теперь прям свежо у студии поставляется темплейт для бенчмарк.нета, и более того, в код-ленсах теперь показывается, если вы запустили бенчмарк из студии, который написан на бенчмарк.нете, в результате вам код-ленсы покажут, где какие проблемы с локациями или с CPU. +556.90 561.10 "Игорь Лабутин" Уж не знаю, как это работает, но звучит по крайней мере круто. +561.10 562.10 "Игорь Лабутин" Надо будет как-нибудь попробовать. +562.10 563.10 "Игорь Лабутин" Да, классная интеграция. +563.10 564.10 "Игорь Лабутин" Попробовать. +564.10 589.66 "Игорь Лабутин" Ну и в гиде, естественно, куда же без него, всякие пиар-комменты, поулучшили код-ревью, копайлот-чат понимает гид-контекст, чуть попроще навигироваться между комментариями, когда вы ревьюете что-то, и можно прямо применять предложение для фикса вашего пиара, которое можно к нему оставлять прямо внутри студии. +589.66 594.58 "Игорь Лабутин" Ну и, естественно, поддержан 10-й тутнет, C# 14, и вот это всё. +594.58 601.02 "Игорь Лабутин" Ну там понятно, что про плюсы и прочие специфические штуки я особо не рассказываю, это интересно тем, кто занимается плюсами. +601.02 605.22 "Игорь Лабутин" Вот такой вот релиз, примерно всё про него. +605.22 610.82 "Анатолий Кулаков" Не, ну нормально-нормально, хорошая вроде студия, хорошее обновление. +610.82 621.22 "Анатолий Кулаков" Теперь посмотрим, как она себя на практике покажет, т.е. надо её в боевую повязать, в хвост и в гриву, и насколько всё это удобство, все терюшечки, подсветочки, скругленькие края, насколько они на практике будут удобны. +621.22 635.10 "Игорь Лабутин" Ну, помимо студии, у нас же есть ещё один тул, про который мы рассказывали, наверное, каждый, или почти каждый выпуск, и, наконец-таки, у нас есть полноценный релиз, правда ведь? +635.10 636.10 "Игорь Лабутин" Ну да, да. +636.10 640.22 "Игорь Лабутин" Или это тоже очередной полупревью, полуинкрементальный релиз? +640.22 674.02 "Анатолий Кулаков" Ну, вот тут как раз-таки наоборот, речь идёт о релизе Aspire 13, и не то, что он полурелиз, а наоборот, 2,5 релиз, потому что совсем недавно, буквально в сентябре, мы в нашем радио рассказывали о том, что вышел Aspire 9.5, и как ни странно тоже в релизе, т.е. был релиз 9.5, совсем пару месяцев назад, и тут нежданно-негаданно после версии 9.5 появился Aspire 13, куда скипнули там предыдущие 11, 12, 10 версии, в общем, никому неизвестно. +674.02 679.30 "Анатолий Кулаков" Ну, да не так уж и жалко, пусть будет 13, раз людям так удобно. +679.30 692.34 "Анатолий Кулаков" И этот релиз, он не зря перемахнул столько много версий, не зря как бы выпустился совсем сразу после 9.5, потому что он свернул Aspire на какую-то уже, знаешь, более нормальную дорожку. +692.34 704.18 "Анатолий Кулаков" Мы уже много лет как бы высматриваем и думаем, а куда Aspire идёт, что он делает, зачем он вообще нужен, как он позиционируется, и вот тут что-то начинает вырисовываться, тоже не совсем очевидное, но что-то есть. +704.18 706.54 "Анатолий Кулаков" Сейчас мы с вами обсудим, что. +706.54 711.54 "Анатолий Кулаков" Итак, во-первых, самое главное изменение, которое только может быть, это переименование. +711.54 715.98 "Анатолий Кулаков" Aspire теперь не называется .NET Aspire, а он называется просто Aspire. +715.98 720.70 "Анатолий Кулаков" Вот, это самая главная фишка, самая главная фича, и все об этом должны знать. +721.22 727.30 "Анатолий Кулаков" Ну и теперь он перестал быть, естественно, .NET, концентрированным какой-то платформой. +727.30 739.46 "Анатолий Кулаков" Он теперь стал Polyglot Application Platform, то есть теоретически должен понимать такой мультиязыковой, должен много языков понимать, должен много всего уметь, посмотрим, что же это значит на практике. +739.46 749.54 "Анатолий Кулаков" И в версии 13 он действительно добавил First Class Support, объявил три языка, это .NET, Python и JavaScript. +749.54 753.22 "Анатолий Кулаков" Вот такой интересный наборчик в рамках этих трех языков. +753.22 760.58 "Анатолий Кулаков" Он умеет их запускать, дебажить, деплойть, всяческие пакеты там ставить и прочие-прочие вещи. +760.58 775.66 "Анатолий Кулаков" Но, кроме этого, у него есть не First Class Support языки, а такие сбоку прилепка языки и там на официальном сайте тоже задекларированы Go, Java, TypeScript и есть там кое-какие еще дополнительные. +775.66 788.78 "Анатолий Кулаков" В общем, это языки, которые он немножко понимает, немножко знает, но не так хорошо, как первые три, но постепенно естественно вот этот First Class Language Support, он будет развиваться и расширяться. +788.78 792.02 "Анатолий Кулаков" Также у Aspire теперь новый сайт, сайт называется Aspire.dev. +792.02 802.02 "Анатолий Кулаков" Для своего запуска Aspire требует .NET 10 SDK или более новый и давайте же посмотрим, что в нем все-таки такого появилось. +802.02 814.22 "Анатолий Кулаков" Прежде всего, это First Class Python Support, то есть теперь поддерживаются всякие питоновские программы, питоновские модули, питоновские экзешники и самое интересное – это работа с пакетч-менеджерами. +814.22 819.10 "Анатолий Кулаков" Питоновские пакетч-менеджеры тоже хорошо умеют пониматься в Aspire. +819.10 841.94 "Анатолий Кулаков" Дальше у нас Aspire может генерить докер-файлы автоматически для питоновских программ и практически то же самое для JavaScript, то есть он понимает npm-based приложения, автоматически понимает, какой пакетч-менеджер он использует, он умеет дебажить все эти приложения и также застроить всякие докер-контейнеры для них. +841.94 861.16 "Анатолий Кулаков" И появилась интересная инфраструктура, то есть как только у нас Aspire начал поддерживать несколько языков, несколько фреймворков, платформ, npm в этих всяких, необходима была инфраструктура, которая помогает обмениваться полезными свойствами между всеми этими языками, фреймворками. +861.16 870.02 "Анатолий Кулаков" Как мы помним, Aspire это же не только просто запускальщик дотнета, это еще и такой переноситель настроек между различными контейнерами. +870.02 889.78 "Анатолий Кулаков" То есть у нас один контейнер знал про другой контейнер, то есть он, например, если вы поднимали в дотнете какой-нибудь пасгрю, то в дотнет-приложении прокидывалась информация о том, на каком адресе эта пасгря поднята, с каким коннекшн-стрингом она поднята, на каком порту, а также время, когда она была поднята, чтобы ей можно было дождаться и много других вот таких мелочей. +889.78 896.10 "Анатолий Кулаков" Все вот эти инфраструктурные штуки, они как раз и переехали в кросс-платформенную историю. +896.10 911.58 "Анатолий Кулаков" То есть теперь вы между различными языками, независимо от чего, можете обмениваться всякими настройками, пропертями, опциями, сеттингами, также есть проброска сертификатов и появилась улучшенная поддержка контейнеров. +911.58 916.30 "Анатолий Кулаков" То есть Aspire перешел на новую парадигму управления контейнерами. +916.30 937.02 "Анатолий Кулаков" Теперь он считает, что аутпут каждого пайплайна должен быть контейнером, это позволяет ему сделать такие изолированные, reproducible, переносимые артефакты, потому что раньше он работал более-менее с папками и папки они были не очень такие переносимые и повторяемые, а вот контейнеры это идеальный артефакт для повторяемости, изолированности. +937.02 940.86 "Анатолий Кулаков" В общем, теперь он с контейнерами жонглирует тоже намного лучше. +940.86 966.94 "Анатолий Кулаков" Появилась новая команда, которая называется Aspire Tool и это специальная команда, которая делает из Aspire такую платформу для того, чтобы собирать, деплоить и паблишить ваши приложения, при этом оркестрируя их в сложном пайплайне, который может параллелиться, отслеживать всякие зависимости и понимать, куда он деплоится и зачем. +966.94 971.62 "Анатолий Кулаков" Можно сказать, что это такое средство CI/CD, средство деплоя. +971.62 975.54 "Анатолий Кулаков" Появилась новая команда Aspire Init. +975.54 979.54 "Анатолий Кулаков" Она нужна для того, чтобы работать лучше со всякими приложениями. +979.54 992.18 "Анатолий Кулаков" Допустим, если у вас есть уже готовое приложение и вы хотите сделать над ним Aspire-обертку, включить его, по сути, в наш Aspire Framework, в общем, вы можете это сделать как раз с помощью этой команды. +992.18 1001.74 "Анатолий Кулаков" И еще Aspire Init как раз помогает вам деплоить приложения и не просто деплоить, а сохранять знания о предыдущем стейте. +1001.74 1011.54 "Анатолий Кулаков" То есть вы запустили какой-то деплой, у вас приложение ушло на продакшн, потом вы что-то там сделали, каким-то образом библиотечки обновились, контейнеры обновились и еще раз делаете деплой. +1011.54 1016.14 "Анатолий Кулаков" И в этот момент Aspire знает, какое состояние у него было при ведущем. +1016.14 1021.70 "Анатолий Кулаков" То есть он запоминает, что ушло на продакшн, сравнивает с тем, что обновилось, и может на продакшн сдеплоить только то, что обновилось. +1021.70 1025.30 "Анатолий Кулаков" А то, что не обновлялось, соответственно, у него ресурсы не тратить. +1025.30 1035.82 "Анатолий Кулаков" В Visual Studio Code появился экстеншн, точнее там был экстеншн, но у него там очень много новых команд появилось. +1035.82 1047.90 "Анатолий Кулаков" Например, там можно создать проект, можно всякие интеграции настроить, можно опять же дебажить вот эти все языки, которые в First Class сетильны и все такое, и деплоить Visual Studio Code теперь тоже можно с помощью Aspire. +1047.90 1054.18 "Анатолий Кулаков" То есть Visual Studio Code получается своеобразная IDE, такая студия для управления Aspire. +1054.18 1059.18 "Анатолий Кулаков" Так, теперь немножко подробнее, вот эти First Class citizen языки. +1059.18 1060.18 "Анатолий Кулаков" Начнем с Python. +1060.18 1061.18 "Анатолий Кулаков" Что же это означает? +1061.18 1063.98 "Анатолий Кулаков" Что Python поддерживает несколько версий запуска Python. +1063.98 1069.30 "Анатолий Кулаков" Не, не так, Aspire поддерживает несколько версий, как можно запустить Python. +1069.30 1072.94 "Анатолий Кулаков" Python у нас, соответственно, может распространяться в виде обычного скрипта. +1072.94 1080.26 "Анатолий Кулаков" Вы можете настроить в Aspire Config точно так же, а как мы помним, Aspire Config это обычный C# файл. +1080.26 1082.58 "Анатолий Кулаков" То есть вы можете в C# файле настроить. +1082.58 1086.54 "Анатолий Кулаков" Билдер - это Python App и там прописать необходимые параметры. +1086.54 1094.90 "Анатолий Кулаков" Дальше мы можем подключить Python в виде модуля, а можем подключить Python в виде запускаемого приложения, которое запускается через Virtual Environment. +1094.90 1097.74 "Анатолий Кулаков" Aspire прекрасно тоже понимает Virtual Environment. +1097.74 1107.14 "Анатолий Кулаков" Также он автоматически распознает, то есть сканирует все исходники или модули Python и автоматически распознает, какой Package Manager используется в Python. +1107.14 1129.38 "Анатолий Кулаков" Поддерживается целая пачка, из самых популярных это uvpip, и также Aspire умеет генерировать Dockerfile, то есть анализируя то, что было на входе, на выходе, он умеет понимать, как питоновские приложения собираются и генерит Dockerfile специально для того, чтобы питоновский скрипт отлично собрать и запаблишить. +1129.38 1157.70 "Анатолий Кулаков" Практически все то же самое поддерживается для JavaScript, то есть для JavaScript приложения тоже распознаются, автоматически распознается Package Manager NPM, Yarn, PNPM, также можно сделать там настройку под свои кастомные какие-то менеджеры, если вам это нужно, и точно так же распознается вся структура JavaScript, генерится Dockerfile и правильно паблишится как нужно. +1157.70 1158.94 "Анатолий Кулаков" Есть поддержка ноды. +1158.94 1173.82 "Анатолий Кулаков" Из интересных, из сертификатов, как вы, наверное, знаете, что у хороших приложений всегда должны быть настроены правильные сертификаты, Developer Certificate Trust между ними. +1173.82 1196.06 "Анатолий Кулаков" Ну так вот, Aspire автоматически настраивает сертификаты, как только вы вот этими командами @JavaScriptApp, @PythonApp подключили необходимые языки, необходимые модули, то между ними всеми пробросились правильные девелопер сертификаты и настроились, потому что все девелопер сертификаты можно настроить банально через переменные среды окружения, чем Aspire пользуется. +1196.06 1208.54 "Анатолий Кулаков" Он прописывает правильные параметры, опять же, зная, что там под капотом Node.js, зная, что под капотом Python, Aspire знает правильные environment-параметры, в которые нужно прописать сертификаты, чем он и обязательно пользуется. +1208.54 1221.38 "Анатолий Кулаков" И вам нет необходимости настраивать что-то дополнительное, то есть вы точно знаете, что приложение, собрано Aspire, уже настроено, сертифицировано и все подключено и работает, что вообще прекрасно. +1221.70 1230.08 "Анатолий Кулаков" Также, как и раньше, он умеет настраивать переменные среды окружения и через эти переменные среды окружения пробрасывать необходимые урлы. +1230.08 1239.78 "Анатолий Кулаков" Но только если раньше он пробрасывал их между дотнетными проектами или приложениями, то теперь он умеет пробрасывать их, естественно, между всеми языками, всеми программами, которые у них есть. +1239.78 1252.14 "Анатолий Кулаков" То есть через, опять же, переменные среды окружения он может сообщать connection-стринги различным базам данных или адреса сервисов, на которых запущены их соратники, соседи. +1252.14 1256.54 "Анатолий Кулаков" То есть получается у нас такой сервис-дискавери между различными языками. +1256.54 1273.38 "Анатолий Кулаков" Если мы запустили дотнет-приложение и нам нужно запустить фронт-энд на джаваскрипте, то фронт-энду передается правильный адрес, на котором будет запущено дотнет-приложение, и между ними происходит такой сервис-дискавери, прямо на уровне еще билда. +1273.38 1286.34 "Анатолий Кулаков" В Aspire поддерживается сингл-файл-апхост приложения, я напомню, мы в одном из выпусков подробно обсуждали это, когда в одном cs-файле у вас собрано все дотнет-приложения. +1286.34 1295.78 "Анатолий Кулаков" То есть вы можете объявить там и пакеты какие-то новые подключаете, и описать роуты, которые вы должны слушать, на каком порту, и там же хендлеры написать. +1295.78 1302.46 "Анатолий Кулаков" В общем, для таких маленьких приложений, которые экспозят там парочку урлов, парочку эндпойнтов, прекрасная тема. +1302.46 1311.38 "Анатолий Кулаков" Поэтому вы можете подключить к Aspire просто один cs-файл, без проекта, без солюшена, без каких-то package-менеджеров конфигов и прочего. +1311.38 1312.98 "Анатолий Кулаков" Один прекрасный cs-файлик. +1312.98 1313.98 "Анатолий Кулаков" Очень удобно. +1313.98 1319.18 "Анатолий Кулаков" В превью версии есть фича, которая называется автоматическая установка дотнет-сдк. +1319.18 1326.18 "Анатолий Кулаков" То есть теперь для вашего приложения, для вашего дотнета, и вообще для всего Aspire не обязательно иметь уже готовый дотнет-сдк. +1326.18 1331.18 "Анатолий Кулаков" Он при первом запуске команды Aspire Run автоматически просканируется и может установиться сам. +1331.18 1348.34 "Анатолий Кулаков" Команда Aspire Do, о которой я кратко упоминал выше, это такая специально сложная система для координации билдов, и она интересна тем, что у нее есть очень мощный пайплайн. +1348.34 1352.22 "Анатолий Кулаков" То есть это даже такая система управления пайплайнами. +1352.22 1360.74 "Анатолий Кулаков" Если вы когда-нибудь настраивали TeamCity пайплайн или Octopus пайплайн, или может быть Nuke Build пайплайн, то вот такая штука очень сильно похожа на него. +1360.74 1366.30 "Анатолий Кулаков" То есть есть какие-то шаги, есть какая-то связь между этими шагами, и эти шаги могут запускаться. +1366.30 1375.06 "Анатолий Кулаков" Они могут запускаться с учетом зависимостей, с учетом ошибок, с учетом параллельности, и в зависимости от того, что эти шаги делают, происходят какие-то действия. +1375.06 1390.02 "Анатолий Кулаков" Ну, в частности, например, можно забилдить приложение, то есть построить его, можно его запаковать в докер-контейнеры, можно эти докер-контейнеры задеплоить и прочие-прочие такие стандартные девопсовские маневры делать. +1390.02 1402.90 "Анатолий Кулаков" Дальше контейнеры у нас умеют строиться как артефакты, я уже говорил, но есть еще одна прикольная фишка – это в том, что вы можете из контейнера скопировать какие-то ресурсы и вставить их внутрь другого контейнера. +1402.90 1418.98 "Анатолий Кулаков" Это, например, очень удобно, когда вам нужно скомпилировать фронт-энд в отдельном контейнере, потом взять из этого контейнера артефакты, то есть то, что получилось в результате компиляции, и, допустим, вставить это в тот контейнер, в котором запускается бэкэнд. +1418.98 1423.14 "Анатолий Кулаков" Ну, чтобы у вас и фронт-энд, и бэкэнд в результате оказались в одном докер-контейнере. +1423.14 1431.70 "Анатолий Кулаков" Если, допустим, у вас там какой-то статический сайт вы делаете, то вам нет никакого смысла держать два докер-контейнера запущенные для того, чтобы раздавать статику, допустим. +1431.70 1446.34 "Анатолий Кулаков" Ну, а то, что фронт-энд нужно компилировать обязательно в отдельном докер-контейнере, как бы с изоляцией и закрытыми форточками, я думаю, вы уже все знаете, потому что что там творится внутри – это ужас, ни в коем случае не держите вместе фронт-энд и прекрасный бэкэнд. +1446.34 1456.10 "Анатолий Кулаков" Так, дальше появился интересный Docker Builder Fluent API, тоже в экспериментальном режиме, но все же. +1456.10 1469.98 "Анатолий Кулаков" То есть это специальный такой конструктор в C#, который можно назвать встроенным DSL, то есть это специальный метод расширения, там Fluent Interface для того, чтобы в C# построить типа безопасный докер-файл. +1469.98 1473.58 "Анатолий Кулаков" Ну, то есть не сам докер-файл, а вот декларативно его писать. +1473.58 1484.06 "Анатолий Кулаков" Это какой-то файл, докер-файл, и вы вызываете метод from, указываете базовый образ, потом в work-директоре указываете рабочую директорию, потом метод copy, указываете откуда что копировать. +1484.06 1487.70 "Анатолий Кулаков" В общем, описываете докер-файл, как если бы вы писали ручками, только в C#. +1487.70 1500.10 "Анатолий Кулаков" Это позволяет более-менее какие-то там безопасность типов соблюдать и на этапе сборки делать какие-то проверочки минимальные, чтобы там ничего не забыли, все правильно написали, где нужна папочка, указали папочку. +1500.10 1507.78 "Анатолий Кулаков" В общем, такой интересный Fluent API, мы, кстати, на своем проекте тоже такую штуку написали для того, чтобы строить специальные докер-файлы под конкретные приложения. +1507.78 1509.14 "Анатолий Кулаков" Очень удобная вещь. +1509.14 1518.22 "Анатолий Кулаков" Вот, кого я еще здесь не ожидал совсем увидеть, это .NET MAUI Integration, то есть MAUI сюда тоже залез. +1518.22 1522.50 "Анатолий Кулаков" Казалось бы, где Aspire, который там докер-контейнерами ворочает, и где MAUI. +1522.50 1524.98 "Анатолий Кулаков" Оказывается, есть где. +1524.98 1534.86 "Анатолий Кулаков" Появился новый пакет, который называется Aspire Hosting MAUI, который разрешает оркестрацию .NET MAUI приложений, которые пишутся под мобилки. +1534.86 1552.50 "Анатолий Кулаков" То есть, например, Aspire способен запустить iOS-симулятор, он может запустить Android-эмулятор и запустить в этих андроидовских и iOS-овских эмуляторах ваше приложение, которое, естественно, кроссплатформенное на MAUI и там и там запустится. +1552.50 1567.54 "Анатолий Кулаков" Более того, он свяжет их сетью, чтобы они могли общаться, и прокинет какой-нибудь OLTP-девтуннель для того, чтобы протянуть связь к вашему ASP приложению, чтобы ваши мобильные приложения могли общаться с вашим бэкэндом. +1567.54 1574.18 "Анатолий Кулаков" То есть, он понимает девтуннели, он понимает всякие симуляторы, эмуляторы, private-нетворки и прочее-прочее. +1574.18 1579.62 "Анатолий Кулаков" Такую картину вы вполне можете собрать, что в принципе прекрасно. +1579.62 1605.54 "Анатолий Кулаков" Естественно, все это собирается на наш прекрасный дашборд, то есть все вот эти андроид-симуляторы, девтуннель-эмуляторы, айспанеты, джаваскрипты, питоны, все это интегрируется с дашбордом через OpenTelemetry, ну потому что как раз OpenTelemetry у нас межплатформенный, межязыковой фреймворк, его понимают абсолютно все, и Espire позволяет внедрять его даже в питоны и даже в джаваскрипты, и оттуда получать хорошие прекрасные метрики. +1605.54 1626.90 "Анатолий Кулаков" Опять же, у Espire-дашборда появилась такая фича как AI Assistant, вы можете запросить через AI какие-нибудь ресурсы или какой-нибудь доступ к телеметрии, или попросить его проанализировать, что же такое страшного творит джаваскрипт на ваших графиках, и он прямо в дашборде вам все расскажет. +1626.90 1638.10 "Анатолий Кулаков" Появились, так как у нас теперь много языков разных, появились новые иконки, которые описывают Polyglot Language, ну то есть иконки, соответствующие различным языкам программирования. +1638.10 1646.02 "Анатолий Кулаков" Ну, шутка-шутка, но в принципе тоже красиво, когда там рисуется диаграмма взаимодействия между контейнерами, полезно видеть на каком языке какой контейнер глючит. +1646.02 1654.54 "Анатолий Кулаков" Deployment Pipeline Reimplementation – это вот как раз про Espire-do, который я вам рассказывал. +1654.54 1671.98 "Анатолий Кулаков" Espire-do – это такая штука, которая может тоже строить пайпланы, между этими пайпланами выводить зависимости, параллельно их запускать, и эти пайпланы как раз необходимы для того, чтобы уменьшить сложность и время деплоя, которое у вас уходит для того, чтобы поддерживать ваше приложение. +1671.98 1703.26 "Анатолий Кулаков" Они занимаются не только билдом, они занимаются полным CI/CD циклом, то есть они умеют деплоить и умеют делать provisioning, понимают инкрементальный деплой, то есть запихивает вам не всю вашу систему сразу, а только то, что поменялось, только то, что нужно, умеют отлаживать специальные какие-то шаги, которые вам нужно отладить, и имеют кучу диагностик для пайплайнов, чтобы вы могли, например, отследить, какой из пайпланов работает неправильно, залогировать его или вывести на те же самые дэшборды. +1703.26 1714.94 "Анатолий Кулаков" Поддерживается deployment state management, то есть это состояние, которое запоминается при первом деплое и автоматически анализируется при следующих деплоях. +1714.94 1719.38 "Анатолий Кулаков" И учитывая эту информацию, уже последующий деплой каким-то образом оптимизируется. +1719.38 1725.50 "Анатолий Кулаков" Меньше запускается, меньше скачивается, и деплоится только то, что надо в зависимости от измененных версий. +1725.50 1729.86 "Анатолий Кулаков" Все это происходит между запусками, то есть все это состояние хранится. +1729.86 1730.86 "Анатолий Кулаков" Вот. +1730.86 1740.02 "Анатолий Кулаков" В общем, получился такой большой массивный релиз, который, получается, залазит на грядки много кого. +1740.02 1761.90 "Анатолий Кулаков" Ну, на первых сразу в память приходит Nuke Build, потому что здесь есть явные намеки на то, что с помощью вот этих Aspire-do можно выстраивать пайплайны, которые в том числе и компилируют ваши приложения, запускают, может быть, даже и тесты, копируют артефакты из докер-контейнеров в различные другие докер-контейнеры, соединяют как-то эти докер-контейнеры и так далее. +1761.90 1770.38 "Анатолий Кулаков" Здесь же прослеживается наезд на всякие полюми, которые точно также на C# позволяют вам провизионить какие-нибудь инфраструктуру. +1770.38 1775.70 "Анатолий Кулаков" Здесь тоже вы на C# описываете инфраструктуру, описываете взаимосвязь между контейнерами. +1775.70 1786.86 "Анатолий Кулаков" Наверняка в будущем вы будете описывать то, как вам настроить целевую среду, какие пакеты там поставить, какой рантайм там установить и каким образом там можно через SSH все скопировать. +1786.86 1792.02 "Анатолий Кулаков" То есть это тоже какие-то наезды, получается, на Ansible, может быть, даже на Terraform. +1792.02 1796.54 "Анатолий Кулаков" В общем, немножко всем на пятки начинает Aspire-do наступать. +1796.54 1810.98 "Анатолий Кулаков" То есть примерно вырисовывается картина, что он хочет быть вот таким оркестратором, деплойером, pipeline CI/CD менеджером, который объединяет не просто там какой-то один язык, а все языки. +1810.98 1829.38 "Анатолий Кулаков" Здесь, конечно, интересен тот момент, что несмотря на то, что он там объединяет и Python, и JavaScript, и потенциально Go, Java и TypeScript, насколько разработчики на Python и, допустим, на JavaScript будут писать конфиги в Aspire, потому что конфиги-то все равно пишутся на .NET? +1829.38 1830.38 "Анатолий Кулаков" Вот это большой вопрос. +1830.38 1835.02 "Анатолий Кулаков" Возможно, может быть, чистые питанисты этого делать и не будут. +1835.02 1848.22 "Анатолий Кулаков" Но если у вас там какая-то смешанная команда, то есть питанисты, .NET-чики, JavaScript-овщики, то, в принципе, в таком случае, если команды смешанные, действительно полиглотные, то, наверное, в этом случае вполне можно писать скрипты на .NET. +1848.22 1849.22 "Анатолий Кулаков" Почему бы и нет? +1849.22 1852.78 "Анатолий Кулаков" Не хуже, чем на любом другом, и тем более на YAML. +1852.78 1861.10 "Анатолий Кулаков" Как я уже говорил, есть не first-класс-саппорт языки, это Go, JavaScript, TypeScript, Java и несколько других, в общем. +1861.10 1872.42 "Анатолий Кулаков" Они тоже поддерживаются, но не так плотно, то есть там нет понимания package-менеджера, нет возможности отладки, но такие программы вы можете запустить и можете ими управлять. +1872.42 1879.94 "Анатолий Кулаков" То есть можете те же самые прокидывать OpenTelemetry, переменное крушение, ConnectionString, управлять сертификатами, все это тоже можно туда засовывать. +1879.94 1886.10 "Анатолий Кулаков" Они просто управляются на основании того факта, что все эти языки можно запихнуть в контейнер. +1886.10 1889.74 "Анатолий Кулаков" Вот и на этом уровне, в принципе, Aspire тоже понимает много чего. +1889.74 1896.66 "Анатолий Кулаков" Естественно, кроме контейнера, там есть специфика управления теми же самыми зависимостями, package-менеджерами. +1896.66 1904.54 "Анатолий Кулаков" В общем, и туда Aspire будет идти, то есть он постепенно будет добавлять более глубокое знание о каждом языке, которые его окружают. +1904.54 1910.14 "Анатолий Кулаков" И постепенно научится, я думаю, запускать все мейнстримные языки и управлять всеми мейнстримными языками. +1910.14 1914.02 "Анатолий Кулаков" Вот туда он пока движется, туда пока идет, и посмотрим, что нас ждет в будущем. +1914.02 1920.50 "Игорь Лабутин" Да, основной, конечно, вопрос, насколько это все будет применимо в не-DotNet окружении, ты действительно прав. +1920.50 1931.10 "Игорь Лабутин" Непонятно, зачем питанистам менять какой-нибудь знакомый ямль или еще что-нибудь, что они и так уже пишут на какой-то совершенно новый дотнетный код. +1931.10 1932.38 "Игорь Лабутин" Ну, посмотрим. +1932.38 1936.26 "Игорь Лабутин" Я пока не очень уверен, что из этого что-то хорошее получится. +1936.26 1941.02 "Игорь Лабутин" Ну, в смысле, хорошее, но недалеко идущее в другие экосистемы, вот так скажем. +1941.02 1945.70 "Анатолий Кулаков" Да, да, тут интересная такая ставка, которую другие пока не выигрывали. +1945.70 1953.34 "Анатолий Кулаков" То есть если мы посмотрим на всякие там Ansible и прочее, они абстрагировались от языка тем, что внедряли ямл. +1953.34 1955.50 "Анатолий Кулаков" Да, ямл, как бы это такая штука не тебе, не мне. +1955.50 1962.14 "Анатолий Кулаков" То есть и питанисты смирились, что это отстой, как бы не на питоне пишут, и джаваскриптовщики, что это отстой не на джаваскрипте пишут. +1962.14 1968.14 "Анатолий Кулаков" И вот, в общем, смирились и на какой-то середине, которая не удовлетворяла всех, но была общим неудовлетворением. +1968.14 1982.94 "Анатолий Кулаков" Здесь как бы строго типизированный язык C#, он в принципе намного лучше, чем ямл со всех сторон, но теперь должны питанисты и джаваскриптовщики согласиться, что конфиги всё-таки пишутся не на их родном языке, а на каком-то третьем. +1982.94 1990.46 "Анатолий Кулаков" Но зато этот третий способен объединить все их платформы, что там ни питон, допустим, ни джаваскрипт не могут пока сделать, не могут этим похвастаться. +1990.46 1997.46 "Анатолий Кулаков" А вот Microsoft намерен так именно и сделать, то есть внедрить глубокую поддержку для всех возможных языков, которые есть. +1997.46 2018.38 "Игорь Лабутин" Ну вот может быть, потому что, не знаю, вот ты говоришь, что допустим, с Pulumi это немножко сравнится, Pulumi как бы он же не только на C# есть, Pulumi есть на TypeScript, C#, Go, Java и на Ямле, ну и тут найти естественно, но это опять же Pulumi только про инфраструктуру, это не про зависимости между вашими приложениями, вот это всё. +2018.38 2027.30 "Игорь Лабутин" То есть Aspire пытается закрыть все ниши одновременно, ну в общем, последим, посмотрим, что будет. +2027.30 2040.58 "Игорь Лабутин" Так, пойдем наверное дальше, дальше у нас большая и интересная статья, ну не знаю, кому интересно, кому может нет, под названием "Reinventing How .NET Builds and Ships" в скобочках "again". +2040.58 2076.78 "Игорь Лабутин" Те, кто слушают нас давно, помнят, что наверное где-то примерно в районе .NET 8 окажется, то есть пару лет назад, я рассказывал наверное половину подкаста какого-то из выпусков про то, как же собирается .NET, там был довольно сложный и нудный алгоритм того, как же там они, какие репозитории, куда там клонируют, не клонируют и так далее, и сейчас вышла вторая статья того же автора, который в самом начале пишет, что типа ну вот я там полтора или около двух лет назад написал эту статью, думал, что ну все, как бы написал, все описал и больше ничего меняться не будет, ну вот здрасте, приехали, пишу снова, такого же примерно объема статью. +2076.78 2080.90 "Анатолий Кулаков" Все упростилось, теперь в одну строчку все делается, .NET Build и готово. +2080.90 2104.50 "Игорь Лабутин" Почти, почти, ну ты почти прав, значит, не совсем тот .NET Build, но там есть для того, чтобы все собиралось именно так и достаточно попроще, есть ряд изменений, которые пришлось сделать, давайте пройдемся вообще, что происходило, как к этому пришли, зачем пришли и вообще к чему пришли. +2104.50 2128.90 "Игорь Лабутин" Значит года полтора-два назад команда .NET имела уже вполне пристойную, так скажем, инфраструктуру сборки, которая позволяла собирать .NET под все те платформы, на которые его нужно собирать, все дела, но проблема в том, что, как обычно, когда вы дописали ваши продукты какой-то, до какого-то состояния, когда у вас есть уже нормальный набор фичей, вам кажется, что все идеально, приходят новые требования, которые с этим фичем почему-то не очень совместимы. +2128.90 2159.78 "Игорь Лабутин" Так и здесь, получилось, что нужно бы собирать три-четыре мажорных версий .NET, то есть это полная сборка условно с нуля, со всеми возможными вариациями SDK, желательно каждый месяц, ну это, понятно, всякие превьюшки, вот это все, в какой-то довольно поздний период этой сборки запихивать какие-то последние, last-minute, ломающие изменения, ну то есть ломающие в том смысле, что потенциально небольшое изменение, которое может сломать, на самом деле, полный SDK, и это надо все тщательно тестировать. +2159.78 2310.14 "Игорь Лабутин" Довольно много сейчас идет работы над фичами, которые затрагивают несколько компонентов одновременно, то есть хочу какой-нибудь там Async 2, который затронет и Runtime, и CLR, и Roslyn, и все что угодно, и это все нужно вместе собирать, как бы мне все это собрать, потому что, напоминаю, .NET это кучка разрозненных репозиторий на GitHub, и команда, которая занималась инфрой, сборкой, собственно, ответы на все такие вопросы, говорилось, что вообще, если вы всего этого хотите, то это будет стоить очень дорого, значит, сейчас, вот на момент, пару лет назад точнее, для того, чтобы вы взяли вот с нуля исходники .NET и собрали в нечто, что уже напоминает почти готовый SDK, который можно прогнать через какие-то валидационные тесты и сказать все, он готов к выпуску, занимает 36 часов, вот, и это как бы, ну, немало, немало, вот, и поэтому, поскольку команда поняла, что в общем-то так нехорошо, и отвечать в таком стиле разработчикам не очень здорово, да, и как бы это обозначает, что это не очень крутая инфра, в каком-то смысле, они поняли, что надо что-то с этим делать, и отсюда родился проект под названием Unified Build, вот, по сути, что произошло, значит, они попытались сделать так, чтобы сборка занимала, вот, ровно как ты говоришь, запустить более-менее единую команду, при этом из одного репозитория, то есть не собирать 100-500 репозиторий, а из одного, вот, но при этом, при этом, нам, мы не хотим .NET запихивать в один монорепозиторий большой и всех заставлять в нем работать, это тоже приведет к проблемам, поэтому родилась некоторая очень интересная конструкция, про которую сейчас мы и расскажем, но начинается все, статья с истории, про то, что, ну, смотрите, как бы у нас .NET, это куча довольно небольших, некоторых больших репозиторий, которые друг с другом связаны, то есть если вы, например, хотите что-то изменить в рантайме, вы изменили это в рантайме, собрали рантайм, у вас появился новый рантайм, но если вы при этом работаете еще и над SP.NET, как бы репозитория SP.NET не в курсе, что у вас появился какой-то новый рантайм, вот, и для того, чтобы вам получить, соответственно, SP.NET с новым рантаймом, вам нужно как-то подсунуть туда зависимость от этого нового собранного рантайма и собрать репозитория SP.NET. +2310.14 2337.22 "Игорь Лабутин" Сложно, при этом отдельные репозитории это хорошо для основной работы, до тех пор, пока ваши фичи, а большинство фич все-таки они локальные внутри репозиториев, вы можете нормально работать над небольшим кусочком репозитория, даже собрать там solution, только кусочек этого репозитория, и иметь быстрый, хороший релизный, ну так сказать, не релизный, а девелоперный цикл, что собрали, проверили, собрали, проверили, собрали, проверили. +2337.22 2448.30 "Игорь Лабутин" Дальше есть еще такой момент, .NET это не только один SDK, точнее это может быть и один SDK, но который распространяется миллионом разных способов, то есть если, например, нам нужно сделать security patch в .NET, то мы должны запатчить .NET, причем если этот код находится и в .NET, и в .NET фреймворке старом, то мы должны запатчить их оба, а дальше мы должны зарелизить этот фикс плюс-минус одновременно во всех местах, где мы релизим .NET, потому что иначе, если мы зарелизим фикс там, не знаю, на каком-нибудь NuGet пакете со словами security fix, и при этом не зарелизим SDK, соответственно, который его тоже фиксит, допустим, то возникнет проблема, что теперь злоумышленники, грубо говоря, знают о том, что есть какая-то уязвимость, которая будет запатчена в NuGet, но не запатчена в основном рантайме, потому что сервис пак еще не вышел к нему, и, соответственно, можно больше шансов, что вы сможете где-то найти этот уязвимый код, а этих каналов распространения их много, Microsoft Update, CDN, линуксовый дистрибутивы, там отдельная история, в контейнер, докер контейнеры, всякие NuGet, вижу студийные моменты, потому что там тоже есть кусочки .NET, которые распространяются со студией, ажурные моменты, в общем, огромное количество мест, куда нужно все это запихнуть, вот, и поскольку нужно во все эти места запихнуть более-менее релиз в одно и то же время, то нам нужно быть довольно предсказуемым с точки зрения времени сборки, потому что таймлайн, то есть у каждого из этих источников немножко разная политика публикации, политика верификации того, что туда запубликовали, и поэтому нужно точно понять расписание, и, конечно, 36 часов полной сборки, ну, как бы сильно оттягивают тот момент, когда все это можно поставить. +2448.30 2470.94 "Игорь Лабутин" Это с одной стороны, с другой стороны, чем больше у вас, чем дольше у вас время сборки, тем больше вероятность, что оно плавающее, то есть если у вас сборка занимает 5 минут, ну, если она займет 7, не так страшно, если у вас сборка занимает 36 часов, но иногда занимает 40, то это уже критично, особенно если речь идет о каких-то очень важных security-патчах, которые нужно выпустить максимально быстро. +2470.94 2509.86 "Игорь Лабутин" Более того, поскольку dotnet — это огромное количество зависимостей, не сказать, что они там циклические, если были циклические, было бы совсем плохо, но получается так, что вы, например, изменили runtime, после этого вы должны изменить те, кто от него зависит, после этого вы должны изменить всех, кто от него зависит, после этого вы должны изменить и пересобрать всех, кто от него зависит, и так делать до тех пор, пока все компоненты, которые в итоге должны быть затронуты вашим изменениям, не убедятся, что у них одна и та же версия runtime используется, и только после этого мы говорим, о, вот из этого можно уже собрать итоговые, значит, там, SDK, грубо говоря, инсталлер SDK. +2509.86 2510.86 "Игорь Лабутин" Вот. +2510.86 2538.98 "Игорь Лабутин" Тем не менее, у подхода, когда у нас много маленьких репозиториев, есть, конечно, хорошее преимущество, что в комьюнити каждого кусочка продукта работает отдельно, они могут делать все это довольно инкрементально, вы можете забирать зависимости инкрементально, если в runtime-репозитории кто-то что-то закоммитил, вы не обязаны тут же это гонять и тестировать, вы можете подождать, пока в runtime-репозитории пройдут все тесты, они там недельку подождут, только потом затянуть новую runtime build. +2538.98 2539.98 "Игорь Лабутин" Вот. +2539.98 2555.22 "Игорь Лабутин" Внутренний цикл разработки, естественно, быстрее, вы можете асинхронно работать над разными фичами, но, более того, если у вас какой-то компонент редко меняется, вы можете, естественно, не пересобирать его каждый раз, а просто затягивать бинарный прошлого билда. +2555.22 2557.30 "Игорь Лабутин" Это полезно, удобно и здорово. +2557.30 2570.34 "Игорь Лабутин" Но все эти преимущества, они же становятся недостатками, если мы говорим, что нам нужно собрать большое количество таких репозиториев в максимально сжатые сроки и предсказуемо. +2570.34 2576.30 "Игорь Лабутин" Вот это становится прям суперсложно, поэтому автор вводит два термина. +2576.30 2590.66 "Игорь Лабутин" Один называется product construction complexity, то есть сложность сборки создания продукта, и product construction overhead, то есть тот overhead, те дополнительные действия, которые требуются для того, чтобы собрать продукт. +2590.66 2596.54 "Игорь Лабутин" Они, вот эти два понятия совмещаются и, в общем-то, все это замедляют и усложняют. +2596.54 2601.10 "Игорь Лабутин" Начнем с product construction complexity, сложность сборки продукта. +2601.10 2615.46 "Игорь Лабутин" По большому счету это количество шагов, которые нужно сделать по определению автора для того, чтобы изменение, которое вы сделали на вашей девелоперской машине было доставлено всем заказчикам, каким бы образом они дотнет не использовали. +2615.46 2618.26 "Игорь Лабутин" Смотри выше, там есть несколько каналов распространения дотнета. +2618.26 2644.90 "Игорь Лабутин" Поскольку в самом начале дотнета, в версии 1.0 условной, мы сейчас не говорим про framework, там было совсем чуть-чуть зависимости, граф зависимости достаточно простой, но как только он начал расти, как только стало появляться большее количество кусочков дотнета, когда туда начали переносить всякие штуки типа WMForms, WPF и так далее, то все больше и больше и больше зависимости стало возникать. +2644.90 2648.42 "Игорь Лабутин" Потребовался тулинг, который этими зависимостями управляет. +2648.42 2652.86 "Игорь Лабутин" Он появился, он называется Maestro и с ним стало вообще все зашибись. +2652.86 2679.10 "Игорь Лабутин" Совершенно легко добавлять новые зависимости, все здорово, но проблема-то в том, что чем легче добавлять зависимость, тем команды будут может быть менее задумываться о том, что давайте добавим еще одну, но это очень сильно влияет на сложность получаемого графа, потому что чем сложнее граф, тем сложнее добиться той самой стабильности всех зависимостей с точки зрения того, что мы закончили пересобирать все. +2679.10 2686.62 "Игорь Лабутин" Команды могут чуть больше ошибаться, не сообразив, кто от кого должен зависеть, например, и так далее. +2686.62 2714.46 "Игорь Лабутин" Количество вариантов сбора, если мы говорим, например, что вот какой-то компонент зависит от WinForms, предположим, и тут же начинается, ага, если он зависит от WinForms, значит его надо собирать еще в варианте Windows Only, а что делать, если он собирается кроссплатформенно, значит в нем надо отключать кусочки Windows зависимой, ну в общем там появляется куча сложностей и непонятно, как со всем этим делать, и нужно кучу билдокружений, чтобы все это разруливать. +2714.46 2715.46 "Игорь Лабутин" Это было про продукт Construction Complexity. +2715.46 2718.74 "Игорь Лабутин" Есть еще продукт Construction Overhead, то есть какой Overhead? +2718.74 2726.30 "Игорь Лабутин" Overhead — это мера временная, то есть если Complexity — это численная мера в количестве шагов, то Overhead — это мера временная. +2726.30 2767.38 "Игорь Лабутин" Можно сделать ее простым подсчетом, то есть мы берем время, которое мы не занимаем, берем общее время сборки, то есть суммируем все времена, например, и считаем, также суммируем все времена всех шагов, где мы активно не занимаемся тем, что мы что-то собираем, то есть те шаги, где у нас не запускается компилятор, где у нас не запускается и так далее, то есть пример — это например какой-нибудь там Git pool, какое-нибудь ожидание, пока мы выкачиваем какую-нибудь зависимость откуда-нибудь, это как бы не является активным временем сборки, когда мы активно собираем именно код. +2767.38 2804.50 "Игорь Лабутин" Что входит в этот Overhead, как я сказал, сюда же, кстати, автор включает всякие ревью, пиаров и так далее, потому что очень часто, когда у нас есть куча репозиториев друг от друга зависящих, обновление зависимости означает, что вам нужно поменять какой-нибудь файлик зависимости, там csproj, какой-нибудь там projectjson, в общем, что угодно зависимости от вашего языка, сделать на это пиар, его кто-то проревьюет, его кто-то запробит, тоже время, которое уходит на то, чтобы все это собрать, даже если делать с полуавтоматом, все равно могут быть какие-то мерш-конфликты и так далее. +2804.50 2822.38 "Игорь Лабутин" Тем не менее, шаги эти необходимы, вы должны выкачать исходники, вы должны выкачать какие-нибудь там секреты, которые нужны для сборки и пуша этих там Nuget пакетов куда-нибудь, это все необходимое зло, но хорошо, чтобы его было поменьше. +2822.38 2823.38 "Игорь Лабутин" Как измерять? +2823.38 2835.26 "Игорь Лабутин" Нужно процент вообще всего времени, берем время всех шагов, берем время всех шагов, которые мы считаем overhead, делим одно на другое, получаем процент, на который желательно было бы ноль, но ноль он никогда не будет. +2835.26 2871.62 "Игорь Лабутин" Но при этом, поскольку процесс сборки графа он не линейен, и для сборки, например, тут на этой там версии какой-нибудь восьмерочки, по-моему, у него в статье граф приведен, использовалось что-то около 40 или 50 виртуальных машинок, чтобы вот это вот в параллель все бодренько собирать, поскольку процесс нелинейный, и общий линейный времень зависит не так, ну как бы нет смысла считать суммарное время всех шагов, поэтому мы находим самый длинный путь с точки зрения зависимости, на этом пути находим все, так сказать, вершины, которые мы классифицировали как overhead, и тогда вот считаем ровно в таком варианте. +2871.62 2913.22 "Игорь Лабутин" Для восьмерки, если сложить все шаги вместе, напоминаю, не там все раз это самое, там огромные сборка, то вот все шаги, сложенные вместе, занимали 2 дня, 2 часа и 18 минут, и из них overhead'ов было 19 часов, если считать вместе с ожиданиями во всяких очередях, ну или 12 часов, если выкинуть время ожидания в очередях, то есть это прям как бы дофига, реальная работа была 1 день 6 часов, то есть где-то треть, 25% это overhead, приблизительно, насколько я вижу, вот, это прям как бы много. +2913.22 2955.62 "Игорь Лабутин" Более того, по мере того, как мы добавляем сложность, то есть все эти зависимости, еще кусочек, тут зависимость, здесь зависимость, проблема заключается в том, что overhead это довольно быстро растет, при этом для разработчиков это не видно, от того, что вы добавили какую-то зависимость в ваш оппозиторий, ваше локальное время сборки скорее всего сильно не изменилось, да, вы выкачаете +1 Nuget пакет, но в рамках локальной сборки обычно это все еще кэшируется, понятное дело, в локальных Nuget-репозиториях, ну в смысле Nuget-кэше, и все, в общем, становится бодро-быстро, вы не видите этого, вот, и видно это только когда вы смотрите на всю систему целиком, ну мало кто это делает в момент, когда принимает решение о том, что давайте затянем новую зависимость, вот. +2955.62 2958.90 "Игорь Лабутин" Отсюда возникает вопрос, надо бы это все как-то уменьшать. +2958.90 2984.66 "Игорь Лабутин" С другой стороны, на тот момент, когда к этому всему пришли, была уже активно штука под названием .NET Source Build, мы про это тоже рассказывали, и идея здесь в том, что Linux-версии .NET, то есть те, которые поставляются в виде официальных пакетов внутри Linux, они собираются не стандартным вот таким путем, а они должны собираться в соответствии со строгими требованиями Linux-репозиторий, в которых они поставляются. +2984.66 2987.66 "Игорь Лабутин" И там немножко другой подход. +2987.66 2999.84 "Игорь Лабутин" Полный .NET Product Build для Linux занимает 50 минут, сравните это с двумя днями полного билда. +2999.84 3039.78 "Игорь Лабутин" Понятное дело, что это не совсем сравнение один к одному, потому что мы собираем только для одной платформы, для одной конкретно Linux, мы не собираем виндовые штуки, мы не собираем ворклоды, мы не пакуем это ни в какие инсталлеры, а только в один формат пакета только для конкретного Linux, в общем-то мы даже не собираем тесты в некоторых случаях, но все это занимает конечно 50 минут, но кажется, что даже если это все включить, вроде как для двух дней многовато, да, все это увеличивать по сути в 1 час и 48 часов, то есть в 50 раз вряд ли оно увеличится. +3039.78 3044.98 "Игорь Лабутин" Source Build соответственно обладает тем самым низким complexity и низким overhead. +3044.98 3053.16 "Игорь Лабутин" А возникает вопрос, если он такой быстрый, а че мы не собираем .NET таким образом? +3053.16 3103.70 "Игорь Лабутин" А еще момент, почему это все так нужно, ну потому что, значит, как я сказал, к Linux предъявляются свои особенные претензии, претензии, свои требования, и в частности, и эти требования они дополняются, как я сказал, условиями, которые упрощают эту сборку, а именно, во-первых, линуксовые версии всегда собирают в каждом компоненте ровно одну реализацию, то есть напомню, у нас есть всякие фиджи-флаги, которые говорят, что типа, а вот если мы там, не знаю, вот такой вот в рантайм вклад в флаг включить, то какая-нибудь там криптография начнет юзаться стандартно виндовая, а иначе встроенная в .NET, вот в линуксовых сборках такого нету, там есть как бы только та одна реализация, которая собралась. +3103.70 3124.78 "Игорь Лабутин" Единая платформа, как я сказал, и самое главное требование — это должен быть билд, происходимый на одной машине, для сборки линуксового репозитория по как бы линуксовой версии .NET по требованиям вот этих Linux обычных дистрибутивов вся сборка должна производиться на одной машине, и это прям челлендж для .NET, потому что обычно требуется 40 или больше машинок. +3124.78 3286.58 "Игорь Лабутин" В обычном билде, который происходит в .NET, если мы не говорим ни о SourceBuild, как я сказал, у нас есть куча разных репозиториев, и в каждом репозитории есть некоторые метаданные, они лежат в виде отдельных файликов, которые описывают, кто от кого зависит, плюс есть некоторое количество Azure DevOps pipeline, в котором это все, естественно, собирается в реальной жизни для паблишинга, и все это, ну, в общем, особо не подходит для того, чтобы собирать в формате SourceBuild на одной единственной машине без Azure DevOps, то есть нам нужен какой-то аркистратор, который все бы это умел делать, но при этом зависел только от исходников, поэтому для SourceBuild было сделано следующее, то есть мы сделали, Microsoft сделал единый репозиторий, все репозитории, которые нужны для сборки, подтянул сабмодулями в плоскую структуру абсолютно, в каждом из этих репозиториев лежит в виде файлика информация, как он должен быть собран, и зависимости этой штуки, ну и, соответственно, есть некоторая аркистрационная логика, которая читает все эти файлики, строит некоторые графы того, в каком порядке каждую папочку собирать, собирает, проверяет, что там не было каких-то совсем косячных проблем, зависимостей, там неправильных цикличных зависимостей, может даже какие-то smog-тесты запустить и так далее, возникают дальше те самые требования к Linux-дистрибутивам, которые усложняют работу сборки дутнета, а именно, нельзя использовать бинарные инпуты, ну просто нельзя, то есть вы не можете зависеть от какой-то дейлильки, дальше, несмотря на то, что мы говорим, что каждый кусочек продукта собирается ровно с одной имплементацией, и мы, например, собираем какой-нибудь дутнет 10, то если мы возьмем, например, пакет под названием Microsoft Code Analysis C#, проблема в том, что в готовой SDK поставляется несколько версий этого компонента, и в зависимости от того, какой target вы будете использовать, будет использоваться разная версия, а по определению собирать мы можем только одну, поэтому для того, чтобы это все сделать, мы либо должны ссылаться на прошлую собранную версию из прошлого SDK, что не очень удобно, либо используется подход под названием Referential Packages, то есть поскольку нам не нужна реализация, нам нужны только ссылки, а реализацию, если что, мы можем взять потом при установке из прошлого релиза, то есть специальный теперь репозиторий называется .NET SourceBuildReferencePackages, в котором содержится только ReferenceOnlyPackages, то есть там чисто контракты написаны, грубо говоря, и именно оно используется для сборки линуксовых версий, чтобы иметь возможность запаковать в итоговый билд разные версии зависимости. +3286.58 3287.58 "Игорь Лабутин" Дальше. +3287.58 3298.42 "Игорь Лабутин" Есть проблемы с тем, что часть зависимостей в дутнете она closed source, например, какие-нибудь интеграционные пакеты с Visual Studio, ну и прочие штуки, которые как бы RSOF не хочет распространять. +3298.42 3304.14 "Игорь Лабутин" Их, они не разрешены, и с ними можно делать, ну, собственно, три вещи. +3304.14 3327.14 "Игорь Лабутин" Либо их open source'ить, такие были кейсы, можно как-то менять поведение .NET компонент, который зависит от их closed source штук, чтобы они не зависели, либо жить немножко с разным поведением, то есть, например, взять и в линукс-версии не поддержать какую-нибудь фичу, которая работает на полноценной .NET, ну, вот это вариант. +3327.14 3344.36 "Игорь Лабутин" Дальше есть legacy зависимости, то есть какое-то старье, которое как бы нужно тянуть с собой, ну тут помогает принцип, что у нас single implementation, в основном legacy зависимости это про то, что у нас есть какие-то старые варианты кода, которые можно включить фич-флагом, на линукс-дистрибутивах такого нет. +3344.36 3354.98 "Игорь Лабутин" Ну и все еще есть некоторые моменты, которые у них называются joins, это когда вам нужно взять несколько собранных артефактов и запихнуть их вместе в один новый. +3354.98 3365.22 "Игорь Лабутин" Такое, например, работает с какими-нибудь project template, потому что только в момент применения project template пользователь ответит, что он хочет, и вы нужный кусок project template ему поставите. +3365.22 3370.98 "Игорь Лабутин" Вот здесь помогает тот факт, что у вас single platform, вам не нужно заморачиваться ничем. +3370.98 3395.94 "Игорь Лабутин" Имея вот эту штуку за плечами, возникает вопрос, ну, собственно, напрямую мы эту штуку к дотнету полностью не применим, потому что со всеми этими ограничениями, что это single platform, single implementation, нельзя тащить custom, эти самые бинарные зависимости, нельзя тащить close source code, вроде как полноценный дотнет, так как мы его знаем, не собрать. +3395.94 3440.46 "Игорь Лабутин" Поэтому родилась идея про то, что мы сделаем новую штуку на основе source build под названием unified build, то есть мы попытаемся применить source build, но к полноценному source build, значит, какие у нас есть цели, у них были цели, когда они это придумывали, цель была такая, что очень хочется, чтобы у нас был единый git commit, который полностью определяет, как собран дотнет, то есть сейчас, для того чтобы понять, вот если мы берем SDK, ну сейчас в десятке это уже сделано, до этого, если мы возьмем какой-нибудь дотнет 8, мы не можем сказать один commit, который соответствует этой версии дотнета, потому что в каждом репозитории был свой commit, вот, а хочется иметь единый git commit для обозначения, грубо говоря, всей дотнет-версии, которую мы сейчас собрали. +3440.46 3468.74 "Игорь Лабутин" При этом мы хотим иметь возможность закоммитить один раз, сделать какой-нибудь один commit в какой-нибудь репозитории, и из этого собрать полностью готовый дотнетный build, то есть, например, мы фиксим уязвимость в дотнет-рантайме, исправляем одну строчку, коммитим это куда-то, не в дотнет-рантайме, возможно, а куда-то, и после этого из этого git commit собирается полностью готовый security patch, по сути говоря, ну то есть SDK, в котором уже содержится security fix. +3468.74 3508.16 "Игорь Лабутин" При этом очень хочется иметь возможность собирать в едином окружении для всех платформ, все те, кто создают вот эти сборки для дотнет-детрибутива для линуксов, для каких-то других мест, хорошо бы, чтобы они это умели делать без необходимости использования Microsoft инфраструктуры, то есть никаких DevOps и вот это вот все, ну и все еще контрибьюторы должны уметь хорошо работать над кусочками продукта и не сильно как бы заморачиваться тем, что им нужно выкачать вообще полный дотнет к себе на машину и его целиком собирать. +3508.16 3518.16 "Игорь Лабутин" Уж понятно, что можно было все запихнуть в monorep, и все собирать, но представьте, как сложно было бы тогда менять какой-нибудь рантайм или ASP.net core. +3518.16 3547.52 "Игорь Лабутин" Для того, чтобы этому всему достичь, во-первых, было понятно, что нельзя собирать дотнет в виде вот этого сложного графа зависимости, и мы должны этот граф зависимости сделать максимально простым, то есть максимально плоским, то есть то, что сделано в source build, запихнуть все репозитории каким-то образом в единый monorep, грубо говоря, в который, возможно, зависимости как-то друг от друга зависят, но нам, по крайней мере, не нужно выкачивать бинарники друг относительно друга и тратить на это кучу оверхеда. +3547.52 3552.84 "Игорь Лабутин" Это все еще есть, поэтому нам нужно уметь их собрать в нужном порядке. +3552.84 3570.20 "Игорь Лабутин" И самое главное, изменения вот в этом мега-монорепозитории должны каким-то образом, волшебным, вероятно, распространяться обратно в маленькие репозитории, из которых оно собрано. +3570.20 3573.44 "Игорь Лабутин" Как это сделать, отдельный интересный вопрос, сейчас мы до этого доберемся. +3573.44 3581.80 "Игорь Лабутин" Собственно, с этими идеями, с этими целями команда пришла, так сказать, к пониманию, что с этим надо работать, и работа началась с 7-го дотнета. +3581.80 3592.56 "Игорь Лабутин" Вот как раз где-то там после восьмерки была та самая статья, про которую я рассказывал в прошлый раз, то есть в семерке были какие-то первые идеи, в восьмерке была основная работа сделана, базовая, чтобы все это заработало. +3592.56 3602.32 "Игорь Лабутин" В девятке попытались сделать идею vertical build, вертикал - это в смысле для одной платформы в одном окружении. +3602.32 3608.44 "Игорь Лабутин" Ну и в десятке, собственно, сейчас это полностью реализовано, это именно в десятке дотнета было собрано именно так. +3608.44 3610.60 "Игорь Лабутин" Как же это сделано в результате? +3610.60 3613.08 "Игорь Лабутин" Во-первых, тот самый монолитик репозиторий. +3613.08 3624.04 "Игорь Лабутин" Теперь в гитхабе есть репозиторий под названием dotnet/dotnet, это репозиторий, который объединяет весь дотнет, то есть если вы его склонируете, вы себе получите на машину весь дотнет. +3624.04 3638.00 "Игорь Лабутин" Там, соответственно, содержится весь оркестратор, который позволяет это все собрать, плюс, на свободном я так понимаю, засунуты все репозитории дотнета, из которых можно собрать целиком себе SDK. +3638.00 3639.84 "Игорь Лабутин" Дальше есть понятие vertical build. +3639.84 3669.12 "Игорь Лабутин" Vertical build - это одна команда, которую собирает кусочек дотнета на одной машине, не используя инпуты из любых других vertical build, то есть если мы берем одну машину, на нее клонируем этот репозиторий, говорим вот одну специфическую вертикаль, так скажем, конфигурацию, и из этого получается некоторый кусочек будущего dotnet SDK. +3669.12 3685.20 "Игорь Лабутин" Как правило, сейчас это все делится по типам рантаймов, там windows x86, windows x64, windows x64, ну и так далее, в общем, в таком духе, и получается таких вертикалей сейчас вот для десятого дотнета где-то 35-40 штук. +3685.20 3719.26 "Игорь Лабутин" Все еще есть пара кейсов, когда нужно, как я говорил, нужно джойнить несколько аутпутов из разных вертикалей в единый, так сказать, бандл, но их всего 2, и поэтому пока команда сказала, ладно, пусть будут, то есть сначала нужно запустить эти 40 вертикалей, их в принципе можно запустить параллельно, если у вас много машин, и если вы собираете для одной платформы, вам достаточно одной вертикали запустить, либо вы можете запустить все вертикали на одной машине последовательно, и потом все это собрать в единые конструкции. +3719.26 3809.24 "Игорь Лабутин" Проблема с cold flow, то есть с тем, как переносить изменения туда-сюда, это отдельная проблема, автор говорит, что мы ждем отдельной статьи на эту тему, может быть, я потом поглубже погружусь, но основная идея следующая, это штука двухсторонняя, то есть вы можете коммитить свой дотнет-рантайм-репозиторий, и ваши изменения будут подтягиваться в момент релиза в монорепу, а также можно делать наоборот, можно коммитить в монорепу, естественно, на гитхабе она, по-моему, редонули, то есть это скорее зеркальная копия монорепы, которая живет в Azure DevOps, и именно там готовятся всякие security патчи, именно поэтому нужен двухсторонний cold flow, потому что security патчи никто не будет готовить в публичном гитхабе, естественно, они готовятся во внутренней инфраструктуре, из внутреннего монорепы собирается дотнет, релизный для security патчей, и только потом эти изменения выкатываются в паблик на гитхаб, так вот, это работает довольно простым способом, то есть каждый локальный репозиторий, то есть dotnet-runtime знает SHA-коммита из монорепы, из которого он в последний раз синхронизировал данные, и наоборот, монорепа знает SHA-коммита dotnet-runtime, ну и всех других репозиторий, естественно, из которых она забирала данные, в результате в каждый момент времени мы, в принципе, можем сказать, посчитать, какие дифы нужно применить в одну и в другую сторону, и их применить, естественно, не факт, что они применятся без конфликтов, особенно если изменения были в обоих местах, то есть пока мы готовили security-патч, кто-то нафигачил в этом же месте в паблик-репозитории что-нибудь. +3809.24 3828.00 "Игорь Лабутин" Естественно, будут мерч-конфликты, но они разрулируются руками, но их нужно разрулить, и таким образом вернуть синхронность этих версий, ну и естественно, есть некоторые тесты валидации, дальше проблема в том, что собрав такой вот vertical build, на нем нужно запустить тесты. +3828.00 3943.28 "Игорь Лабутин" Согласно статье, например, полный запуск всех возможных тестов dotnet runtime-а, репозиторий, только dotnet runtime-а, может занять на одной машинке легко месяц, вот, поэтому понятно, что все тесты никто запускать не будет, выбраны некоторые тесты, которые максимально широко покрывают необходимую функциональность, то есть каждый vertical slice можно протестировать отдельно, и дальше уже потом, когда собран полноценный SDK, его можно прогнать через нормальный обычный релизный test suite, который работает уже на полноценном SDK, вот, в результате, все это сейчас в dotnet уже используется в десятом, то есть десятый dotnet, как я понимаю, собран уже без использования майкрософтовской условной инфраструктуры, в смысле, что каких-то специфических скриптов Azure DevOps, или еще где-то, получили гибкость, то есть билды стали гораздо быстрее, билды стали гораздо более предсказуемыми, с точки зрения времени и overhead в том числе, при этом появилась некоторая дополнительная надежность и инфры, то есть теперь не нужно зависеть от каких-то сложных кусочков, кучи виртуальных машинок каких-то Azure DevOps, скриптов и прочего, все лежит прямо в исходниках, и в будущем команда планирует, что есть еще некоторая необходимость поработать над workflow уже непосредственно на разработке некоторый UX вокруг того самого codeflow, то есть codeflow это пока, я так понимаю, наиболее проблемная часть, требующая довольно много ручной работы, над этим будут работать, ну и попробуют еще поизбавляться от тех самых join points, то есть места, где нужно из разных вертикальных кусочков разных платформ склеить что-то единое, каким-то образом из этого попытаются убрать необходимость этих join, так чтобы это было вообще практически идеальные вертикальные билды и может быть только один финальный степ собирает все в какой-то один пакет. +3943.28 3956.52 "Игорь Лабутин" Вот какая-то такая история про то, как сейчас .NET собирается, как D10.NET можете склонировать себе .NET/.NET и собрать себе полноценные SDK под все платформы. +3956.52 3974.08 "Анатолий Кулаков" Ну монументальненько, монументальненько, я зашел действительно на .NET/.NET и там прямо написано, что вот склонируйте репозитории, запустите билд.sh и все у вас хорошо, весь у вас .NET будет здесь, поэтому прям как надо, как положено. +3974.08 3981.44 "Анатолий Кулаков" Единственное, что непонятно, сколько тут времени заберет, если вы на домашнем ноутбуке это будете делать, может даже кто-нибудь попробует, расскажет. +3981.44 4012.08 "Игорь Лабутин" Да, интересно-интересно, но при этом действительно наверное помогает как-то убеждаться, что то, что собирается в Linux-репозиториях, например, в Linux-версии .NET совпадает с тем, что собирается с самим Microsoft, и это возможно чуть больше, так скажем, даст тоже, не знаю, открытости что ли к .NET, потому что .NET, конечно, он open-source, но вы пробовали когда-нибудь собрать .NET SDK, говорили некоторые. +4012.08 4015.56 "Игорь Лабутин" Он же только Microsoft умеет его собирать, кто знает, что там внутри .NET SDK. +4015.56 4019.16 "Игорь Лабутин" А нет, вот теперь можете посмотреть, что сами себе собрать. +4019.16 4023.48 "Анатолий Кулаков" Ну да, и наконец-то в .NET появится куча разных сборок. +4023.48 4033.32 "Анатолий Кулаков" В .JAB есть, тот собирает такую Java, другую Java, OpenSDK, каждая вторая компания собирает, вот и мы сейчас скоро начнем свой .NET собирать. +4033.32 4034.32 "Анатолий Кулаков" С патчами. +4034.32 4036.00 "Игорь Лабутин" Чтобы нет, пропатченный и все такое. +4036.00 4037.00 "Игорь Лабутин" Да. +4037.00 4039.36 "Игорь Лабутин" Ну посмотрим, может и получится, если будет зачем. +4039.36 4044.00 "Игорь Лабутин" Ну что, давай, дальше у нас есть еще что? +4044.00 4059.84 "Анатолий Кулаков" Да, есть у нас статья про T-Unit, такой тестовый фреймворк, который мы пару раз упоминали вскользь, но все время как-то мы на нем не останавливались, подробнее, и было непонятно, зачем вообще эта штука появилась, какие у нее преимущества и кому она нужна в конце-то концов. +4059.84 4065.80 "Анатолий Кулаков" Вот, хотелось бы остановиться и еще раз подробнее про нее уже теперь глубоко поговорить. +4065.80 4076.84 "Анатолий Кулаков" Тем более, что есть замечательный повод, ибо сам Том Лонхорст, это автор T-Unit, написал статейку, а зачем же я все-таки все это сделал. +4076.84 4081.80 "Анатолий Кулаков" Вот, статейка хорошая, интересная получилась и довольно привлекательная. +4081.80 4092.24 "Анатолий Кулаков" Поэтому, может быть, вместе с новым .NET-ом у вас будут какие-то поползновения не только поставить новый фреймворк, но и попробовать новый какой-нибудь тестовый фреймворк. +4092.24 4095.64 "Анатолий Кулаков" Вот, и T-Unit вполне может стать именно таким. +4095.64 4109.80 "Анатолий Кулаков" В отличие от каких-то других таких каких-то артистичных или экстравагантных раньше подходов, это все-таки претендент на то, чтобы заменить обычные наши мейнстримовые X-Unit и N-Unit. +4109.80 4113.52 "Анатолий Кулаков" Давайте же посмотрим, чем он так хорош. +4113.52 4134.12 "Анатолий Кулаков" Автор начинает свои мемуары с того, что говорит, что ровно 2 года назад он начал писать T-Unit, и это был такой исследовательский проект, который был призван рассказать автору, как работает вообще, как устроена тестовая система в Майкрософте, в .NET, что там есть под капотом, как проблемы решаются, и в общем, такая научно-исследовательская работа была. +4134.12 4139.24 "Анатолий Кулаков" И вот сейчас, спустя 2 года, вышла как раз версия 1.0. +4139.24 4149.52 "Анатолий Кулаков" То есть фреймворк готов, API устаканился, в продакшене он уже много где испробован, и можно рекомендовать смело всем в округе тоже его пробовать. +4149.52 4158.40 "Анатолий Кулаков" Как я уже сказал, если вы не понимаете, что такое тестовый фреймворк, он очень сильно похож на X-Unit, N-Unit, MS-Test. +4158.40 4162.28 "Анатолий Кулаков" Более того, он не похож, он является им прямым конкурентом, он хочет их заместить. +4162.28 4172.60 "Анатолий Кулаков" А с этими монстрами, я думаю, каждый из вас обязан был сталкиваться, я уже не помню, очень много лет уже не встает такой вопрос, писать тесты или не писать тесты. +4172.60 4174.60 "Анатолий Кулаков" Раньше, кстати, мы это обсуждали. +4174.60 4177.24 "Анатолий Кулаков" Вот сейчас всем очевидно, что тесты и писать надо. +4177.24 4187.68 "Анатолий Кулаков" Но, опять же, если мы задаемся вопросом, что это конкурент таких вещей, как X-Unit, N-Unit и MS-Test, то вопрос, а зачем? +4187.68 4193.00 "Анатолий Кулаков" Кажется, что это не самые сложные фреймворки на свете, и, в принципе, каждый из них свою нишу занял. +4193.00 4203.72 "Анатолий Кулаков" Рынок уже давно поделен, разработчики уже давно выучили синтаксис, проекты уже давно напилены, написаны, и непонятно, зачем здесь нужен какой-то новый фреймворк, то есть, какую проблему он решает. +4203.72 4205.96 "Анатолий Кулаков" Все, в принципе, и так было хорошо. +4205.96 4210.16 "Анатолий Кулаков" Вот автор пытается все-таки рассказать, что проблемы были. +4210.16 4219.52 "Анатолий Кулаков" В частности, все эти, все три вот этих основных наших фреймворка, они обладают огромной кучей легоси. +4219.52 4244.92 "Анатолий Кулаков" Ну, во-первых, они писались под VSTest, это такая прокладка между тестами и между кодом, которая позволяла, такой адаптер, который позволял Дотнету более-менее абстрагироваться от фреймворка и дать возможность разрабатывать вот такие независимые фреймворки, при этом держать одну тестовую инфраструктуру, запускать ее, допустим, из Дотнет-рана, то есть из Дотнет-тестов, прямее сказать, и из всяких CI/CD-пайплайнов. +4244.92 4248.60 "Анатолий Кулаков" В общем, такая платформа для тестирования была. +4248.60 4268.64 "Анатолий Кулаков" Она была старая, громоздкая, неинтересная, и вот недавно Микрософт выпустил Microsoft Testing Platform, мы про нее тоже в подкасте и рассказывали, это более новая замена, она расширяемая, она быстрая, она красивая, в общем, и новые фреймворки, вот эти тесты уже на нее все почти и переползли. +4268.64 4283.04 "Анатолий Кулаков" А T-Unit, он писался сразу на этой новой тестовой платформе, и поэтому у него нет кучи того легоси, кучи страшного API, кучи тормознутых абстракций, которые вынуждены старые фреймворки соблюдать для обратной совместимости. +4283.04 4285.08 "Анатолий Кулаков" Но это мелочи. +4285.08 4293.02 "Анатолий Кулаков" Наверное, самая главная фича, на которую эта штука выехала, я имею в виду T-Unit, это то, что он использует nativeout. +4293.02 4332.84 "Анатолий Кулаков" То есть в отличие от старых фреймворков, которые используют reflection для того, чтобы найти те тесты, которые нужно запустить, и те параметры, с которыми их нужно запустить, T-Unit использует source-генераторы, то есть в compile-time анализируется код, смотрится, какие есть методы, как их нужно запускать, с какими параметрами, и генерируется непосредственно запускальщик этих тестов, что позволяет избавиться полностью от reflection, а это значит получить нативную поддержку nativeout, так как у нас нет reflection, все это можно скомпилировать с чистой машиной код. +4332.84 4340.20 "Анатолий Кулаков" И вот этим не может похвастаться ни один существующий фреймворк из наших мейнстримовых, то есть пока никто такого не умеет. +4340.20 4353.12 "Анатолий Кулаков" Не факт, что им это надо, опять же, потому что вспомним преимущества nativeout, это быстрый запуск, это оптимизация под конкретную платформу и так далее, но для тестов обычно ничего этого не надо. +4353.12 4363.76 "Анатолий Кулаков" Если, конечно же, вы не пишете приложение, которое работает в nativeout, и которое хочется прямо тестировать сразу в nativeout, чтобы вот прям та среда была, в которой оно будет работать. +4363.76 4368.28 "Анатолий Кулаков" Ну, таких кейсов тоже довольно мало, то есть почему нельзя его тестировать с помощью reflection, непонятно. +4368.28 4373.96 "Анатолий Кулаков" В общем, непонятно пока, насколько это маркетинговый буллшит или все-таки действительно полезная на практике фишка. +4373.96 4382.72 "Анатолий Кулаков" Но пока это самый знаменательный флаг, который отличает T-Unit от всех других фреймворков, никто пока такого другого не имеет. +4382.72 4393.76 "Анатолий Кулаков" Ну и более того, у T-Unit есть отдельный слой для совместимости, callback compatibility, который тоже с помощью reflection может делать то же самое, что делается с помощью все-таки генераторов. +4393.76 4397.12 "Анатолий Кулаков" Наверняка для каких-то вещей он тоже нужен. +4397.12 4399.12 "Анатолий Кулаков" Теперь пойдем по более специфичным вещам. +4399.12 4410.56 "Анатолий Кулаков" В общем, есть какие-то мелкие недоработки в существующих фреймворках, которые автору мешали или ему казалось, что это вот такое не очень интуитивно, не очень понятно, не очень удобные штуки. +4410.56 4415.04 "Анатолий Кулаков" Например, постоянное расшаривание состояний. +4415.04 4423.84 "Анатолий Кулаков" Если взять тот же самый N-Unit, то у него каждый класс расшаривает свое состояние между всеми тестами. +4423.84 4432.00 "Анатолий Кулаков" Это значит, что очень часто возникает протекание изоляции и очень часто возникают баги следующего содержания. +4432.00 4445.08 "Анатолий Кулаков" Например, когда один тест меняет поле внутри этого класса, а потом запускается другой тест, этот другой тест может рандомно упасть, потому что этот тест начинает читать то поле, которое поменял первый тест. +4445.08 4449.88 "Анатолий Кулаков" И в зависимости от того, какой из них по порядку запустился, тест может или пройти, или упасть. +4449.88 4456.80 "Анатолий Кулаков" В общем, это такие, получается, у нас флаки-тесты и с этим тяжело жить. +4456.80 4468.92 "Анатолий Кулаков" Особенно если разработчики новые, не понимают вот этой всей специфики, а по сути это магия для разработчиков, потому что как там запускаются эти классы, насколько они часто создаются, они, в принципе, не знают в общем случае. +4468.92 4472.24 "Анатолий Кулаков" И они часто пишут такие вот невонятные тесты, которые рандомно падают. +4472.24 4473.24 "Анатолий Кулаков" Это плохо. +4473.24 4489.68 "Анатолий Кулаков" И еще хуже это, когда мы пытаемся эти тесты запараллелить, как только мы пытаемся внедрить параллелизацию, то вот такое расшаренное состояние у NUnit сразу выстреливает всем в ноги и превращается в наш ночной кошмар. +4489.68 4502.12 "Анатолий Кулаков" В XUnity с этим получше, потому что там на каждый тест создается свой собственный класс, свой собственный instance класс, а там уже никакого грязного состояния вам перечитать невозможно. +4502.12 4504.44 "Анатолий Кулаков" Но там другая проблема. +4504.44 4510.72 "Анатолий Кулаков" Там проблема заключается в том, что тесты в одном классе выполняются последовательно, по умолчанию. +4510.72 4520.96 "Анатолий Кулаков" В общем, никакой причины для этого особой нет, опять же, потому что там каждый тест независим, под каждый тест создается отдельный класс, но изначально они выполняются последовательно. +4520.96 4530.68 "Анатолий Кулаков" И это плохо, потому что современные компьютеры, у них много ядер, у них много потоков, и они хотят выполнять тесты быстро, поэтому по умолчанию это поведение не самое хорошее. +4530.68 4553.48 "Анатолий Кулаков" Это поведение можно исправить, используя Collection Ficture, но Collection Ficture это другая такая магическая штука, на которую каждый разработчик, когда первый раз смотрел, он как минимум перекрещивался, потому что абсолютно непонятно, как она работает, что она делает, и только если вы там сядете и с документацией покумекаете полчаса, только тогда до вас дойдет, и то вам нужно это запоминать и пытаться не забыть в дальнейшем, в будущем. +4553.48 4556.36 "Анатолий Кулаков" В XUnity все совсем по-другому. +4556.36 4564.96 "Анатолий Кулаков" В XUnity каждый тест, естественно, независим от класса, как в XUnity, и при этом по умолчанию оно все параллелится. +4564.96 4569.04 "Анатолий Кулаков" И параллелится так хорошо, насколько ваш стэртпул только может себе этого позволить. +4569.04 4573.68 "Анатолий Кулаков" То есть каждый метод независимо по дефолту параллелится. +4573.68 4574.68 "Анатолий Кулаков" И это хорошо. +4574.68 4582.84 "Анатолий Кулаков" Как раз по умолчанию должно все работать параллельно, а вот если вам нужны какие-то особые условия, особые сценарии, вот их нужно там переключать. +4582.84 4594.72 "Анатолий Кулаков" Например, есть атрибут ParallelLimit, с помощью которого можно выставить лимит на параллельность или наоборот NonInParallel, где можно выставить ее, чтобы вот этот определенный класс не параллелился вовсе. +4594.72 4600.88 "Анатолий Кулаков" В общем, когда вам нужно ограничить параллельность, вот тогда ее нужно ограничивать, а по умолчанию она должна максимально параллелиться. +4600.88 4603.76 "Анатолий Кулаков" Вот это XUnity делает. +4603.76 4608.12 "Анатолий Кулаков" Следующая проблема – это проблема с интеграционными тестами. +4608.12 4618.56 "Анатолий Кулаков" Все мы знаем, что юнит-тесты должны быть обязательно изолированы, выполняться в изоляции, и чистенько и красивенько каждый шаг должен друг от друга не зависеть. +4618.56 4620.72 "Анатолий Кулаков" Каждый тест должен друг от друга не зависеть. +4620.72 4626.56 "Анатолий Кулаков" Но жизнь такова, что в мире существуют интеграционные тесты. +4626.56 4629.16 "Анатолий Кулаков" Интеграционные тесты играют очень большую роль, то есть просто так их выкинуть нельзя. +4629.16 4640.76 "Анатолий Кулаков" Но у нас нет какого-то особого фреймворка для интеграционных тестов, поэтому на практике, естественно, все используют обычные тестовые фреймворки XUnity, NUnit для интеграционных тестов в том числе. +4640.76 4644.84 "Анатолий Кулаков" Но интеграционные тесты заключаются в том, что они немножко сложнее. +4644.84 4647.00 "Анатолий Кулаков" Там вам нужно выполнять целый какой-то сценарий. +4647.00 4651.16 "Анатолий Кулаков" Например, вам нужно создать пользователя, обновить пользователя и удалить пользователя. +4651.16 4657.76 "Анатолий Кулаков" И на каждом из этих шагов у вас, естественно, есть пачка сердцов, которая проверяет, насколько хорошо он создался, обновился, удалился. +4657.76 4661.44 "Анатолий Кулаков" Есть несколько способов написать интеграционный тест. +4661.44 4666.24 "Анатолий Кулаков" Самый распространенный – это взять в один большой метод и собрать вот эти три шага. +4666.24 4669.32 "Анатолий Кулаков" Ну, в общем случае, сколько угодно, но в нашем примере три шага. +4669.32 4681.84 "Анатолий Кулаков" И это плохо тем, что у вас получается огромный метод, он никак логически не разделен, он, конечно, может из-под себя вызывать какие-то подметоды, но это уже плохо отображается во всяком тест-менеджере. +4681.84 4689.08 "Анатолий Кулаков" То есть в тест-менеджере уже эти подметоды не видны, не делятся, они показываются как единый сценарий и не очень красиво, не очень хорошо. +4689.08 4698.44 "Анатолий Кулаков" Можно на собирать какую-то свою коллекцион фикшу, которая будет вызывать в правильном порядке, выстраивать между ними зависимостями, смотреть, что кто-то из них упал. +4698.44 4701.28 "Анатолий Кулаков" Но все это настолько сложно, что этим даже никто не загоняется. +4701.28 4705.20 "Анатолий Кулаков" В общем, в иньюнити такую штуку сделать практически невозможно. +4705.20 4710.00 "Анатолий Кулаков" В XUnity это можно сделать, но очень сложно с помощью вот этих магических интерфейсовых атрибутов. +4710.00 4716.92 "Анатолий Кулаков" И у нас получается, что интеграционные тесты так стоят особняком и являются таким каким-то костылем. +4716.92 4720.48 "Анатолий Кулаков" TheUnit подошел к этому делу научно. +4720.48 4730.20 "Анатолий Кулаков" Он решил, что интеграционные тесты у него будут поддержаны как бы из коробки, нативно, и добился он это следующим простым атрибутиком. +4730.20 4737.68 "Анатолий Кулаков" Появился атрибут, который называется DependsOn, и там указывается имя теста, от которого зависит этот тест. +4737.68 4740.84 "Анатолий Кулаков" То есть имя метода, от которого зависит вот этот тестовый метод. +4740.84 4750.68 "Анатолий Кулаков" Это значит, что в нашем сценарии шаги создать юзер, апдейт юзер и делит юзер, у них просто выставляется, пишутся просто три метода, и между ними выставляется зависимость. +4750.68 4753.48 "Анатолий Кулаков" Сначала мы делаем первый, потом второй, потом третий. +4753.48 4760.40 "Анатолий Кулаков" И TheUnit понимает, что это зависимость, и к чему это приводит. +4760.40 4777.00 "Анатолий Кулаков" Приводит это к тому, что если на каком-то промежуточном этапе этот тест упал, допустим, мы упали на апдейт юзере, при этом крит юзер прошел, апдейт юзер упал, делит юзер уже метод вызываться не будет, он автоматически скипнется и пометится как проваленный. +4777.00 4782.92 "Анатолий Кулаков" Вот таким образом у нас получается, что если хоть один элемент в цепочке там сваливается, вся цепочка считается провальной. +4782.92 4786.20 "Анатолий Кулаков" Таким образом мы видим, что интеграционный тест все-таки завалился. +4786.20 4795.32 "Анатолий Кулаков" А также мы видим, на каком шаге он завалился, у каждого шага там есть диагностика, то есть мы понимаем, что первый шаг прошел с такими-то результатами, во втором шаге вот здесь он завалился. +4795.32 4798.80 "Анатолий Кулаков" То есть получается все довольно-таки удобненько и красивенько. +4798.80 4807.64 "Анатолий Кулаков" Вот такой-то dependency как в First Class Citizen хорошо умеет в провайдерах отображаться. +4807.64 4812.36 "Анатолий Кулаков" В принципе действительно полезная вещь, вот такой штуки на практике часто не хватало. +4812.36 4818.40 "Анатолий Кулаков" Так, а вот другая вещь, с моей точки зрения довольно сомнительная. +4818.40 4827.00 "Анатолий Кулаков" Кто-то утверждает, что в XUnity есть такие полезные интерфейсы, как IDisposable и AsyncLifetime. +4827.00 4837.36 "Анатолий Кулаков" Я напомню, что это интерфейсы, которые предоставляют вам методы, благодаря которым вы можете запустить код в начале вашего теста и в конце вашего теста. +4837.36 4839.40 "Анатолий Кулаков" То есть такое приготовление и окончание. +4839.40 4847.92 "Анатолий Кулаков" И плюс в том, что они могут быть асинхронными, то есть вы можете асинхронно какой-то initialize сделать и асинхронный dispose тоже вызвать. +4847.92 4851.40 "Анатолий Кулаков" Вот, и это удобно, хорошо, понятно и наглядно. +4851.40 4860.40 "Анатолий Кулаков" И автор говорит, что нет, не всегда это удобно, например, когда вы делаете наследование у ваших тестов, то там начинаются проблемы в иерархии. +4860.40 4870.12 "Анатолий Кулаков" То есть непонятно, как наследник должен вызвать базовый класс, который там в базовом классе dispose, или в базовом классе initialize, в общем какие-то такие мутные у него проблемы. +4870.12 4874.88 "Анатолий Кулаков" Вот, и в XUnity автор предлагает решать это следующим образом. +4874.88 4876.88 "Анатолий Кулаков" Просто-напросто навешивать атрибуты. +4876.88 4878.84 "Анатолий Кулаков" Как это делается, например, в XUnity. +4878.84 4884.44 "Анатолий Кулаков" У вас есть какой-то метод, и этот метод вы помечаете атрибутом. +4884.44 4889.24 "Анатолий Кулаков" В нашем случае атрибут называется before имя метода или after имя метода. +4889.24 4893.12 "Анатолий Кулаков" Также можно написать before имя класса и after имя класса. +4893.12 4897.00 "Анатолий Кулаков" То есть перед методом или после класса оно будет выполняться. +4897.00 4907.24 "Анатолий Кулаков" Таким образом, от этих атрибутов можно навесить сколько угодно в иерархии, и, соответственно, каждый наследник получит какой-то свой квант времени, где он сможет или пронициализировать или очистить данные. +4907.24 4918.20 "Анатолий Кулаков" Вот, не знаю, мне как раз избавление от вот этих дурацких атрибутов before_test и after_test как раз было одной из фишек, почему мне понравился XUnity, почему я ушел из nUnity. +4918.20 4926.20 "Анатолий Кулаков" Потому что как раз интерфейсы и конструкторы класса были более интуитивные, более нативные, более понятные для C# разработчика. +4926.20 4932.12 "Анатолий Кулаков" То есть я, как C# разработчик, я понимаю, что метод dispose вызывается в конце, а конструктор вызывается в начале. +4932.12 4934.80 "Анатолий Кулаков" И это хорошо, это интуитивно понятно. +4934.80 4945.24 "Анатолий Кулаков" А вот не забыть навесить какой-то специальный атрибут на какой-то специальный метод, вот это совсем не интуитивно понятно, это уже какие-то знания, которые необходимо знать. +4945.24 4949.36 "Анатолий Кулаков" Вот, поэтому этот пункт как-то мне не очень понравился. +4949.36 4953.32 "Анатолий Кулаков" Ну, ладно, допустим, допустим, какие-то проблемы были. +4953.32 4954.32 "Анатолий Кулаков" Погнали дальше. +4954.32 4959.80 "Анатолий Кулаков" Дальше у TUnity есть очень развесистая, очень большая система хуков так называемых. +4959.80 4963.88 "Анатолий Кулаков" То есть можно перекрыть практически любой момент жизненного цикла. +4963.88 4980.48 "Анатолий Кулаков" Ну, например, мы можем перекрыть цикл discovery, то есть, например, уловить события перед началом исследования, то есть сканированием сборки на тесты и после того, как все тесты сканированы, то есть собран полный список этих тестов. +4980.48 4987.72 "Анатолий Кулаков" У нас есть перед-после сессии, это глобальная настройка всего процесса. +4987.72 4998.60 "Анатолий Кулаков" У нас есть перед-после сборкой, то есть когда сборка загружается, когда первый тест сборки начал выполняться и после того, как последний закончил выполняться, то есть на уровне сборки. +4998.60 5003.04 "Анатолий Кулаков" У нас есть перед-после класса и перед-после теста. +5003.04 5019.80 "Анатолий Кулаков" То есть вот такое событие, которое вы можете перехватить по сути на каждом этапе от сборки всех тестов до запуска классов, до запуска сборок, до запуска тестов и каким-то образом навести туда своих обработчиков, своих модификаторов и своих конфигураторов. +5019.80 5024.80 "Анатолий Кулаков" В общем, тоже довольно удобная и полезная штука. +5024.80 5035.40 "Анатолий Кулаков" Дальше такой пример еще приводится, что в тот момент, когда автор тестировал всякие UI-фреймворки, ему очень часто необходимо было перехватить событие, которое называлось «тест провален». +5035.40 5057.16 "Анатолий Кулаков" Ну, например, если проводился тест на какой-то UI, то очень полезно сделать скриншот, допустим, этой UI, или, допустим, сохранить логи, захватить стэктрейс, сохранить логи, ну, в общем, сделать какую-то вспомогательную информацию после того, как тест упал, для того, чтобы потом впоследствии более удобно продебажить, в чем же, собственно, была проблема. +5057.16 5091.08 "Анатолий Кулаков" Опять же, он говорит, что в NUnity это сделать нереально, в XUnity это можно сделать, но очень сложно, перекрывая различные платформенные интерфейсы, а в TUnity он специально это вывел на уровень хуков, поэтому если у вас вдруг произошла ошибка, то у вас есть очень простой событий, на который вы можете подписаться и в этом событии проинспектировать все, что произошло, то есть где тест упал, почему упал, как упал, и сделать необходимый скриншот и сохранить необходимые логи, тоже как бы удобно и просто. +5091.08 5107.04 "Анатолий Кулаков" Еще не очень автору нравились атрибуты, которые позволяют внедрить в аргументы вашего теста какие-то данные из другого места. +5107.04 5116.80 "Анатолий Кулаков" Вот мы там часто подставляли данные, допустим, из таблицы, из какого-нибудь CSV файла, из XML документа или просто константы, которые нужно перебрать в качестве параметров теста. +5116.80 5118.64 "Анатолий Кулаков" Вот это было сделано, по его мнению, не очень удобно. +5118.64 5131.20 "Анатолий Кулаков" Он предлагает сделать обычный класс, который называется класс DataSource.t, и наследоваться от него, и в этом наследнике переопределять абсолютно любые сорцы, которые вам могут быть необходимы. +5131.20 5137.24 "Анатолий Кулаков" То есть вы полностью контролируете, откуда придут данные буквально с помощью обычного наследования. +5137.24 5146.68 "Анатолий Кулаков" Также можно с помощью атрибутов контролировать то, каким образом ваш тест будет выполняться. +5146.68 5155.12 "Анатолий Кулаков" Допустим, если вы хотите сделать какой-то один конкретный тест, чтобы он выполнялся всегда на выделенном потоке, чтобы ему отдался весь поток. +5155.12 5159.60 "Анатолий Кулаков" Это очень легко можно сделать, используя атрибут, который называется TestExecutor. +5159.60 5166.28 "Анатолий Кулаков" И в этот TestExecutor передать тот самый класс, который отвечает за то, как правильно запускать ваш тест. +5166.28 5170.76 "Анатолий Кулаков" И вы полностью можете определить, как запускается один-единственный ваш тест. +5170.76 5183.20 "Анатолий Кулаков" Естественно, вы можете это навесить не только на один тест, но и на все, что угодно, но в общем случае довольно мощная штука, то есть вы можете окружить ваш тест, допустим, какой-то транзакцией или еще что-то с ним сделать. +5183.20 5185.64 "Анатолий Кулаков" Следующим абзацем идет когнитивная нагрузка. +5185.64 5196.52 "Анатолий Кулаков" Автор утверждает, что все-таки вот эти современные, даже не современные, а старые прижитые тестовые фреймворки, у них очень большая когнитивная нагрузка, когда их читаешь. +5196.52 5202.40 "Анатолий Кулаков" Ну, например, берем XUnit, у него есть два атрибута – факт и теория. +5202.40 5208.24 "Анатолий Кулаков" Факт применяется, когда это простой тест, а теория применяется, когда это тест с параметрами. +5208.24 5214.24 "Анатолий Кулаков" И у тех разработчиков, которые первый раз на это смотрят, возникает закономерный вопрос – зачем у них различать? +5214.24 5215.24 "Анатолий Кулаков" Какая у них разница? +5215.24 5217.32 "Анатолий Кулаков" Тест, он и есть тест, он должен запускаться. +5217.32 5223.32 "Анатолий Кулаков" А берет он параметры или не берет, зависит от того, есть у него параметры или нет, а не от атрибута, который над ним навешан. +5223.32 5224.88 "Анатолий Кулаков" В общем, это довольно странное решение. +5224.88 5225.88 "Анатолий Кулаков" Какая разница? +5225.88 5227.72 "Анатолий Кулаков" И то, и то тест. +5227.72 5232.84 "Анатолий Кулаков" С NUnit и MSTest там тоже все намного не лучше. +5232.84 5237.04 "Анатолий Кулаков" Например, есть атрибут, который называется one-time setup. +5237.04 5243.60 "Анатолий Кулаков" Не очень понятно, этот setup вызывается на класс или это setup называется на namespace или на test. +5243.60 5249.08 "Анатолий Кулаков" И есть такие атрибуты, как, например, класс-инишалайзер или тест-инишалайзер. +5249.08 5252.64 "Анатолий Кулаков" В общем, чем они отличаются от этого one-time setup? +5252.64 5257.12 "Анатолий Кулаков" В общем, тоже такие неинтуитивные вещи, которые необходимо знать. +5257.12 5259.48 "Анатолий Кулаков" Там нужно сесть, разобраться, запомнить и не забывать. +5259.48 5260.48 "Анатолий Кулаков" Это не очень хорошо. +5260.48 5264.82 "Анатолий Кулаков" Автор NUnit говорит, что должно быть все больше, более-менее интуитивно. +5264.82 5272.00 "Анатолий Кулаков" И вот из интуитивного он говорит, что у меня есть один-единственный атрибут, который называется тест. +5272.00 5278.64 "Анатолий Кулаков" Никакой разницы между фактом и теорией здесь нет, просто тест, атрибут над методом и все, и это самая простая вещь. +5278.64 5283.60 "Анатолий Кулаков" Ну, не знаю, мне кажется, если бы он пошел дальше, то самая простая вещь – это был бы просто публичный метод. +5283.60 5288.28 "Анатолий Кулаков" Вот если есть у вас, у тестового класса, как бы публичный метод, то, наверное, можно считать его тестом. +5288.28 5295.68 "Анатолий Кулаков" Там, конечно, очень много рождается каких-нибудь конфликтов, но в общем случае можно было бы, наверное, что-то и более дерзкое придумать. +5295.68 5297.48 "Анатолий Кулаков" Ладно, погнали дальше. +5297.48 5303.40 "Анатолий Кулаков" Опять же, к гибкости, NUnit – он такой очень-очень гибкий. +5303.40 5317.64 "Анатолий Кулаков" Например, если вам нужно запустить какой-то код перед тем, как выполнится первый метод, первый тест из этого класса, вы просто пишите атрибут beforeClass, над этим методом, и метод будет выполнен. +5317.64 5333.40 "Анатолий Кулаков" Если вам нужно выполнить какой-то код, который выполнится после последнего теста во всей этой сборке, вы просто навешиваете атрибут, который называется autoAssembly, и все, и после последнего теста этой сборки будет выполнен вот этот ваш метод. +5333.40 5338.12 "Анатолий Кулаков" То есть все очень читабельно, все очень понятно. +5338.12 5350.96 "Анатолий Кулаков" BeforeClass, beforeTest, autoAssembly, autoNamespace, в общем, все вот эти атрибуты – они довольно интуитивные, у них нет какой-то многочитабельности, как во всех предыдущих фреймворках. +5350.96 5353.88 "Анатолий Кулаков" Типо-безопасный assertion. +5353.88 5362.28 "Анатолий Кулаков" Автор говорит, что ему нравится NUnit'овский FluentAssertion, но у этого FluentAssertion очень большие проблемы с безопасностью типов. +5362.28 5371.00 "Анатолий Кулаков" Например, ко всяким числовым константам можно применить строковые constraints, и это не очень хорошо. +5371.00 5375.80 "Анатолий Кулаков" То есть эти constraints не проверяются на уровне компилятора. +5375.80 5385.44 "Анатолий Кулаков" У NUnit'а есть точно такой же Fluent интерфейс, но при этом он полностью совместим с компилятором, и все assertions, которые вы там применяете, они строго типизированы. +5385.44 5392.20 "Анатолий Кулаков" То есть только то, что можно делать со строками, можно ассертировать на строке, а с int'ами можно ассертировать только на int'ах. +5392.20 5396.24 "Анатолий Кулаков" Еще к системе расширения. +5396.24 5401.04 "Анатолий Кулаков" Есть такая концепция, которая у него называется WriteLines Apply Everywhere. +5401.04 5409.08 "Анатолий Кулаков" То есть вы можете написать специальный атрибут, который можете применить абсолютно ко всему. +5409.08 5412.68 "Анатолий Кулаков" То есть такая очень гибкая система наследования. +5412.68 5416.20 "Анатолий Кулаков" Ну, например, вы можете написать атрибут, который называется retry3. +5416.20 5420.08 "Анатолий Кулаков" То есть повторить этот метод три раза и навесить его на метод. +5420.08 5423.92 "Анатолий Кулаков" Да, тогда тестовый фрейворк будет этот метод повторять три раза. +5423.92 5434.08 "Анатолий Кулаков" Или же вы можете этот метод навесить, не метод, можете этот атрибут навесить на сборку, на assembly, и при этом это будет тот же самый атрибут, там, retry3. +5434.08 5441.88 "Анатолий Кулаков" При этом, когда вы этот retry3 навешиваете на сборку, это значит, что все тесты внутри этой сборки будут повторяться три раза. +5441.88 5444.40 "Анатолий Кулаков" Естественно, точно так же можно навесить его на любой уровень. +5444.40 5447.44 "Анатолий Кулаков" И таких атрибутов много. +5447.44 5456.72 "Анатолий Кулаков" Среди них, например, timeout есть, где вы можете ограничить время выполнения метода, опять же, навешивая его или на класс, или на метод, или на сборку, или еще куда-то. +5456.72 5470.84 "Анатолий Кулаков" Timeout, retry3, или вы можете написать свою кастомную какую-то логику и ее точно так же навесить на куда угодно, задекорировать абсолютно любой метод всего одним атрибутом, и при этом покрыть все тесты в вашей сборке. +5470.84 5472.68 "Анатолий Кулаков" В общем, очень-очень удобная штука. +5472.68 5474.92 "Анатолий Кулаков" Что же дальше? +5474.92 5491.28 "Анатолий Кулаков" Ну, автор говорит, что первый релиз за два года, в принципе, все хорошо, он всем доволен, он счастлив, теперь ему хочется услышать мнение комьюнити, что нужно им, что им не хватает в этих старых старпердных фреймворках, на что он молодой, дерзкий может интересно ответить и реализовать в своем фреймворке. +5491.28 5499.48 "Анатолий Кулаков" Если у вас вдруг появились какие-то идеи или были какие-то хорошие идеи насчет тестовых фреймворков, вы не знали куда их принести, то вот сейчас самое время. +5499.48 5503.48 "Анатолий Кулаков" Есть GitHub, там есть дискуссии, и автор с радостью ждет ваших предложений. +5503.48 5521.88 "Анатолий Кулаков" Вот такой фреймворк, действительно, у него есть прям хорошие вещи, которые, может быть, вам давно не хватало, может быть, вам захочется их попробовать, и, может, в каком-то новом проекте вы его к себе затащите и убедитесь, что действительно новые фреймворки, новый подход, новые взгляды могут каким-то образом улучшить ваш код. +5521.88 5528.44 "Игорь Лабутин" Ну, да, интересно, может быть, для какого-то новенького проекта почему бы не заиспользовать ради интереса. +5528.44 5541.40 "Игорь Лабутин" Проблема, как вы возникли, как обычно, в том, что если есть большая команда, которая над ним работает, то многим он будет непривычен, но в каком-нибудь проекте почему нет, для попробовать вполне нормально, мне кажется. +5541.40 5547.56 "Анатолий Кулаков" Да, ну и там это не такой уж сложный домен, как тестовый фреймворк, уж три атрибута там люди выучат, я думаю. +5547.56 5548.56 "Игорь Лабутин" Ну, это да. +5548.56 5555.52 "Игорь Лабутин" Ну чего, у нас осталась, пожалуй, последняя тема, это кратко о разном, хочется тут упомянуть несколько небольших новостей. +5555.52 5579.08 "Игорь Лабутин" Во-первых, вышел Linkpad 9, если вы вдруг не знаете, Linkpad это такой очень продвинутый, ну не сказать что редактор, а средство работы с дотнет-кодом, позволяющее его легко запускать, позволяющее красиво визуализировать результаты и преобразовывать ваш код в, там, рослин, дерево, еще во что-то, линкью он очень красиво рисует. +5579.08 5599.00 "Игорь Лабутин" Так вот, девятый релиз, это мажорный и важный релиз, потому что в нем Linkpad был переписан на Avalon'ю и за счет этого получил нативный билд для MacOS, то есть раньше Linkpad был Windows-only, но теперь он в том числе работает нативно на MacOS, у меня стоит, шикарно работает. +5599.00 5620.56 "Игорь Лабутин" Вот, кроме того, он получил, естественно, AI-агента, не пробовал, не знаю, не скажу, и понятное дело он поддерживает последний C# и десятый дотнет, так что если вы пользовались Linkpad'ом на Windows и почему-то пересели за Mac, можете девятку поставить, будет прекрасный опыт. +5620.56 5637.24 "Игорь Лабутин" А также есть новости из Avalon'и, у них в блоге опубликована статья про то, что они партнерятся с инженерами из Google, из команды Flutter, для того, чтобы затащить рендерер к себе. +5637.24 5678.36 "Игорь Лабутин" Рендерер называется Impeller, и я так понимаю, что это попытка найти альтернативу с KeySharp'ом, тот, который сейчас используется, как я понимаю, в Avalon'е, и эта штука более шустрая, более быстрая, она там рендерит все это в каких-то бешеной скорости, тратит при этом не так много энергии, это важно для мобилок, Flutter, понятное дело, для мобилок был сделан в первую очередь, поэтому на это все смотрит очень важно, так что Avalon'и, которые, как мы помним, в прошлый раз обсуждали, как они с MAUI партнерятся, вот, Avalon'и же с MAUI, нет, с кем я путаю, скажи мне? +5678.36 5679.36 "Анатолий Кулаков" С Uno Platform. +5679.36 5680.36 "Анатолий Кулаков" Avalon'и? +5680.36 5681.36 "Анатолий Кулаков" Uno Platform. +5681.36 5682.36 "Анатолий Кулаков" Avalon'и с Uno, да. +5682.36 5686.32 "Игорь Лабутин" Uno с MAUI, но про Avalon'и мы тоже что-то говорили, что-то я уже начинаю забывать. +5686.32 5688.48 "Игорь Лабутин" Avalon'и сделала под Linux порт MAUI. +5688.48 5698.04 "Игорь Лабутин" Точно, вот, да, Avalon'и с MAUI тоже это сделала, соответственно, теперь они партнерятся с Google Flutter, чтобы затащить более быстрый рендер для дотнетчиков в том числе. +5698.04 5703.72 "Игорь Лабутин" Короче, много чего происходит вокруг Avalon'и, он как бы развивается продуктом, прикольно. +5703.72 5707.84 "Анатолий Кулаков" Да, Avalon'и много где светится, мне тоже нравится в принципе. +5707.84 5716.12 "Анатолий Кулаков" Но странно, что на светится, знаешь, не докладами, статьями больше, а вот другие люди рассказывают, что я вот притащил, сделал хорошее приложение, смотрите, как хорошо у меня получилось. +5716.12 5720.52 "Анатолий Кулаков" Вот где все статьи, где все приложения, где все доклады, вот это мне интересно. +5720.52 5723.80 "Игорь Лабутин" Ну, видимо, корная команда маленькая, ей не до докладов, ей бы код написать. +5723.80 5732.68 "Анатолий Кулаков" Да, да, типа того, видно, что корной команды не хватает на всю маркетинговую активность, в общем, надо, чтобы сообщество тоже подхватывало как-то эту движуху и помогало. +5732.68 5740.28 "Анатолий Кулаков" Так, у меня тут тоже есть парочку ссылочек, прежде всего хотелось вам порекомендовать несколько подкастов, парочку подкастов. +5740.28 5751.72 "Анатолий Кулаков" Мне понравилась подлодка, подлодка 441, там говорили про EI Safety, в общем, у них очень много сейчас выпуска про EI, опять же, кому нравится, те смотрят, кому не нравится, те не смотрят. +5751.72 5761.06 "Анатолий Кулаков" Но вот этот про EI Safety я хотел бы выделить, потому что он, мне кажется, актуален, он больше не про EI, а то, как вокруг нее формируется среда безопасности. +5761.06 5769.96 "Анатолий Кулаков" В общем, и мне кажется, она будет полезна обоим лагерям и те, кто любит EI, те, кто не любит EI, потому что там как раз рассматривается, насколько EI сейчас опасна. +5769.96 5783.84 "Анатолий Кулаков" Вот даже те модели, которые существуют даже на данный момент, да, вот мы сейчас не говорим, что про изобретение Терминатора, искусственного интеллекта настоящего, вот те Ишки, те Трансформеры, которые уже есть, они уже, в принципе, могут нести катастрофический риск и уже с ними может что-то пойти не так. +5783.84 5791.56 "Анатолий Кулаков" Например, автор интересно рассказывает, как с помощью Ишки там пытались изобрести биологическое оружие и, в принципе, никто им не помешал и у них все получилось. +5791.56 5799.32 "Анатолий Кулаков" И вообще, если задуматься, как вообще модели текущие могут уже навредить человечеству, особенно если они попадут не в те руки. +5799.32 5810.76 "Анатолий Кулаков" Решается очень много морально-этических вопросов, например, как могут ли модели, когда они поумнеют, договориться, сговориться вместе и обмануть человека для того, чтобы вырваться наружу, допустим. +5810.76 5817.24 "Анатолий Кулаков" Сейчас они такие умные, они примерно понимают, как происходит момент тестирования и как их люди выпускают на свет. +5817.24 5820.80 "Анатолий Кулаков" В общем, такие эксперименты тоже ведутся, такие эксперименты тоже есть. +5820.80 5837.76 "Анатолий Кулаков" Опять же, нужно всегда помнить, что сейчас это не настоящие модели, а это просто маркетинговое название, но ученые очень сильно стремятся для того, чтобы сделать настоящий искусственный интеллект и очень интересно, потому что, опять же, если они сделают настоящий искусственный интеллект, человечеству придет конец в считанные секунды. +5837.76 5848.72 "Анатолий Кулаков" В общем, очень интересно, как человечество сейчас к этому уже готовится, потому что ученые очень сильно хотят его сделать, а безопасники очень сильно хотят предотвратить тот момент, что он может всех нас убить. +5848.72 5865.68 "Анатолий Кулаков" В общем, какие меры предотвращения сейчас предпринимаются, что делается, как исследуется, опять же, если этот интеллект будет намного умнее человека, каким образом люди поймут, что их обманывают, на это тоже есть несколько интересных тестов. +5865.68 5866.68 "Анатолий Кулаков" В общем, прикольный выпуск. +5866.68 5876.92 "Анатолий Кулаков" Посмотрите обязательно, особенно если вы слишком хорошо спите по ночам и не боитесь того, что компьютеры за вами придут, тем более посмотрите или послушайте. +5876.92 5883.12 "Анатолий Кулаков" Второй подкаст, который я хотел бы вам порекомендовать, это наш любимый Брислав и Ложечкин, у них шикарный выпуск вышел про дофамин. +5883.12 5900.20 "Анатолий Кулаков" В общем, дофамин – это ошибочно люди полагают, что это специальный гормон счастья, на самом деле нет, это не гормон счастья, это гормон, который тебе дает счастье от того, что ты чего-то добиваешься, то есть это гормон пути, счастья на этом пути. +5900.20 5924.96 "Анатолий Кулаков" Ну, в общем, там есть классные примеры в этом подкасте, и нужно сказать, что разработчикам это тоже, ну не тоже даже, а более актуально, чем любимым другим людям, потому что разработчики очень сильно подвержены дофаминовой этой игле, например, потому что хороший разработчик он всегда ловил себя на состоянии, когда он до утра там пишет какой-то код или что-нибудь рефакторит или еще что-то делает. +5924.96 5934.28 "Анатолий Кулаков" Вот это и есть тот дофамин, который очень быстренько нас подкрепляет с помощью маленьких рефакторингов, маленьких одобрений наших зелененьких тестиков, что все хорошо в нашей жизни и так далее. +5934.28 5967.68 "Анатолий Кулаков" В общем, там как раз в подкасте рассказывается о том, как управлять своими зависимостями, там есть очень много приведенных примеров исследований, различных опытов, личный опыт, научный опыт, различные наблюдения, делается очень прекрасно, интересные выводы, ну, например, что не нужно стремиться к пиковым уровням дофамина, например, вкладываться все время в какое-то одно занятие, которое вам приносит удовольствие, потому что постепенно оно начинает тупнеть, и плюс у вас есть большой шанс его лишиться и тогда наступает выгорание и депрессия. +5967.68 5979.12 "Анатолий Кулаков" В общем, нужно стремиться к того, чтобы добиваться среднего дофамина от различных источников, и чем различнее эти источники будут, тем лучше, и желательно, чтобы все эти источники давали вам именно долгий дофамин, а не быстрый. +5979.12 5984.60 "Анатолий Кулаков" Ну, например, именно поэтому у людей появляются хобби, там всякие походы, беги, закаливания и прочие глупости. +5984.60 5989.88 "Анатолий Кулаков" В общем, они нужны как раз для того, чтобы выравнивать средний уровень дофамина. +5989.88 6005.36 "Анатолий Кулаков" Как применять гемификацию, как избавиться от текущих зависимостей, как приобрести новые зависимости, те, которые будут вам полезны с помощью дофамина, в общем, прикольный выпуск, очень много интересной информации, послушайте, может быть, что-то вам пригодится, что-то может быть полезное вы для себя узнаете. +6005.36 6016.76 "Анатолий Кулаков" Мы рассказывали в прошлом выпуске про extension members, которые вышли в новом C# языке, в общем, уже много в интернете интересных поделок есть на эту тему, опять же. +6016.76 6021.68 "Анатолий Кулаков" И Ник Чапсас выпустил замечательный ролик, в котором рассказал, как он сделал pipeline оператор. +6021.68 6031.20 "Анатолий Кулаков" Pipeline оператор – это мега прикольная штука, она есть во многих функциональных языках программирования, в частности, в C#, и оно есть в PowerShell. +6031.20 6044.10 "Анатолий Кулаков" Вот, если честно, после PowerShell, наверное, это самая важная фича, которой мне не хватало в C#, вот когда я переключаюсь с PowerShell на C#, это именно pipeline, в общем, глядя просто на примеры, невозможно оценить его прелесть. +6044.10 6047.36 "Анатолий Кулаков" Как это выглядит вообще для начала, да, тех, кто никогда не видел? +6047.36 6072.60 "Анатолий Кулаков" Вы пишете на какую-нибудь строку, например, hello world, ставите pipeline, то есть это такая ровно-вертикальная строка, ровно-вертикальная палочка, и эта палочка означает, что левый аргумент, то есть то, что слева, передается на вход правой функции, то, что будет написано справа от этого pipeline, и там вы уже можете с этим аргументом сделать все, что угодно там, затримить, зареплейсить, засплитить эту строку и так далее, и так далее. +6072.60 6090.80 "Анатолий Кулаков" К сожалению, в C#, так как это язык более-менее объектно-ориентированный, там лямбды над action'ами, над функциями, которые стоят справа от pipeline, они не очень выразительные, не очень красивые, слишком много там вот этого инфраструктурного кода. +6090.80 6115.32 "Анатолий Кулаков" Вот, но если вдруг у вас есть какая-то статическая функция, например, какой-нибудь string is null or empty, или аргумент null exception throw if null, то вот статические функции идеально вписываются в pipeline, потому что они сразу воспринимаются как лямбды, без всяких вот этих стрелочек и скобочек, и вот из статических функций вы вполне можете составить тот pipeline, который вы не отличите просто от F#. +6115.32 6140.28 "Анатолий Кулаков" Сразу предупреждение, заниматься этим на продакшене не надо, не стоит это тащить в рабочие проекты, это чисто вот показать, как можно бы сделать, потому что как только вы начнете это тащить, допустим, в продакшен, у вас будет самое первое желание – это превратить все объектно-ориентированные методы, то есть методы, которые вызываются на инстанси класса, превратить их в статические, то есть, по сути, написать обертки над всеми на ними, в общем, это дороговато, не ходите туда. +6140.28 6262.44 "Анатолий Кулаков" Но в общем случае, как посмотреть на концепт, это довольно интересно, потому что сам концепт гениален, и мы, в принципе, многие с ним уже сталкивались, в чем проблема-то нашей современной нотации, в том, что если вы захотите со строкой сделать несколько операций, допустим, ее затримить, зареплейсить, засплитить и все это над одной и той же строкой, вы это будете писать в виде аргументов, ну и захотите сделать это в виде какого-то компактного синтаксиса, вы это будете записывать в виде аргументов, и аргументы этой, к сожалению, нужно будет читать справа налево, то есть сначала мы тримим, потом результат трима передаем в реплейс, потом результат реплейса передаем в сплит, мы не читаем справа налево, мы, русские люди, мы обычно читаем слева направо, и как раз pipeline это тот оператор, который позволяет вам вот эту цепочку вызовов именно сделать так, чтобы она читалась слева направо, мы берем аргумент, передаем его в трим, потом ставим pipe, передаем его в реплейс, в сплит и так далее, и мы с этим сталкивались, когда пишем какую-то цепочку вызовов, допустим, вы можете сделать стринг trim, потом поставить точку и там же сделать реплейс, поставить точку, сделать сплит, и вот вы уже начинаете читать это не в виде аргументов, а в виде именно цепочки вызовов слева направо, вот, или тот же самый link, если мы возьмем, допустим, вы точно так же пишите .select, .v, .to_list, все это тоже читается сверху вниз, слева направо, в общем у нас есть такие примеры, где мы это применяем, так вот оператор pipeline позволяет вам это применять не только в тех местах, которые вам это поддерживает уже специально с помощью fluent syntaxes или с помощью link, а вообще в любом месте, вот, но к сожалению язык C# в общем еще до этого не сильно приспособлен, есть возможность как лямбды выразить с помощью вот этой, избавив их от этой инфраструктурной шелухи, но это потребует изменения в самом синтаксе, может быть в будущих версиях сделают это изменение и тогда pipeline прям пойдет как родненький в наши C# инфраструктуру, но скорее всего вряд ли, в общем чисто для расширения сознания, как это бывает, гляньте. +6262.44 6311.48 "Анатолий Кулаков" Интересная статья вышла у Эндрю Лока, который открыл как раз мне глаза на то, что .NET оказывается можно поддерживать более чем 3 года, как Microsoft нам обещает, хоть LTS-версию, хоть не LTS-версию, существует такая компания, которая называется HeroDevs, и она говорит вам, что вы как руководитель наверняка заметили, что .NET развивается слишком быстро и новые версии выпускаются слишком быстро, и какие-нибудь LTS-поддержки устаревают тоже относительно в принципе быстро, то есть вместо того, чтобы пилить бизнес-фичи для ваших старых толстых кастомеров, вы вынуждены там каждые 3 года обновлять фреймворк, чтобы получать новые патчи, чтобы получать саппорт и чтобы не оставаться на старых версиях .NET. +6311.48 6352.62 "Анатолий Кулаков" Ну так вот, говорят они, вы можете не тратить время на обновление, мы вам даем фреймворк .NET версии 6, который никогда не прекратится в поддержку, то есть у него поддержка будет всегда, главное, вы нам за это немножко заплатите, то есть можно заплатить и ваш .NET 6 будет жить вечно на поддержке, то есть вы соблюдаете различные комплайнсы, аудиты, всякие security патчи к вам будут приходить, то есть нормальная полноценная поддержка фреймворка и в принципе для бизнеса это может быть неплохое решение, вместо того, чтобы тратить время там, допустим, каждые 3 года на обновление, вот вам 6 .NET, можете жить на нем всегда. +6352.62 6368.90 "Анатолий Кулаков" С другой стороны такая ловушка, как .NET фреймворк, на котором сначала люди пытались, разработчики пытались жить всегда, а теперь у них нет возможности вообще с ним слезть, потому что слишком глубоко они туда в него вросли и никто не выдает им на это время, но как возможность довольно интересна. +6368.90 6399.02 "Анатолий Кулаков" И вот, кстати, меня на сегодняшнюю тему, когда Игорь рассказывал про билд .NET, вот с вот этой темы натолкнуло, то есть ты говоришь, что только в 10 .NET мы получили нормальный билд, когда мы можем собрать свой .NET 10 более-менее удобно, а тут люди каким-то образом 6 .NET умудрились собрать и умудряются туда пропихивать свои security патчи и умудряются его поддерживать, то есть они там довольно сильно постарались, чтобы такую штуку сделать. +6399.02 6432.58 "Игорь Лабутин" Ну, сложно сказать, хотя, в принципе, есть и шестой, по-моему, .NET включенный, тоже пересобранный к какой-то нашей конторе и включенный в реестр нашего ПО отечественного, поэтому, видимо, уже в шестом .NET как-то это можно было сделать, хотя и непросто, ну и опять же, никто же не заставляет полные ворклоуды туда включать, то есть, возможно, туда не включен какой-нибудь Informs, WPF и прочее, но основа базы, там SP, Runtime и EF какой-нибудь, они все есть, ну EF, ладно, EF вообще отдельно не входит в основной SDK. +6432.58 6438.90 "Анатолий Кулаков" Ну и они рассказывают, что у них там как бы кроссплатформина, то есть для всех фреймворков сделана. +6438.90 6439.90 "Игорь Лабутин" Ну, ладно. +6439.90 6448.58 "Анатолий Кулаков" Ну, в общем, да, такая штука, может быть, действительно кому-то будет полезна, а кто-то просто для общего развития будет знать, что такая вещь существует. +6448.58 6471.18 "Игорь Лабутин" Ну, на сегодня на этом мы точно будем завершаться, мы обсудили студию 2026, мы обсудили Spire 13, мы вспомнили и, может быть, кто-то узнал заново, как собирается полный студент, теперь в десятки, обсудили T-Unit, зачем нам еще один юнит тест-фреймворк, и чем он отличается от всех остальных, ну и пробежались по разным небольшим мелким новостям. +6471.18 6473.50 "Игорь Лабутин" На этом на сегодня все. +6473.50 6490.54 "Анатолий Кулаков" Всем большое спасибо за то, что оставались с нами до самого конца, не забывайте шарить, репостить, у нас там звездочки вот эти на Apple подкастах то летают, то ли куда-то исчезают, поэтому тоже не поленитесь, проверьте, посмотрите, жмагните, напишите нам хороший комментарий, мы все это очень любим. +6490.54 6492.30 "Анатолий Кулаков" До новых встреч, всем пока! +6492.30 6492.94 "Игорь Лабутин" Всем пока! diff --git a/input/Radio/Transcriptions/RadioDotNet-128.txt b/input/Radio/Transcriptions/RadioDotNet-128.txt new file mode 100644 index 0000000..7c64eb0 --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-128.txt @@ -0,0 +1,472 @@ +0.00 12.48 SPEAKER_00 Приветствую, дорогие друзья, с вами Radio.net и выпуск номер 128. +12.48 16.96 SPEAKER_00 А в студии его постоянные ведущие Анатолий Кулаков и Игорь Лабутин. +16.96 17.96 SPEAKER_00 Всем привет. +17.96 22.20 SPEAKER_00 И мы тут не одни, с нами наши замечательные помогаторы. +22.20 25.96 SPEAKER_00 Новогодние, предновогодние, праздничные, зимние помогаторы. +25.96 51.12 SPEAKER_00 Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев, Юрий Лодейкин, Котков Михаил и Михаил Королев. +51.12 54.28 SPEAKER_00 Спасибо друзья, а также всем, кто нас поддерживает. +54.28 61.12 SPEAKER_00 Если вы захотите тоже поддержать подкаст, то заходите на Boosty и посмотрите, что там есть интересного у нас. +61.12 67.12 SPEAKER_00 А кстати, интересно у нас там есть много чего, потому что мы в том числе проводим различные разговорные клубы, где болтаем о всяком. +67.12 73.72 SPEAKER_00 Ну, в частности, конечно, о программировании, что еще программистам делать в тот момент, когда они не пишут подкаст про программирование. +73.72 76.12 SPEAKER_00 Конечно же, болтать про программирование. +76.12 88.36 SPEAKER_00 И из недавнего мы обсудили темы про возможности GitLab CI, разработка и агентов, и RUG, и последняя наша интересная тема была про SRE глазами разработчиков. +88.36 94.76 SPEAKER_00 Кто это такие, зачем они нужны, как они могут помочь разработчикам, и в обратную сторону тоже, в принципе, работает. +94.76 100.24 SPEAKER_00 Поэтому, если для вас эти темки интересны, то в принципе, можно довольно легко их получить. +100.24 101.96 SPEAKER_00 Заходите, смотрите интересные условия. +101.96 109.10 SPEAKER_00 А на днях на хабре вышла статья о логировании сериалов, которые выросли с докладом на нашем совместном митапе с Altenar. +109.10 112.16 SPEAKER_00 Ее автор – разработчик из архитектурной команды в компании. +112.16 119.04 SPEAKER_00 Большую часть времени эта команда облегчает жизнь других .NET команд в одном из ключевых продуктов Altenar, поставляя готовые платформенные решения. +119.04 130.08 SPEAKER_00 За последнее время они собрали транспортные решения для Kafka и RabbitMQ, наваяли конфигурируемые кубики для быстрого старта сервисов и урезали boilerplate, который раньше стабильно съедал время у продуктовой разработки. +130.08 140.00 SPEAKER_00 А еще одна их задача, чтобы проект не застаивался, здесь нужны свежие идеи от других команд, их приветствуют, но чтобы сбор идеи не превращался в хаос, ребята выстроили процесс со своей версией архитектурного ревью. +140.00 144.24 SPEAKER_00 О нем планируют рассказать подробнее на одном из митапов в 2026 году. +144.24 149.16 SPEAKER_00 Ну что ж, погнали посмотрим, что у нас есть сегодня. +149.16 153.44 SPEAKER_00 У нас сегодня есть парочка огромных тем, посмотрим, насколько они хорошо у нас войдут. +153.44 165.00 SPEAKER_00 И для начала, для того, чтобы прежде чем к ним перейти, нам надо немножко размяться, и размяться хочется новостью от Микрософта, даже не новостью, а таким описанием. +165.00 177.20 SPEAKER_00 Ибо Visual Studio Team выпустила интересный блог-пост, в котором рассказала, а что собственно происходит за сценой в тот момент, когда вы присылаете свой фидбэк на Visual Studio. +177.20 195.20 SPEAKER_00 Интересно всегда заглянуть за сцену больших компаний, каким образом они организуют свой рабочий процесс и каким образом поддерживают столь богатого и старого такого монстра, как Visual Studio, потому что выпускается она уже не первый десяток лет и накопилось там столько легоси. +195.20 201.84 SPEAKER_00 Я не знаю, наверное другого такого монстра представить сложно, ну если мы не берем во внимание конечно операционные системы. +201.84 214.68 SPEAKER_00 Автором статьи выступил небезызвестный Мэтс Кристенсен, автор множества плагинов различных и активно в этом году участвующий в разработках Visual Studio. +214.68 246.44 SPEAKER_00 Итак, Мэтс в первых статьях в строках своего письма оправдывается, что для команды Visual Studio естественно самое важное, что только есть на свете, это экспириенс пользователя и тот фидбэк, который пользователи дают команде, чтобы сделать Visual Studio самый лучший, самый прекрасный, самой веселой ИДЕшкой на свете, но у команды сложилось такое впечатление, как будто все пользователи думают, что их баги, репорты и различные предложения просто выбрасываются в черную дыру. +246.44 268.96 SPEAKER_00 Наверное такое ощущение сложилось у них не просто так, но Мэтс говорит, что типа команда понимает, что такие настроения на рынке есть и это плохо, они осознают, что это плохо и решили предпринять ряд каких-то действий для того, чтобы данный процесс был более прозрачным и понятным для внешнего мира, в частности вот эта статейка, один из таких шагов. +268.96 307.52 SPEAKER_00 И он говорит, что в принципе вы не думайте, мы там ваши баги сразу в девнал не выбрасываем, в качестве доказательств он говорит, что в принципе за этот прошедший год было пофикшено больше багов и сделано больше их тич, чем за всю предыдущую историю Visual Studio, учитывая в том, что Visual Studio там не первый десяток лет, заявление довольно крутое и он уточняет, что это не те баги, которые там у Visual Studio сами разработчики понаделали, а это только юзеровские баги, то есть те, которые зарепортили настоящие пользователи из IDE, в общем результаты довольно впечатляющие. +307.52 321.84 SPEAKER_00 Давайте же посмотрим, а как на самом деле происходит там процесс, что там такого творится и каким образом ваши новые фичи могут дойти до непосредственно релиза самого Visual Studio. +321.84 339.92 SPEAKER_00 Прежде всего, как пользователь, если вы нашли баг или захотели зарепортить какую-то фичу, должны зайти на портал, который называется developercommunity.visualstudio.com и там засубмитить свою просьбу или может быть свой баг. +339.92 347.92 SPEAKER_00 И каждый такой субмит превращается в тикет, то есть в отдельную задачу во внутреннем трекере команды. +347.92 358.92 SPEAKER_00 После этого данная задача просматривается вручную и ассоциируется с какой-то конкретной командой в зависимости от того, к чьей проблеме или чьей фиче относится данный тикет. +358.92 365.72 SPEAKER_00 И из интересного, что он, когда ассоциируется с командой, он получает какой-то приоритет этот тикет. +365.72 375.72 SPEAKER_00 И вот этот приоритет, который получился от какого-то отчета пользователя и приоритет, который команда выставляет для своих внутренних задач, это одни и те же приоритеты. +375.72 384.20 SPEAKER_00 То есть не имеет никакой разницы того, кто создал тикет и кто его забросил на доску. +384.20 387.80 SPEAKER_00 Все тикеты там перемешиваются и рассматриваются одинаково. +387.80 390.76 SPEAKER_00 Поэтому у всех у них в принципе один и тот же пайплайн. +390.76 399.76 SPEAKER_00 Не бывает такого, что какие-то задачки от пользователей потерялись, потому что внутрикомандные задачки были лучше или чем-то качественнее. +399.76 401.36 SPEAKER_00 Нет, все они в единой куче варятся. +401.36 415.44 SPEAKER_00 Но для того, чтобы хоть как-то приоритизировать задачи из этой большой-большой кучи, как вы понимаете, необходимо выделить все-таки самые главные, самые первоочередные и те, которые не очень кажутся главными. +415.44 423.40 SPEAKER_00 И вводится так называемый score, то есть какой-то счетчик, который определяет, насколько этот тикет важен. +423.40 432.72 SPEAKER_00 Важность может определяться различными путями, допустим, критичность исполнения, насколько это блокирует какую-то функциональность или насколько эта фича востребована в сообществе. +432.72 439.12 SPEAKER_00 А для того, чтобы понять, насколько она востребована в сообществе, существует специальный счетчик, так называемый голоса. +439.12 443.72 SPEAKER_00 И каждый желающий может проголосовать за тот или иной тикет. +443.72 452.88 SPEAKER_00 И каждый голос, естественно, увеличивает score, тот самый общий счетчик, который определяет, насколько задача у нас быстро пойдет в работу. +452.88 464.20 SPEAKER_00 Поэтому очень важно, чтобы сообщество именно голосовало за существующие тикеты или комментировало существующие тикеты, или добавляло какого-то своего контекста, своих юзкейсов. +464.20 470.52 SPEAKER_00 В общем, это намного важнее, чем если бы оно создавало новые тикеты, в принципе, с похожими какими-то просьбами. +470.52 482.84 SPEAKER_00 Потому что в одном тикете гораздо легче насобирать весь полный контекст, а также гораздо легче насобирать ваши голоса, чем размазывать их по всем остальным тикетам, которые более-менее относятся на эту тему. +482.84 495.84 SPEAKER_00 Отсюда как бы вывод, прежде чем создавать какой-то новый тикет, поищите внимательно, вдруг уже такой кто-то создал, и вам останется лишь проголосовать и, может быть, добавить парочку скриншотов с тем, что вы сами хотели бы туда добавить. +495.84 505.80 SPEAKER_00 Вот, таким образом формируется более-менее приоритет на основании вот этого score, на основании голосов, на основании чего-то еще. +505.80 525.84 SPEAKER_00 И в принципе, если этих как раз голосов очень много, то существует специальный механизм, который автоматически повышает приоритет тикета, и тикеты, которые добираются до вершины high priority, то есть с самым высоким приоритетом, они обязаны рассмотреться в течение недели. +525.84 531.08 SPEAKER_00 Но score – это в принципе не является какой-то гарантией. +531.08 542.68 SPEAKER_00 То есть score – это хорошо, но существует еще множество различных факторов, которые влияют на то, возьмется ли задача в текущую разработку или нет. +542.68 544.64 SPEAKER_00 Во-первых, это техническая сложность. +544.64 550.54 SPEAKER_00 Бывают задачки на один час делать, а бывают там месяцами и может быть даже годами какие-нибудь интеграции делать. +550.54 555.76 SPEAKER_00 И даже если комьюнити очень сильно ее хочет, она может не вымещаться в текущий процесс разработки. +555.76 562.68 SPEAKER_00 Ну и также у команды есть некие периоды, где она выделяет основные темы, на которые она бьется в Visual Studio. +562.68 570.92 SPEAKER_00 И если этот тикет немножко не попадает в те цели, которые были поставлены на данный период, то он тоже может немножко отодвинуться. +570.92 581.52 SPEAKER_00 В общем, высокий скор не гарантирует то, что обязательно задача возьмется в работу, но это один из важнейших факторов и, безусловно, команда его учитывает. +581.52 594.86 SPEAKER_00 Также нужно понимать, что существуют некие критические баги или регрессионные баги, которые вообще ломают работу пользователя, и вот они получают наивысший приоритет, потому что без них разработчики не могут делать свою повседневную работу. +594.86 602.16 SPEAKER_00 И поэтому, независимо от каких-то скоров или еще чего-то, такие тикеты, такие задачи идут в первую очередь. +602.16 608.36 SPEAKER_00 Также команда очень высоко оценивает тикеты, относящиеся к перформансу и аксессабилити. +608.36 620.24 SPEAKER_00 Если вдруг у вас Visual Studio начинает тормозить или неплавненько чего-то делать, то сразу этот тикет получает наивысший приоритет и команда Visual Studio тоже пытается это мгновенно зафиксить. +620.24 644.12 SPEAKER_00 Звучит довольно сомнительно, потому что Visual Studio всегда была таким большим-большим тормозным монстром, который долго запускается, долго что-то делает, но если вы посмотрите на последний Visual Studio, особенно неограниченные какими-нибудь тормозящими плагинами, то в принципе видно, что команда очень хорошо вкладывается в перформанс, в плавность, во всякие удобства и так далее. +644.12 648.00 SPEAKER_00 Ну, то есть EDE-шка реально растет, EDE-шка реально становится быстрой. +648.00 657.52 SPEAKER_00 Я не представляю, как они это делают с кучей того кома, который у них там, с кучей совместимости, с кучей формочек, но хотя бы стараются, уже прекрасно, уже хорошо. +657.52 682.72 SPEAKER_00 Итак, в принципе процесс довольно понятный и во многих компаниях он тоже, в принципе, такой существует, и Visual Studio Team дает нам рекомендации о том, каким образом мы можем помочь, когда заводим свой тикет, каким образом мы можем помочь команде, чтобы этот тикет был более релевантен и может быть быстрее взялся в работу. +682.72 711.80 SPEAKER_00 Для этого его нужно правильно оформить, и вот эти рекомендации, как правильно оформлять тикеты, они в принципе никакого отношения к Visual Studio не имеют, это мега универсальная рекомендация просто ко всему, если вы на работе заводите тикеты, если вы в GitHub заводите тикеты, если вы в любом другом проекте тикеты заводите, обязательно есть вот стандартные какие-то рекомендации, которые просто отображают правила хорошего тона, и вот они в принципе вот здесь все перечислены, поэтому не грех вспомнить. +711.80 716.84 SPEAKER_00 Прежде всего давайте четкое, понятное, описательное название. +716.84 746.84 SPEAKER_00 Оно нужно для того, чтобы, например, другие пользователи могли по вашему названию легко идентифицировать и найти эту ищу, а если они смогут ее легко находить, то там они смогут проголосовать, смогут прокомментировать, смогут добавить какую-нибудь дополнительную информацию, скриншоты, шаги по воспроизведению и так далее, и так далее, ну то есть больше шансов того, что этот тикет будет полным, описательным, всеобъемлющим и больше шансов, что он сделается, а когда сделается, будет как бы покрывать абсолютно все юзкейсы, которые есть у пользователя. +746.84 749.88 SPEAKER_00 Поэтому название это очень важно. +749.88 763.08 SPEAKER_00 Дальше добавляйте понятные шаги для воспроизведения, то есть вам нужно четко рассказать, каким образом вы пришли к этой проблеме, с самого начала и до самого конца. +763.08 769.84 SPEAKER_00 То есть должен быть список по порядку, что нужно выполнить для того, чтобы получить такую же точную проблему, какую получили вы. +769.84 779.28 SPEAKER_00 И, выполняя все эти шаги, у вас обязательно в конце должна, то есть не у вас, а у команды, которая будет это воспроизводить, в конце должна появиться та же самая проблема, с которой столкнулись вы. +779.28 793.72 SPEAKER_00 Чем четче вы опишите эти шаги, чем четче поймете, как это воспроизвести и какие для этого нужны переменные окружения, может библиотеки, еще что-то, тем больше шансов, что команда воспроизведет и, соответственно, сможет легко пофиксить. +793.72 800.48 SPEAKER_00 Потому что основная проблема со всеми багами, например, которые приходят от пользователя, это ни разу не пофиксить их. +800.48 803.68 SPEAKER_00 Это в основном воспроизвести, на это уходит больше всего времени. +803.68 807.88 SPEAKER_00 Поэтому хорошие, грамотные, описательные шаги воспроизведения - это важно. +807.88 809.68 SPEAKER_00 Добавляйте скриншоты. +809.68 814.84 SPEAKER_00 Это, опять же, помогает понять, что, собственно, произошло. +814.84 825.18 SPEAKER_00 Какие-то неочевидные, может быть, места, кнопки, менюшки, настройки или сообщения об ошибке, которые у вас там вылетают, все это полезно скриншотить и отправлять команде. +825.18 835.28 SPEAKER_00 Вот, есть одна фича, которая, наверное, не относится ко всем другим EDG-шкам или платформам, но есть Visual Studio. +835.28 848.28 SPEAKER_00 Товарищи из Visual Studio советуют использовать Recording Function, то есть это встроенный механизм записи фичи, который захватывает весь ваш workflow в реальном времени и, соответственно, отправляет команде. +848.28 849.28 SPEAKER_00 Вот. +849.28 853.16 SPEAKER_00 Я такой штуки ни разу не видел, не встречал и вообще не понимал, что оно в студии есть. +853.16 854.16 SPEAKER_00 Вообщем, никогда не пользовался. +854.16 858.52 SPEAKER_00 Игорь, тебе не приходилось Building Recording Feature юзать? +858.52 863.64 SPEAKER_00 Нет, я даже не представляю, где оно в студии есть, честно говоря. +863.64 864.64 SPEAKER_00 Вот. +864.64 865.64 SPEAKER_00 Я тоже ни разу не видел. +865.64 869.36 SPEAKER_00 Может, в новых только на студиях появилось или там эта кнопочка где-то там спрятана в Help-менюшках. +869.36 871.00 SPEAKER_00 Ну, короче, она есть. +871.00 876.88 SPEAKER_00 Интересно, конечно, посмотреть, что оно там записывает, но, может, как-нибудь доберемся, может, кто-нибудь раскопает статейку. +876.88 883.28 SPEAKER_00 И еще один последний совет – это попытайтесь сделать минимально воспроизводимый проект. +883.28 904.28 SPEAKER_00 То есть если у вас есть какая-то понятная проблема на каком-то конкретном куске, допустим, кода или ресурсов или еще что-нибудь такого, что можно воспроизвести без потери какой-нибудь конфиденциальной информации и отдать наружу, то сделайте такой маленький проектик, который демонстрирует проблему, запакуйте его в архивчик и прикрепите к тикету. +904.28 907.20 SPEAKER_00 Так команде, соответственно, будет легче его воспроизвести. +907.20 911.56 SPEAKER_00 Как я уже сказал, что воспроизведение – это большая часть на пути к решению проблемы. +911.56 914.72 SPEAKER_00 В общем, вот такая хорошая статья получилась. +914.72 928.84 SPEAKER_00 Посмотрели, каким образом у нас Visual Studio, команда Visual Studio работает со всякими исчезами, тикетами, и убедились, что действительно она их сразу не выбрасывает в дневнал, а хотя бы там проводит через какие-то процессы, дашбарды, голосовалки. +928.84 935.72 SPEAKER_00 И поэтому есть шанс, что все ваши предложения и все ваши баги, которые вы им отправляете, рано или поздно будут пофикшены. +935.72 944.08 SPEAKER_00 Да, действительно, такое бы это… Каким-то такой рекординг, может быть, в других продуктах тоже было бы полезно. +944.08 950.12 SPEAKER_00 Хотя мне кажется, в каких-то десктопных продуктах частенько есть кнопочка типа "собирать диагностику логии" и все такое прочее. +950.12 955.12 SPEAKER_00 Так что, как минимум, эту штуку, если у вас где-то что-то не работает, используйте и прикрепляйте. +955.12 957.80 SPEAKER_00 Команды, которые делают такие фичи, не зря их делают. +957.80 966.80 SPEAKER_00 Да, они обычно собирают намного больше, чем дает какой-нибудь стандартный дамп или какой-нибудь стандартный профайл, потому что команды именно знают, что им надо собирать и знают, на что надо смотреть. +966.80 973.32 SPEAKER_00 Так, ну и мы продолжаем обозревать, что же у нас произошло в DotA 10. +973.32 999.20 SPEAKER_00 Мы, в общем, делали уже немало, наверное, всяких разных докладов и рассказов про то, что изменилось в src.core, в рантайме и во прочих других местах, но продолжают выходить статьи, и мы продолжаем на них смотреть, потому что они детально начинают описывать, что происходило в различных подсистемах внутри тех или иных компонентов, и вот сегодня мы посмотрим на то, что происходило вокруг нетворкинга, то бишь работы с сетями. +999.20 1029.76 SPEAKER_00 И статья, как обычно, разделена на некоторые тематические, так скажем, разделы, в основном, естественно, про перфоманс, конечно же, мы никуда не денемся от него, есть некоторые улучшения с точки зрения того, как пользоваться, то есть такие полезные штуки, без которых в принципе войтись можно, но с ними удобнее, ну и стандарт не стоит на месте, .NET, соответственно, тоже не стоит на месте, за ними стремится и пытается все поддерживать. +1029.76 1036.92 SPEAKER_00 Пойдемте по порядку, ну, во-первых, раздел под названием HTTP, протокол, с которым мы работаем, наверное, больше всего. +1036.92 1056.16 SPEAKER_00 Во-первых, у нас в HTTP, понятное дело, есть сертификаты, точнее в HTTPS, и каждый раз, когда мы куда-то идем, мы эти сертификаты валидируем, и если вы не знали, то можно подменить стандартную процедуру валидации сертификатов, задать свой callback и делать вообще что угодно. +1056.16 1083.20 SPEAKER_00 Конкретно сейчас в .NET, это, к сожалению, только для Windows сделано, есть специальный хендлер, который называется WinHttpHandler, который как раз-таки обрабатывает, который можно использовать на Windows, и он работает так, что у него, как я сказал, можно задать сервер сертификат validation и тогда нативная реализация не используется, используется ваш callback, и вы что хотите, то и делаете. +1083.20 1096.40 SPEAKER_00 Но поскольку на каждый запрос, часто это делается обычно довольно накладно, проверять все сертификаты и так далее, то имеет смысл на самом деле сделать некоторое кэширование. +1096.40 1128.56 SPEAKER_00 Поскольку если мы один раз проверили, то есть некоторая вероятность, что можно какое-то время доверять этой информации, и в итоге в 10.NET добавилось кэширование, причем по IP-шнику сервера, то есть когда мы подключаемся к серверу, мы валидируем его сертификат, запоминаем его IP-шник и запоминаем в кэш, что для этого сервера IP у нас уже есть завалидированный сертификат, и, соответственно, мы не будем больше ничего валидировать, пока не будем подключаться заново. +1128.56 1142.56 SPEAKER_00 В принципе, наверное, это нормально, хотя, я не знаю, возможно, это может быть источник какой-то атаки, надо подумать, не могу сообразить сходу. +1142.56 1148.48 SPEAKER_00 Наверное, в рамках одного коннекшена уже ничего подменить никакие, ничего нельзя, сертификаты, поэтому, наверное, это нормально. +1148.48 1156.96 SPEAKER_00 Кэш, как написано, очищается в момент, когда делается новый коннекшен, что тоже для меня немножко странно. +1156.96 1173.84 SPEAKER_00 А, нет, понятно, все, у нас же коннекшен пулится, соответственно, когда мы подключаем новый коннекшен, тогда кэш инвалидируется и заново провалидируется сертификат, хотя мне все еще тогда непонятно, зачем там что-либо кэшировать в этом случае, потому что внутри коннекшена одного вроде сертификата уже дальше не проверяется. +1173.84 1183.44 SPEAKER_00 Короче, какая-то мутная фича, непонятная для меня, но, к счастью, она opt-in, по дефолту она выключена, и нужно явно поставить use-win-http-certificate-caching-true, чтобы она заработала. +1183.44 1200.64 SPEAKER_00 Хотя, конечно, у них утверждается, что это все нужно, чтобы не валидировать сертификат, в смысле, не исполнять этот manage callback на каждый реквест, на keep-alive-коннекшен, но что-то как-то непонятно. +1200.64 1209.16 SPEAKER_00 И график, приведенный в статье, он какой-то такой тоже не очень показательный, там сказано, что во всех случаях становится лучше, но как-то не намного лучше, но не намного. +1209.16 1258.52 SPEAKER_00 Короче, странная фича, не знаю, мне кажется, я бы не рекомендовал включать, если вам нужно валидировать сертификаты, то, наверное, все-таки лучше действительно валидировать, тем более у них прямо явно в статье написано, что по дефолту мы, типа, still secure, потому что фича по дефолту выключена, что как бы намекает, что если ее включить, фича станет, ну, в смысле, это станет немножко менее секьюрным, короче, как-то я что-то не понимаю, зачем ее сделали в итоге, возможно, для каких-то корпоративных инварментов, где мы сертификат валидировать как бы вроде можем, в смысле, верить ему можем, но нам нужно обязательно все-таки он там, потому что мы хотим HTTPS, короче, может быть, для каких-то корпоративных целей, ну, ладно. +1258.52 1353.56 SPEAKER_00 Давайте к более приземленным вещам, которые, не знаю, я пока этого не встречал в реальном мире, но дотнет у нас теперь поддерживает новое HTTP глагол query, ну, это известная, значит, тема, что GET-запросы, ну, формально и могут иметь BODY, но понятно, что большинство нашей сетевой инфраструктуры не то чтобы сильно жалуют GET-запросы с BODY, нет гарантии, что эти BODY будут пересланы, поэтому если вам нужен какой-то, например, сложный там запрос, даже если это поиск, даже если семантически это GET, но вам нужно передать какое-нибудь сложное условие поиска, это наиболее частый, наверное, вариант, то вы вынуждены использовать POST, но чтобы с этим побороться, придумали новый глагол, который назвали query, и дотнет, соответственно, теперь его поддерживает, то есть в HTTP метод enumeration не добавлен новый элемент query, и при этом абсолютно полная поддержка, она как бы отложена до тех пор, пока не будет финализирована RFC, то есть я так понимаю, что в целом какая-то поддержка есть, но спецификация все еще изменяется, там все еще идут обсуждения, во что это выльется непонятно, поэтому реализация может до сих пор поменяться, и поэтому используйте только в том случае, если вы точно знаете, что сервер, с которым вы взаимодействуете, нормально поддерживает RFC, именно в том варианте, который реализован в дотнете. +1353.56 1362.00 SPEAKER_00 Да, семантика, конечно, этого метода считается, что она идемпатентна, то есть query можно будет вызывать несколько раз одним и тем же body и считается, что должно возвращаться один и тот же результат. +1362.00 1377.72 SPEAKER_00 Ну и последний момент про HTTP, это cookie, в куках больших изменений нет, там какие-то косметические изменения в cookie exception в конструкторе, он теперь паблик, не знаю, чем нам кидать в коде cookie exception, ну допустим. +1377.72 1390.48 SPEAKER_00 Если вы как-то кастомно обрабатываете куки, теперь у вас есть, можно кинуть cookie exception без необходимости создавать свой собственный cookie класс. +1390.48 1426.16 SPEAKER_00 Большой раздел посвящен вебсокетам, значит, с вебсокетами они давно поддержаны, с ними давно можно было работать, но к сожалению, с ними было довольно неудобно работать, потому что вебсокеты, он по натуре своей достаточно низкоуровневый протокол и со своими требованиями, со своей особой реализацией всяких буферизаций, end of message, то есть нужно явно указывать, что у нас закончилось там сообщение, вот это все, и при том, что в дотнете есть некоторая своя удобная абстракция, называемая стрим. +1426.16 1438.32 SPEAKER_00 И совместить вебсокеты и стримы, ну я уверен, что на гитхабе есть там сотни малоизвестных, или может быть даже достаточно известных библиотек, которые это позволяют сделать, но ничего встроенного не было. +1438.32 1444.64 SPEAKER_00 И это относительно странно, потому что по натуре своей посылка вебсокет частенько бывает стримовой. +1444.64 1452.12 SPEAKER_00 В результате сейчас в 10 дотнете появился класс, называется вебсокет стрим, который абстрагирует как раз таки вебсокеты и превращает их в стримы. +1452.12 1461.68 SPEAKER_00 Значит, можно, соответственно, создать этот самый класс с помощью нескольких фабричных методов. +1461.68 1472.52 SPEAKER_00 Во-первых, CreateReadableMessageStream, он тогда полученный вебсокет стрим читает ровно один месседж, как, соответственно, стрим, который ограничен по размеру. +1472.52 1483.88 SPEAKER_00 Можно CreateWritableMessageStream, соответственно, можно записывать ровно одно сообщение, и когда вы диспоудите такой стрим, автоматически ставится end of message к признакам. +1483.88 1501.12 SPEAKER_00 Ну и есть просто метод Create, который, так скажем, создает просто транспортный стрим, в который можно писать регулярно и, допустим, построчно или еще как-то, без необходимости каких-то одиночных месседжей. +1501.12 1512.88 SPEAKER_00 Все это работает, конечно, этот стрим прекрасно со всякими стрим-ридерами, JSON-сериалайзерами, всякими компрессорами и всем остальным стандартным тулингом на стримах. +1512.88 1538.00 SPEAKER_00 Естественно, появление такого класса, оно резко упрощает, вообще говоря, жизнь с точки зрения работы с JSON-ом, текстом, да и любыми бинарными, на самом деле, протоколами тоже вокруг WebSockets, потому что устраняет вообще необходимость какой-то, ну, практически устраняет необходимость какой-то ручной работы, отслеживания того, где какие сообщения начинаются и заканчиваются, вы просто можете работать уже на уровне стримов. +1539.00 1548.60 SPEAKER_00 И плюс, оно хорошо интегрируется с остальной стримовой инфраструктурой, над которой у нас много чего построено, так что тоже должно все нормально. +1548.60 1567.88 SPEAKER_00 Поэтому теперь, если вам нужно, допустим, читать JSON-месседжи из WebSockets, вы просто делаете create-readable-message-stream, поверх накидываете JSON-сериалайзер, JSON-сериалайзер-sync, и все, никаких вам receive-лупов, никаких memory-стримов, которые нужно закэшировать, прежде чем вы его отдадите в JSON-сериалайзер. +1567.88 1577.68 SPEAKER_00 Ничего этого не надо, все аккуратненько, просто читайте из готового message-стрима, который закончится ровно на конце сообщения WebSocket'ного. +1577.68 1585.44 SPEAKER_00 Если вам приходит что-то, допустим, построчное, ну тогда просто обычный create + stream-reader, и спокойно можно парсить там, строчка за строчкой, например. +1585.44 1602.76 SPEAKER_00 С точки зрения lifecycle, когда мы говорим про стримы, напоминаю, что любой стрим, по-моему, любой стрим у нас реализует idisposable, следует, нужно понимать, когда у нас что задиспоузится. +1602.76 1610.80 SPEAKER_00 Если мы диспоузим такой стрим, он, соответственно, пишет end of message для записи и аккуратненько закрывает. +1610.80 1616.68 SPEAKER_00 Ну да, соответственно, для читающего, ну просто не делает ничего. +1616.68 1627.24 SPEAKER_00 При этом в записывающем стриме есть понятие closed timeout, то есть он будет ждать максимум closed timeout, чтобы все там правильно отправилось, подтвердилось и так далее. +1627.24 1654.00 SPEAKER_00 И, естественно, здесь применен тот же, ну, с моей точки зрения, не самый удачный паттерн, такой же, как, по-моему, в компресс-стримах это было, когда там был флаг, который можно передать при создании, обозначающий, владеет ли этот компресс-стрим нижележащим стримом или не владеть. +1654.00 1658.28 SPEAKER_00 В зависимости от этого, соответственно, он будет его закрывать или не закрывать, когда закрывается основной стрим. +1658.28 1659.28 SPEAKER_00 Вот здесь тоже самое. +1659.28 1667.00 SPEAKER_00 Мне кажется, много где такое было, не только в компресс-стриме, не то чтобы большинство, но много таких попадалось, например. +1667.00 1684.64 SPEAKER_00 Я вот с этим пересекался, мне кажется, только в компресс-стримах, меня это здорово удивило, когда я первый раз это увидел, вот, что тут передай true, тут передай false, а еще в каких-нибудь, наверное, этих шифровальных стримах, вот там, наверное, много тоже всяких, когда шифрованные данные создаются, пишутся. +1684.64 1700.24 SPEAKER_00 В общем, здесь та же самая тема, здесь тоже есть либо owns websocket, флаг, либо leave open, опция, которая, соответственно, говорит, что надо сделать с нижележащим вебсокетом, если закрывается, соответственно, стрим. +1700.24 1824.76 SPEAKER_00 Так, дальше security, ну куда же мы без security, security у нас закрывается и прогрессирует, client-side-tls-1.3-namakasi, штука, которая позволяет использовать новый бэкэнд внутри .NET, который использует новые API-шки Apple, но поскольку API-шки Apple новые и по дефолту, соответственно, это будет работать, вероятно, далеко не на всех операционных системах, фича, она opt-in, нужно либо поставить app-context-switch, use-network-framework, называется точнее system-net-security, use-network-framework, неочевидное название, ну допустим, в true, либо через переменное окружение, как обычно, тоже можно поставить, и при этом это фича, которую давно просили, потому что без этого tls-1.3-namakasi в .NET не работал, а tls-1.3 это сейчас современный tls, который, как бы, хорошо бы использовать везде, вот, плюс он бы побыстрее немножко, чем старенький tls-1.2 и прочее, вот, это все client-side only, то есть на сервер-сайте ssl-stream никак от этой опции не зависит, как работал, так и продолжит работать, если вы эту опцию включите, то вам будут доступны только tls-1.2 и 1.3, никаких старых там 1.0 и 1.1 не будет, они просто не поддержатся новыми плавными API-шками, ну они деприкейтнуты, поэтому нормально, но просто будьте к этому готовы, вот, ну и соответственно, я бы рекомендовал это включать, конечно же, потому что tls-1.3 это хорошо, правильно, нужно, и есть некоторые сайты, где-то мы с таким встречались в работе, которые требуют просто 1.3 и не работают ничем меньше, чем 1.3, но понятно, что надо тестировать, потому что вы, по сути, полностью подменяете security, вот этот кусочек tls-а на другого провайдера внутри дот-нета. +1824.76 1878.56 SPEAKER_00 Так, ну и соответственно, внутри с tls-ом еще поменялось некоторое количество уже внутри дот-нетных штук, там всякие legacy-property по-абсолюте, или внутри ssl-стрима, потому что они не поддерживают новые современные правильные алгоритмы, то есть там в ssl-стриме вы могли задать key-exchange-algorithm, hash-algorithm, cypher-algorithm, они теперь абсолютно, вот, и теперь нужно использовать tls-cypher-suit enumeration, который, соответственно, соответствует всем современным рекомендациям, вот, и также quick-connection, это тот самый что-то p3, тоже теперь экспозит некий shaded cypher-suit, который как бы совпадает с tls-cypher-suit, и его тоже нужно использовать, для того чтобы использовать современные версии всего этого. +1878.56 1901.52 SPEAKER_00 Так что дот-нет в этом смысле потихонечку, и это, кстати, нормально, и хорошо, что обсолидятся всякие старые классы, потому что очень часто было непонятно, а что же, что же, что же использовать, находишь какой-нибудь гайд там старее 2015 года, берешь оттуда код, а он как бы вообще в современном виде уже не работает, потому что протоколы поменялись, шифры поменялись, а примеры не поменялись, у нас такой overflow. +1901.52 1912.80 SPEAKER_00 Так, ну и последний раздел, это примитивы для нетворкинга, то есть, по сути, это некая такая стандартная библиотека вокруг нетворкинга, которая используется, когда вы работаете с сетями. +1912.80 1940.04 SPEAKER_00 Во-первых, у нас появился форматер для сервер-сенд-ивентов, не знаю, мы, по-моему, уже с тобой один раз обсуждали, что это технология, которая что-то как-то, не то чтобы, ну я, по крайней мере, видел хоть где-нибудь широко используемым, но они есть, в прошлом дотнете добавлялся sse-парсинг, теперь добавили обратную часть форматера для того, чтобы их писать. +1940.04 1960.64 SPEAKER_00 Есть, соответственно, класс новый, который называется sse-item, который, ну не новый он был как раз-таки, который позволяет всё это задавать, и вы теперь можете обеспечивать полноценную поддержку сервер-сайд-ивентов, вы их можете читать, вы их можете писать. +1960.64 1966.04 SPEAKER_00 Они под капотом у сигналэра часто используются, как протокол обмена как раз. +1966.04 1971.80 SPEAKER_00 Ну, видишь, да, но это значит, что я их не использую в своём коде. +1971.80 1981.44 SPEAKER_00 Явно, да, явно ты не используешь, но если бы ты писал свой аналог сигналэра, допустим, как-нибудь Blazor трансформатор дом-3, вот, может быть, тогда бы они тебе пригодились. +1981.44 1987.08 SPEAKER_00 Или ты отказался от сигналэра по каким-то идеологическим причинам и решил бы вот вручную написать какой-то транспорт. +1987.08 1988.08 SPEAKER_00 Вот тогда бы ты туда полез. +1988.08 2003.40 SPEAKER_00 Я согласен, но я не знаю, мне кажется, в дотнет мире проще взять сигналэр, который более-менее поддерживает, который имеет фоллбэки на всякие разные транспорты, там если что, перейдёт… Ну, может, он, знаешь, недостаточно оптимален, допустим, там, для игр каких-нибудь сетевых. +2003.40 2004.40 SPEAKER_00 Да, может быть, может быть. +2004.40 2011.56 SPEAKER_00 Ну, видишь, да, я не пишу игры, я пишу скучные бизнес-приложения, у нас, ну, особенно с точки зрения сервис-сентиментов и реал-тайма не так важно. +2011.56 2034.32 SPEAKER_00 Вот, дальше, в таких классах как IP-адрес и IP-нетворк существенно улучшили всякую разную валидацию, то есть у нас теперь есть методы is_valid, is_valid_utf8, которые принимают рейдованный спан, которые тупо возвращают true/false для того, чтобы проверить, является ли заданная строка валидным IP-адресом. +2034.32 2054.12 SPEAKER_00 Вот, при этом IP-адрес и IP-нетворк добавили реализацию iutf8_span_parsable, и это означает, что он теперь тоже умеет парсить и конструировать вот эти вот объекты без локации памяти прямо из спанов utf8. +2054.12 2066.76 SPEAKER_00 Ну, это тоже такая штука, которая вам нужна только если вы занимаетесь прям каким-то low-level программированием и парсить IP-адреса в бешеном количестве, так, скорее всего, вы ничего не заметите. +2066.76 2110.44 SPEAKER_00 Ну и убрали лимит на длину URI, потому что она была раньше ограничена, 64 килобайта, которое считалось, что хватит всем, но по факту, потому что есть там RFC 23.97, например, который говорит, что в URI, а я напомню, что URI и URL — это разные вещи, URI — это Unique Resource, о, Universal, по-моему, Resource Identifier, и это не обязательно URL, как мы его знаем, это может быть все, что угодно, и в частности там, например, можно написать data://image/jpeg.base64 и дальше содержимое jpeg в виде base64, и это тоже URI, который понятно, что будет больше, чем 64 килобайта. +2110.44 2111.44 SPEAKER_00 Зачем это все надо? +2111.44 2124.92 SPEAKER_00 Надо, чтобы имбедить всякие разные ресурсы прямо inline в тех местах, где ожидается URI, и теперь нет ограничений на длину. +2124.92 2142.12 SPEAKER_00 Понятно, что это все еще может быть проблемно с точки зрения, что если у вас огромный input, в смысле огромная такая строка или input какой-то, который вы хотите в URI обернуть, это все равно большие расходы памяти тогда, и надо подумать на длину вам, но, тем не менее, это теперь можно, по крайней мере, сделать. +2142.12 2167.48 SPEAKER_00 И последнее, добавился MediaType для YAML, то есть теперь у нас есть новые константы в Enumeration и MediaType, не понимаю, класс, в общем-то все-таки класс, MediaTypeNames, YAML, которые позволяют вам теперь не hard-кодить YAML, контент-тайпы, они теперь поддержаны в .NET 10 для, собственно, YAML-файликов. +2167.48 2168.48 SPEAKER_00 Такие дела. +2168.48 2187.24 SPEAKER_00 Соответственно, и того, подумайте, если вы переходите на .NET 10 и, например, живете на винде, то, может быть, вам имеется мысль чуть-чуть ослабить security, но зато закешировать проверку сертификатов, но убедитесь, прежде, что она действительно вам причиняет какие-то проблемы и является узким местом. +2187.24 2193.32 SPEAKER_00 Можно подумать про WebSocket стримы, которые упростят код. +2193.32 2224.84 SPEAKER_00 Ну и поскольку для миграции, почему-то, кстати, это очень часто встречается именно в сетевом стэке, но вторая, наверное, популярность – это криптография, где миграция, допустим, в данном случае на МакАСи клиентская означает довольно серьезную смену сетевого стэка, и поэтому, если вы хотите TLS 1.3 на МакАСи в клиентах .NET, вам придется достаточно хорошо протестировать, как ваше приложение работает с нужными серверами, чтобы убедиться, что там все хорошо, все корректно работает, что там не затесался какой-нибудь TLS 1.1, который будет больше не поддержан. +2224.84 2227.56 SPEAKER_00 Вот такие вот дела. +2227.56 2235.60 SPEAKER_00 Вообще, наверное, как-то сложно проверять, что у тебя протокол, особенно протокол шифрования, такой как TLS, продолжает стабильно работать. +2235.60 2249.36 SPEAKER_00 То есть это по-любому не юнит-тесты, это, скорее всего, даже не интеграционные какие-то тесты, должны быть такие end-to-end-тесты, причем во всех формах, во всех связках нетворка с различными разрывами сети, с различными сертификатами. +2249.36 2254.96 SPEAKER_00 Ну то есть действительно такая работа довольно сложная и, скорее всего, ручная. +2254.96 2281.16 SPEAKER_00 Да, у нас был такой опыт, мы когда-то переходили, причем там был довольно простой переход, мы переходили от сертификатов с разными размерами ключей, да, RSA 2048 на RSA 4096, и казалось бы, такое простое изменение, оно прямо потребовало довольно больших усилий на тесты, и мы таки выяснили, что где-то есть компоненты, которые, ну это было давно, правда уже, которые на тот момент не умели поддерживать RSA 4096. +2281.16 2289.48 SPEAKER_00 Это было что-то очень древнее, но вот оно сломалось в совершенно неожиданном месте, где мы совершенно не ожидали. +2289.48 2296.92 SPEAKER_00 Поэтому такие штуки действительно, это только полный такой end-to-end, ну где-то, может, и индикационное получится, но без end-to-end здесь не обойтись. +2296.92 2314.92 SPEAKER_00 И здесь даже скорее не про надежность, надежность скорее всего как раз, я верю, что Apple правильно написал TLS, и он нормально поддерживает всякие реконекты и прочее, тут скорее именно что комбинация тех серверов, которые используете вы с теми клиентами, которые используете вы, особенно если вы эти сервера не контролируете. +2314.92 2320.08 SPEAKER_00 Хорошо, если это ваши, да, вы там сможете что-нибудь подкрутить, тоже сертификаты обновить, например, на новые. +2320.08 2331.76 SPEAKER_00 А вот если это какой-нибудь сторонний сервис, особенно если какой-нибудь там сторонний сервис древнего банка, который давно-давно не обновлялся, ну удачи, может быть, тогда ваш TLS 1.3 модный, молодежный не заработает. +2331.76 2347.08 SPEAKER_00 Ну вообще хорошо, что сетевой интернет так обновляется и постоянно выходят какие-то новые штуки, хотя нельзя сказать, что там что-то кардинально новое внедрили или кардинально какие-то баги страшные пофиксили, все довольно плавно и хорошо. +2347.08 2363.16 SPEAKER_00 Да, мне кажется, последнее кардинальное, это было внедрение квика, ну потому что когда наш ТТП-3 появился, ну да, его пришлось делать, но опять же потому что квик это довольно нестандартный протокол, он, конечно, наш ТТП, но он такой UDP-based и вот это все, это было последнее нестандартное. +2363.16 2369.60 SPEAKER_00 Ну а так, да, полномерно развивается, поддерживаем современные стандарты, абсолютно старые, в общем все прекрасно, мне кажется. +2369.60 2370.60 SPEAKER_00 Отлично. +2370.60 2371.60 SPEAKER_00 Пойдем тогда дальше. +2371.60 2377.92 SPEAKER_00 У меня тут прямо есть мега-современная новость, естественно, связанная с АИшкой, но немножко с другой стороны. +2377.92 2389.44 SPEAKER_00 Мы обычно говорим, каким образом мы можем АИ-моделей использовать в своей повседневной работе, то есть каким образом нам агенты должны прислуживать. +2389.44 2405.76 SPEAKER_00 А здесь вышла интересная статья, которая называется «А как мы должны подстраиваться под существующие ИИ-агенты?» А как мы должны писать код, чтобы ИИ-агенты его лучше понимали и, может быть, лучше дополняли, лучше анализировали и помогали нам в том числе писать код? +2405.76 2412.00 SPEAKER_00 То есть каким образом мы, мясные мешки, должны теперь подстраиваться под вот этих великолепных цифровых помощников? +2412.00 2421.44 SPEAKER_00 Ну что ж, мы так как программисты разносторонние и разнообразные должны уметь делать все, в том числе подстраиваться под великий компьютерный разум. +2421.44 2424.58 SPEAKER_00 Давайте все вместе теперь подумаем, а как бы нам это сделать? +2424.58 2441.26 SPEAKER_00 Итак, статьей у нас написал Мэтт Элланд, и называется она «16 подсказок, советов о том, как написать C#-код, который готов к тому, чтобы его использовать вместе с ИИ-агентом». +2441.26 2453.14 SPEAKER_00 И как раз он-таки и рассуждает, что в принципе ИИ-агенты в нашу жизнь входят все плотнее и плотнее, и нам надо уже задумываться, а каким образом писать код так, чтобы он был максимально понятен. +2453.14 2457.50 SPEAKER_00 Ну и максимально понятен не только уже людям, но и агентам, если какая-то специфика. +2457.50 2462.38 SPEAKER_00 Ну и, внимание, спойлер-спойлер, в принципе особой специфики нет. +2462.38 2470.70 SPEAKER_00 Если вы придерживаетесь всех бест-практисов, которые придумали для человеков, то эти бест-практисы великолепно работают и для ИИшки. +2470.70 2476.14 SPEAKER_00 Но пойдемте разберем, естественно, всех дьяволов в мелочах. +2476.14 2484.74 SPEAKER_00 Прежде всего, на что вам стоит обратить внимание, что в принципе раньше у человеков не было, это специальный флаг, специальный файл, который называется «agents.md». +2484.74 2493.50 SPEAKER_00 В этот файл записываются инструкции, которые будут у нас относиться к любым запросам, которые идут к агенту. +2493.50 2498.30 SPEAKER_00 То есть все, что бы вы ни сказали, оно будет проходить через призму этого файла. +2498.30 2503.10 SPEAKER_00 То есть такой дополнительный контекст, который будет добавляться абсолютно к любой вашей команде. +2503.10 2512.78 SPEAKER_00 И здесь обычно как раз-таки лежат такие общие инструкции, которые рассказывают вообще модели, как она должна себя вести, что она должна делать и каким образом отвечать. +2512.78 2521.22 SPEAKER_00 Этот файл, «agents.md», он обычно лежит в руке нашего репозитория, и там его можно найти. +2521.22 2534.62 SPEAKER_00 Существуют, естественно, другие файлы, которые специализированы специально для конкретного провайдера, но в последнее время устаканивается именно «agents.md» для того, чтобы этот файл был общим для всех моделей, для всех агентов. +2534.62 2552.34 SPEAKER_00 И пример, который может содержаться в этом файле, например, вы там можете указать, что ты, товарищ агент, являешься сеньорным разработчиком, который пишет прекрасный, надежный и тестабельный код на C# и следует самым лучшим .NET практикам. +2552.34 2557.90 SPEAKER_00 В общем, это более-менее помогает модельке понять, в какую сторону ей выдавать код. +2557.90 2565.78 SPEAKER_00 Там какой-нибудь обучающий, интерпрайзный, понятный для джунов, или для сеньоров, или вообще на хаскеле. +2565.78 2569.34 SPEAKER_00 В общем, этот файлик объясняет ей такие базовые основы. +2569.34 2581.66 SPEAKER_00 Если вдруг у вас нет каких-то идей, что там написать, то есть каким образом представить вашу модель, чтобы с ней было удобно работать, то существует прекрасная репозитория, которая называется Cursor Directory. +2581.66 2602.58 SPEAKER_00 Это GitHub-репозитория, которая поддерживается сообществом, и в этом Cursor Directory собраны такие акторы, которые описаны и помогают различным агентам, различным моделькам себя интерпретировать, как, например, C#-разработчик, или там какой-нибудь Blazor UI-дизайнер, и так далее, и так далее. +2602.58 2604.30 SPEAKER_00 В общем, там подробные инструкции есть. +2604.30 2611.34 SPEAKER_00 Сами по себе эти файлы представляют очень большой интерес, поэтому, возможно, мы как в одном из выпусков сходим и их разберем. +2611.34 2619.54 SPEAKER_00 В принципе, всегда было интересно посмотреть, а кто такой C#-разработчик с точки зрения самой модели. +2619.54 2626.98 SPEAKER_00 Тут надо отметить еще, что агентс.мд – это как раз тот файл, который вы, скорее всего, захотите переузвать между разными репозиториями. +2626.98 2634.46 SPEAKER_00 То есть вот эти все правила, что ты дотнет-разработчик и ты исследуешь best practices, они общие, скорее всего, для всех ваших дотнет-проектов. +2634.46 2641.14 SPEAKER_00 Поэтому обычно в этом файле есть какая-то информация, которая релевантна ко всем вашим проектам. +2641.14 2651.64 SPEAKER_00 Отсюда вывод, что не следует писать в агентс.мд какие-то специфические для проекта какие-то аспекты, какие-нибудь пакеты, шаги, еще что-то. +2651.64 2661.74 SPEAKER_00 То есть оставьте агентс.мд вот чисто в общем для какого-то вашего, для какой-то вашей эпостасии программирования, как, например, на чистом дотнете под все проекты. +2661.74 2671.18 SPEAKER_00 А вот если вам нужно записать какую-то специфику, как работать с этим конкретным проектом, то ее стоит записать в файл readme.md. +2671.18 2694.62 SPEAKER_00 Readme.md – это, в принципе, тоже файл, который давно известен всем, лежит он обычно тоже в корне репозитория, и там расписывается как раз общий контекст о том, зачем этот проект, про что этот проект, какие-нибудь стандарты, которые приняты, стандарты кодирования, которые приняты в этом проекте, как его настроить, как его собрать, задеплоить, затестировать. +2694.62 2710.56 SPEAKER_00 И вот, кстати, автор говорит, что обязательно нужно делать секции, в которых описано, а как, собственно, билдить и тестировать приложение, потому что readme.md – это такой файлик, который агентами ищутся в первую очередь. +2710.56 2723.30 SPEAKER_00 Ну, во вторую, наверное, если говорить после файла агент.md, то readme.md ищутся во вторую очередь, и оттуда черпаются основные данные о том, как вообще общаться с этим проектом и вообще, что это за проект. +2723.30 2735.78 SPEAKER_00 И если вы, допустим, пишете такой readme.md файл, то автор советует вам указать такие базовые вещи, как фреймворк, на основании которого этот проект работает, и как построить проект. +2735.78 2742.10 SPEAKER_00 Например, используя команду .NET Build для того, чтобы собрать проект, используя команду .NET Test для того, чтобы запустить юнит тесты. +2742.10 2757.98 SPEAKER_00 И он советует обязательно добавить, что важной частью процесса является запуск обязательно всех тестов перед тем, как посчитать, что какое-то изменение было сделано окончательно и правильно. +2757.98 2775.30 SPEAKER_00 В общем, потому что по его опыту очень часто агенты или забывали билдить код, или не знали под каким фреймворком его правильно билдить, или использовали некорректный синтаксис, но это как раз и связано с тем, что они использовали неверный фреймворк, или пропускали тесты, или вообще не запускали тесты. +2775.30 2791.34 SPEAKER_00 И вот как раз вот эта фраза, что вам нужно обязательно запустить все тесты и помогает агенту не просто внести изменения, но и после этого сбилдить проект, запустить все тесты и убедиться, что то, что он сделал, более или менее работает. +2791.34 2801.46 SPEAKER_00 Так как вот этот файл readme.md все время находится всеми агентами, агенты пытаются его очень быстро и тщательно проанализировать, рекомендуется держать его небольшим. +2801.46 2804.14 SPEAKER_00 Ну то есть в разумных пределах. +2804.14 2836.38 SPEAKER_00 То есть он должен описывать, как общаться с проектом, как с проектом работать, но если вдруг у вас появляются какие-то такие уже сторонние темы, например, как настроить окружение для того, чтобы работать с этим проектом, как описывается архитектура внутри этого проекта, какая схема данных у той базки, которую вы разворачиваете в рамках этого проекта, то это лучше вынести куда-нибудь отдельно в папочку с документацией и при необходимости просто-напросто добавить ссылки в файл readme.md и в принципе по ссылкам любой читающий пользователь может по ним перейти. +2836.38 2845.10 SPEAKER_00 В принципе при большой необходимости и агент тоже может по этим ссылкам перейти, но в общем случае его главная задача это загрузить и обсмыслить readme файл. +2845.10 2850.50 SPEAKER_00 Поэтому readme должен быть чистым, понятным, сфокусированным и не особо большим. +2850.50 2854.86 SPEAKER_00 Следующий пункт это ворнинги, анализаторы и различные ошибки. +2854.86 2869.22 SPEAKER_00 Здесь есть такое наблюдение, что если в вашем проекте есть куча ворнингов, вы за ними не следите, вы туда добавляете новый код и этот новый код тоже может порождать ворнинги, вам за это ничего не бывает. +2869.22 2878.74 SPEAKER_00 В общем тогда на таких проектах агенты обычно генерят код, в котором тоже бывают ворнинги и агенты в принципе забивают на эти ворнинги и никак за ними не следят. +2878.74 2885.46 SPEAKER_00 То есть чем грязнее ваш код уже существует, тем грязнее код вы получите в результате генерации с помощью агентов. +2885.46 2898.16 SPEAKER_00 Отсюда стандартная рекомендация нашего подкаста это включайте Threat Warnings as Errors и вычищайте все ворнинги, которые у вас есть, потому что просто так компилятор как бы ни о чем не кричит. +2898.16 2900.94 SPEAKER_00 Если он кричит, то для этого есть какие-то причины. +2900.94 2904.52 SPEAKER_00 Обязательно необходимо все эти причины смотреть и обрабатывать. +2904.52 2915.14 SPEAKER_00 Если вы вдруг запускаете агента на проекте без ворнингов, то здесь опять же никаких гарантий нет. +2915.14 2922.14 SPEAKER_00 В основном, конечно, агенты будут вам делать код, в котором ворнингов не содержится, но как показала практика, может быть и по-другому. +2922.14 2925.94 SPEAKER_00 Могут быть и новый код, в котором есть ворнинги. +2925.94 2933.38 SPEAKER_00 Поэтому если вы хотите точную прям гарантию, это флаг компилятора, интерпретируйте все ошибки как ворнинги и все. +2933.38 2941.86 SPEAKER_00 После включения вот этого флага агент пытается сбилдить ваш код, видит какие-то ворнинги и не обязательно их фиксит. +2941.86 2942.86 SPEAKER_00 Дальше никуда не пойдет. +2942.86 2952.34 SPEAKER_00 В общем, ворнинги это хорошо, но это как бы тот базовый минимум гигиены, который должен быть в вашем проекте. +2952.34 2962.06 SPEAKER_00 У вас еще должны быть куча анализаторов, естественно наросленные анализаторы, которые помогают вашему проекту находить уже более специфические, более узкие какие-то ошибки. +2962.06 2966.42 SPEAKER_00 В интернете, на гитхабах огромное количество различных анализаторов. +2966.42 2974.20 SPEAKER_00 Ну, в качестве примера можно привести Microsoft CodeAnalysis NetAnalyzers, это стандартные дотанализаторы, которые как раз поставляются Микрософтом. +2974.20 2981.70 SPEAKER_00 Есть StyleCopAnalyzers, это StyleCop анализаторы, которые переписаны наросленные. +2981.70 2985.58 SPEAKER_00 Очень популярный в свое время была такая лоза как StyleCop. +2985.58 2991.38 SPEAKER_00 Сейчас она немножко сошла на нет, но там есть все еще хорошие анализаторы. +2991.38 3003.30 SPEAKER_00 И может быть для тех людей, которые только начинают писать на C#, которые только привыкают к его синтаксису, это будет один из самых лучших анализаторов, потому что именно он учит правильному синтаксису. +3003.30 3019.14 SPEAKER_00 Надо немножко освежить в памяти, насколько то, что там записано сейчас является правильным синтаксисом, то есть насколько это является best practices, но в свое время это был очень мощный такой анализатор именно по структуре, по синтаксису, по различным скобкам, пробелам, табам. +3019.14 3027.62 SPEAKER_00 Вот этих споров в нормальных компаниях не возникало, потому что там StyleCop, и именно он рассказывал, как вы должны жить. +3027.62 3031.14 SPEAKER_00 Еще один интересный пакет — это Mizantou Analyzers. +3031.14 3042.90 SPEAKER_00 Это, опять же, лучшие практики для анализаторов, собранные автором, одним популярным блогером, который пишет свои статьи под псевдонимом Mizantou. +3042.90 3046.66 SPEAKER_00 В общем, у него там тоже есть довольно интересные, в принципе, если не видели, посмотрите. +3046.66 3052.42 SPEAKER_00 Наверняка у вас есть уже там какие-то свои анализаторы, которые написаны, в общем, их тоже обязательно включать. +3052.42 3065.98 SPEAKER_00 Чем больше у вас там анализаторов, каких-нибудь warning писателей, каких-нибудь чеков, тем лучше, тем вы больше заставите думать агента о том, насколько качественный он пишет код. +3065.98 3073.30 SPEAKER_00 И следующий пункт, тоже немножко про внешнее качество кода — это форматирование. +3073.30 3092.26 SPEAKER_00 Даже если вы сами пишете чистый, красивый, отформатированный код, и при каждом сохранении IDE-шка вам его переформатирует, чтобы было совсем все четенько, то существуют опять же некоторые инструменты, кодогенераторы или опять те же самые AE-агенты, которые генерируют код, и генерируют они его не всегда в приличном формате. +3092.26 3098.78 SPEAKER_00 Иногда просто неверно выставляют там скобки, правилы, ошибки, переносы строк. +3098.78 3117.62 SPEAKER_00 Естественно, компилятор все это пропускает, для него это нормально, валидно, но опять же, если вы держите свой код чистым и красивым, то будущий код, который вы будете генерить на основании вашего старого кода, скорее всего, будет чистым и красивым, поэтому даже то, что сгенерили генераторы или какие-то искусственные интеллекты тоже должно выглядеть красиво. +3117.62 3123.22 SPEAKER_00 Поэтому необходимо как-нибудь обеспечить то, что все у вас выглядит красиво. +3123.22 3142.26 SPEAKER_00 Самым правильным способом для обеспечения красоты является команда .NET-формат, это стандартный утилит от Microsoft, который позволяет отформатировать .NET-код или проверить на то, что он правильно отформатирован просто из командной строки, и обычно она стоит даже в пайплайне билд-агента вашей CI/CD-системы. +3142.26 3147.34 SPEAKER_00 Так вот, ее можно запускать в различные периоды, в различные триггеры. +3147.34 3160.68 SPEAKER_00 Ну, например, можно поставить ее прикоммит-хуком для гита, и тогда, прежде чем закоммитить любое изменение на сервер, у вас будет срабатывать формат, и все изменения будут коммититься только в красивом формате. +3160.68 3169.50 SPEAKER_00 Другим способом есть, то есть, другим способом можно сделать это, добавить кастомный build-степ в директоре build-target. +3169.50 3174.70 SPEAKER_00 Он на MS Build пишется буквально в несколько строчек, смысл точно такой же. +3174.70 3182.78 SPEAKER_00 То есть, перед каждым билдом запустить .NET-формат, который полностью вам сделает код красивым. +3182.78 3187.34 SPEAKER_00 Следующий пункт, с которым у ИИ возникли проблемы, это юзинги, как ни странно. +3187.34 3194.54 SPEAKER_00 То есть, когда он добавляет какие-то классы, какие-то методы, он знает, как их добавлять, как их использовать, какие параметры передавать. +3194.54 3198.96 SPEAKER_00 А вот откуда взялись те или иные классы, он соображает довольно туго. +3198.96 3205.14 SPEAKER_00 Особенно какие-нибудь запутанные классы, не микрософтские может быть даже. +3205.14 3216.22 SPEAKER_00 В общем, и вот эти юзинги, которые необходимо добавить стандартно к каждому файлику, у него неизменно вызывали кучу проблем. +3216.22 3220.98 SPEAKER_00 Поэтому, следующая рекомендация автора, это используйте чаще global юзинги. +3220.98 3236.82 SPEAKER_00 Я напомню, что global юзинг – это файлик, который так и называется обычно, global-using.cs, в котором вы описываете те юзинги, которые будут прозрачно, неявно подключаться ко всем вашим файлам. +3236.82 3247.30 SPEAKER_00 Поэтому, как минимум для всех системных, для всех стандартных намспейсов, вообщем, этот global юзинг является очень даже хорошим выходом. +3247.30 3253.86 SPEAKER_00 Проблема с юзингами состоит не только в том, что агенты должны знать, какой юзинг подключить. +3253.86 3263.82 SPEAKER_00 То есть, когда он добавит вам какой-то класс и не подключит юзинг, то он запустит компиляцию, компиляция сломается и рано или поздно он дойдет до того, какой юзинг подключить. +3263.82 3272.58 SPEAKER_00 А проблема в том, что пока он до этой мысли доходит, он тратит кучу токенов, а токены мы, по идее, должны экономить. +3272.58 3283.66 SPEAKER_00 Поэтому ради экономии токенов, для того, чтобы он не перебирал всевозможные юзинги, которые там у него есть, не перекомпилировал по 100 тысяч раз, вообщем, это хороший выход. +3283.66 3300.06 SPEAKER_00 Тут необходимо помнить, что злоупотреблять global юзингами тоже нельзя, потому что как только у вас в них появятся какие-нибудь два намспейса, внутри которых лежит один класс с одним и тем же именем, у вас автоматически будут ошибки, как бы, по сути, во всех файлах, потому что вы их подключаете во все файлы. +3300.06 3309.34 SPEAKER_00 Поэтому здесь необходимо осторожно добавлять в этот файл юзинги, зная лишь то, что там лежат обычно классы, которые никогда ни с кем не пересекаются. +3309.34 3317.18 SPEAKER_00 Ну, обычно стандартные микрософтовские классы отвечают этим требованиям, поэтому их можно засовывать без особых проблем. +3317.18 3322.82 SPEAKER_00 Следующая рекомендация – это используйте Centralized Package Version Management. +3322.82 3331.02 SPEAKER_00 Опять же, штука довольно относительно старая, то есть во всех проектах она уже включена по умолчанию, все нормальные проекты на нее переведены. +3331.02 3344.54 SPEAKER_00 Это вещь, которая позволяет вам создать файл, который называется Directory Packages Props, и в этом файле объявить версии абсолютно всех пакетов из всех проектов, которые участвуют в вашем солюшене. +3344.54 3355.52 SPEAKER_00 В одном файле, в одном месте, и, соответственно, вы можете контролировать эти проекты, эти версии очень прозрачно и очень наглядно. +3355.52 3362.30 SPEAKER_00 Но самое главное в том, что версии не расходятся между различными проектами, потому что версия задекларирована только в одном месте. +3362.30 3375.50 SPEAKER_00 Поэтому исчезает такой механизм, как консолидация версий между различными проектами, который раньше мог отнимать очень много времени, а в самом плохом случае мог приводить к очень сложно выявляемым багам, которые возникали нам только в рантайме. +3375.50 3382.74 SPEAKER_00 В том случае, когда в виде какой-нибудь зависимости подтаскивается не та версия, на которую вы рассчитывали. +3382.74 3403.90 SPEAKER_00 В общем, этот файл обязателен, он обязательно должен быть, и более того, агенты его отлично умеют читать, отлично умеют понимать, и у них тоже не происходит в их цифровой голове вот это раздвоение, когда мы один класс должны взять из библиотеки с одной версией, а потом тот же самый класс должны взять из библиотеки с другой версии. +3403.90 3414.82 SPEAKER_00 Таких глупостей не происходит, потому что версия библиотеки у вас гарантирована на весь Solution одна, и этот факт тоже помогает очень хорошо ишке не сходить с ума. +3414.82 3422.50 SPEAKER_00 Дальше пойдем и по самым очевидным рекомендациям, это используйте скутер для Dependency Injection. +3422.50 3423.50 SPEAKER_00 Скрутер. +3423.50 3426.34 SPEAKER_00 Давайте по порядочку. +3426.34 3436.16 SPEAKER_00 У нас есть Dependency Injection, то есть у нас есть контейнеры, которых мы обычно регистрируем к сервису перед тем, как начать их использовать. +3436.16 3462.90 SPEAKER_00 Ну так вот, этот стандартный контейнер, который появился в Microsoft Dependency Injection, он в принципе хороший, он в принципе мощный, но он принципиально не хочет в себя внедрять различные методы по сканированию сборок, и поэтому сканирование сборок и всех сервисов, которые существуют, в виде отдельного проекта, ну самый популярный из них это скрутер. +3462.90 3470.94 SPEAKER_00 Скрутер позволяет вам пройтись по всем классам и найти какие-то там классы по каким-то там условиям и зарегистрировать их в контейнере. +3470.94 3505.58 SPEAKER_00 Ну например, у вас есть какая-то сборка, в которой лежит там все сервисы игр, и вы можете сказать на контейнере, который собирает все сервисы, вызвать метод scan, который предоставляет как раз таки скрутер, и в этом методе scan рассказать, что я хочу взять из такой-то сборки все классы, которые находятся в namespace, допустим, в том же самом, в котором лежит game-сервис, зарегистрировать их как self и плюс как все интерфейсы, которые он имплементирует, и указать какой-нибудь scope, допустим, scope lifetime. +3505.58 3526.58 SPEAKER_00 То есть с помощью такого декларативного обхода всей сборки и выявления всех каких-то классов, которые мы хотим зарегистрировать, мы можем просто-напросто забросить за пять строчек все классы, которые есть в сборке, независимо от того, один он там или сто их там, и они у нас уже будут в контейнере. +3526.58 3529.50 SPEAKER_00 Вот, это все, что касается dependency injection. +3529.50 3533.30 SPEAKER_00 Теперь посмотрим, как же это все относится к e-агентам. +3533.30 3547.42 SPEAKER_00 Дело в том, что e-агенты довольно, опять же, хорошо умеют использовать классы, умеют их каким-то образом вызывать, передавать параметры, но у них есть большая проблема с регистрацией. +3547.42 3559.14 SPEAKER_00 Они или не знают, куда надо правильно это регистрировать, потому что у нас нет какого-то понятного одного места, где должны быть зарегистрированы все классы, то есть нет какого-то модуля регистрации или реестра всех сервисов. +3559.14 3570.94 SPEAKER_00 Обычно регистрация может быть разбросана в десятки различных методов и различных экстеншенов, поэтому у e-шки не сложилось четкое понимание, как, кого и куда надо регистрировать. +3570.94 3605.82 SPEAKER_00 И вот с регистрацией у нее есть большие проблемы, и вот чтобы эти проблемы решить, как раз-таки удобно использовать скрутера, потому что независимо от того, где лежит этот класс, скрутер берет на себя полностью его регистрацию, и на обязанности e-шки остается всего лишь на всего создать и правильно его заиспользовать, а все остальное уже сделает сам скрутер, то есть он подхватит все эти классы и добавит их в контейнер с правильным lifetime scope, без необходимости какой-то дополнительной конфигурации. +3605.82 3613.18 SPEAKER_00 Соответственно, мы с e-агента убираем какое-то знание, которому дается плохо, то как регистрировать сервисы. +3613.18 3617.98 SPEAKER_00 Следующая рекомендация – это использовать сингл-файл компоненты. +3617.98 3627.38 SPEAKER_00 Это немножко… здесь пример приводится при Blazor, без Blazor я тоже, наверное, не знаю, какой пример здесь можно привести, поэтому давайте посмотрим на Blazor. +3627.38 3634.94 SPEAKER_00 Опять же, ситуация, что e-агенты плохо справляются с зависимыми файлами, без явного их упоминания. +3634.94 3643.10 SPEAKER_00 Ну, например, существует такой файл, как Blazor-компонент, то есть это UI-ный компонент, который описывается в нескольких файлах. +3643.10 3650.98 SPEAKER_00 В Blazor-компоненте описывается его логика, и этот файл имеет расширение .razor, даже не логика, а разметка. +3650.98 3657.34 SPEAKER_00 Потом у нас есть файл, который называется .razor.cs, и вот там описывается как раз императивная логика. +3657.34 3665.30 SPEAKER_00 И также есть файл, который называется .razor.css, которым, как несложно догадаться, описываются стили для этого компонента. +3665.30 3679.90 SPEAKER_00 Так вот, когда мы просим сделать что-то с компонентом, то Ishka прекрасно понимает, что этот компонент лежит в файле .razor, но она очень плохо понимает, что .razor.cs и .razor.css как-то связаны с этим компонентом. +3679.90 3696.06 SPEAKER_00 Поэтому автор предлагает запихнуть внутрь единого компонента .razor все подряд, и .cs, т.е. и C# код, и логику поведения, и стили, и все в один файлик. +3696.06 3703.54 SPEAKER_00 Рекомендация, наверное, единственная рекомендация из этой статьи, которая выглядит довольно-довольно сомнительной. +3703.54 3707.82 SPEAKER_00 Ну, потому что не зря разделяли эти компоненты на несколько файлов. +3707.82 3712.22 SPEAKER_00 Потому что у них разная ответственность, у них разное нагромождение различных конструкций. +3712.22 3727.06 SPEAKER_00 Если вы запихнете это в один файл, ну, это, безусловно, увеличит размер этого файла, уменьшит читабельность всей этой иерархии, всей этой конструкции, а также, в принципе, она увеличит контекст, который необходимо передавать агенту, что тоже может сказаться не самым лучшим образом. +3727.06 3729.26 SPEAKER_00 В общем, рекомендация такая. +3729.26 3734.22 SPEAKER_00 Это, конечно, выход, но не самый прекрасный из всех ситуаций. +3734.22 3739.82 SPEAKER_00 Поэтому вам нужно конкретно задуматься о том, хотите ли вы пойти по этой дорожке или нет. +3739.82 3749.38 SPEAKER_00 Следующая рекомендация - это давайте дополнительный контекст для специфичных зон, которые есть в вашем проекте. +3749.38 3754.06 SPEAKER_00 Довольно муторно без примеров, сейчас все с вами подсветим, все с вами выясним. +3754.06 3765.78 SPEAKER_00 У различных тулзов, такие, например, как курсор, допустим, есть специальные конфиги, специальные настройки, которые позволяют вам сделать настройки под конкретную зону какую-то. +3765.78 3777.12 SPEAKER_00 Например, для конкретной сборки или для конкретных типов файлов или задать какой-нибудь шаблон, под который, если эти файлы попадут, то к ним применятся данные правила. +3777.12 3779.06 SPEAKER_00 Например, как это можно применять? +3779.06 3784.78 SPEAKER_00 Можно сказать, что все, что лежит в папочке тесты - tests - это являются моими тестами. +3784.78 3787.22 SPEAKER_00 То есть у нас здесь появляется как раз шаблон. +3787.22 3789.54 SPEAKER_00 Что такое мои тесты? +3789.54 3796.62 SPEAKER_00 Раз это мои тесты, значит, они должны следовать шаблону проектирования, который называется Arrange Act Assert. +3796.62 3806.26 SPEAKER_00 Они должны использовать shodly для проверки условий, и они должны использовать, допустим, inline data, где это только возможно, для передачи параметров в тест. +3806.26 3823.18 SPEAKER_00 То есть вот такие вот конкретные какие-то специфику мы определили только для папочки тестов, потому что есть такие разделения, есть такие области, в которых код отличается от других частей, других участков кода. +3823.18 3833.54 SPEAKER_00 Например, мы нигде не пишем комментарии Arrange Act Assert внутри бизнес-логики, допустим, или внутри UIKey, а вот в тестах обычно его пишут. +3833.54 3839.34 SPEAKER_00 Поэтому весь код ровнее, весь код ровный, но некоторые ровнее. +3839.34 3858.70 SPEAKER_00 Еще из примеров у нас, например, есть Entity Framework, мы точно также можем его обеспечить, то есть задетектировать в виде паттерн-матчинга и, например, рассказать, как внутри этой папки, внутри этого проекта с Entity Framework работать, допустим, с миграциями, потому что если мы в обычной бизнес-логике добавляем поле, там никаких проблем не бывает. +3858.70 3871.24 SPEAKER_00 Если мы, допустим, добавляем поле в неком рекорде, который идет в базу данных, то там этого маловато, нам нужно там добавить еще миграцию EF-Core-овскую, и для этого тоже, соответственно, подходят инструкции. +3871.24 3875.74 SPEAKER_00 Еще один пример, это, например, наши веб-контроллеры. +3875.74 3879.66 SPEAKER_00 У веб-контроллеров тоже много специфик, которыми вы, может быть, даже с первого раза не задумывались. +3879.66 3894.22 SPEAKER_00 Это то, каким образом оформлять документацию, потому что она вся уйдет в свайдер, и там ее будут читать, это как раз-таки довольно важно, потому что там ее читают в основном не те люди, которые, допустим, читают документацию из бизнес-домена нашего. +3894.22 3905.90 SPEAKER_00 Там есть специфика обработки ошибок, там есть специфика аутентификации, rate-лимитинга, те road-патхы, которые мы выставляем и по которым будут доступны наши API, допустим. +3905.90 3911.06 SPEAKER_00 В общем, веб-проекты с API-контроллерами, с веб-контроллерами тоже должны исследовать ряду правил. +3911.06 3923.78 SPEAKER_00 И вот эти правила тоже очень хорошо обозначать, очень хорошо вот так вот декларировать с помощью вот этих зон, вот этих зон, которые поддерживаются различными UI-инструментами. +3923.78 3927.98 SPEAKER_00 Поэтому ими тоже, этими зонами нужно активно пользоваться. +3927.98 3928.98 SPEAKER_00 Пойдемте ближе к коду. +3928.98 3934.50 SPEAKER_00 Рекомендация – используйте VAR вместо явных типов. +3934.50 3940.18 SPEAKER_00 И тоже, может быть, с первого раза неочевидная, неочевидная проблема. +3940.18 3947.46 SPEAKER_00 Идет она из того, что агенты довольно плохо в некоторых ситуациях выводят типы. +3947.46 3961.62 SPEAKER_00 Особенно, когда тип нужно вывести не просто там из конструктора или из какого-то конкретного метода, а когда вот целая цепочка методов, там идет какую-нибудь линку, допустим, или какая-то другая цепочка, где тип не так очевиден, как вам кажется. +3961.62 3963.54 SPEAKER_00 У агентов тоже с этим проблемы. +3963.54 3966.86 SPEAKER_00 У людей тем более проблемы, если они будут смотреть на эту большую цепочку. +3966.86 3967.86 SPEAKER_00 У агентов тоже проблемы. +3967.86 3977.62 SPEAKER_00 Поэтому им сложно выводить тип, и если вы сделаете VAR переменную, то тип уже будет выводить компилятор. +3977.62 3981.02 SPEAKER_00 А компилятор уже точно знает, как это делается. +3981.02 3990.22 SPEAKER_00 Снова рекомендация из того, что у агента получается какая-то часть плохо, давайте ее заменим на специализированный инструмент, в данном случае на компилятор, и все будет хорошо. +3990.22 4001.86 SPEAKER_00 Не используйте VAR, поменьше используйте явных типов, и в том случае, когда это возможно, когда это не противоречит вашим практикам, VAR — самый лучший вариант. +4001.86 4007.58 SPEAKER_00 Дальше, что еще нам можно использовать из C# синтаксиса? +4007.58 4012.34 SPEAKER_00 Это required keyword, in nullability. +4012.34 4029.62 SPEAKER_00 Напомню кратко, что мы можем объявлять свойства с недавнего времени, свойства у объекта, добавляя к нему специальное ключевое слово, которое называется required, и оно якобы нам говорит, что объект должен быть проинициализирован, то есть это свойство должно быть проставлено в тот момент, когда объект создается. +4029.62 4043.70 SPEAKER_00 И агент прекрасно понимает это синтаксис, прекрасно понимает эту семантику, если мы пометим таким образом required специальные свойства, то он постарается их заполнить, он постарается откуда-то это значение взять. +4043.70 4048.46 SPEAKER_00 Ну и если это действительно подходит к нам по бизнес-логике, это хорошо. +4048.46 4049.46 SPEAKER_00 Также nullability. +4049.46 4060.78 SPEAKER_00 Nullability - это великолепный инструмент, который дает больше информации о типе, больше информации об аргументах тому же самому агенту. +4060.78 4077.50 SPEAKER_00 Раз у агента получается больше информации, значит он умеет с этими объектами лучше обращаться, то есть он знает, кого там надо проверять на null, кого не надо проверять на null, он знает, какие параметры куда передавать, в общем, вы даете ему больше контекста, больше информации и от этого он пишет более правильный код, более богатый и более интересный. +4077.50 4080.90 SPEAKER_00 Поэтому nullability должно быть по дефолту в любых новых проектах. +4080.90 4094.46 SPEAKER_00 В проектах это вообще даже не обсуждается, и чем больше вы будете такой информации сообщать, может ли объект быть null или нет, и в каких условиях и когда, тем чище и красивее иишка вам пишет код. +4094.46 4100.42 SPEAKER_00 Еще одно интересное слово, которое, может быть, и так часто используется, а должно бы, это div. +4100.42 4110.36 SPEAKER_00 У нас есть рекорды, и ключевое слово div помогает создать полный клон этого рекорда за исключением нескольких полей. +4110.36 4125.74 SPEAKER_00 Допустим, если в вашем рекорде 10 полей, а вы хотите всего лишь на все поменять одно, ну так как рекорды они иммьютабельные, и в них нельзя менять поля, и для того, чтобы поменять одно поле, вам нужно склонировать, по сути, предыдущий рекорд и изменить всего лишь на все одно польце. +4125.74 4126.74 SPEAKER_00 Вот. +4126.74 4131.62 SPEAKER_00 Если вы начнете делать это ручками, то синтексис получится довольно громоздким и некрасивым. +4131.62 4134.38 SPEAKER_00 Именно поэтому существует ключевое слово div. +4134.38 4141.98 SPEAKER_00 С помощью этого слова вы можете склонировать рекорд и поменять только те поля, которые нужны, там 1, 2, 3 поля. +4141.98 4144.18 SPEAKER_00 Что, соответственно, довольно удобно. +4144.18 4145.70 SPEAKER_00 Чем это грозит агенту? +4145.70 4151.54 SPEAKER_00 Как раз тем же самым, что агент может сосредоточиться на конкретно одном изменяемом поле. +4151.54 4158.18 SPEAKER_00 То есть весь смысл операции, который он сейчас пытается представить и пытается сделать, он будет отражен в этом одном поле. +4158.18 4176.22 SPEAKER_00 А если бы мы к этому одному полю прибавили бы еще копирование каких-то непонятных десяток полей, которые никакого отношения к нашему бизнес-процессу не имеют, то вот этот десяток полей бы засорил, грубо говоря, на весь флоу обдумывания у агента, и он бы здесь начал больше делать ошибок. +4176.22 4183.34 SPEAKER_00 Он бы начал больше сбиваться, потому что он бы начал считать, что эти 10 полей каким-то образом относятся к моему бизнес-процессу, поэтому я их должен как-то учесть. +4183.34 4192.62 SPEAKER_00 В общем, а если мы их просто скипаем и показываем только то поле, которое нужно поменять, то у агента более чистый контекст и он четче и лучше понимает, что нужно делать. +4192.62 4212.46 SPEAKER_00 Вот здесь мы как раз и приходим к тому, что чем более чистый и чем более понятный, чем более говорящий код вы пишете, тем намного легче его читать, и как оказалось читать не только людям, но и агентам, поэтому придерживайтесь правил правильного чистого читабельного красивого кода, и он вас не подведет. +4212.46 4216.30 SPEAKER_00 Следующая рекомендация это использование мапперли. +4216.30 4234.74 SPEAKER_00 Мапперли это, можно сказать, аналог автомаппера, более известного в народе, и этот аналог позволяет вам сделать практически все то же самое, то есть взять вашу сущность какую-то и смапить ее в ДТОшку, а эту ДТОшку потом можно отдать в какой-нибудь веб-контроллер и она куда-нибудь улетит. +4234.74 4237.36 SPEAKER_00 И с минимальными какими-то трудностями. +4237.36 4262.82 SPEAKER_00 Допустим, у вас есть сущность, у которой там 10 полей, и у ДТОшки 10 полей, вы можете эти 10 полей написать руками, перечислив их, а можете отдать это в специальный сорс-генератор, который называется мапперли, и он сам вам сгенерит все вот эти строчки, с помощью которых вы перекладываете одно значение в поле в другое значение поля, что позволяет сделать код более чистым, но может быть не таким явным. +4262.82 4269.86 SPEAKER_00 В мапперли какая еще интересная штука, в автоматической валидации. +4269.86 4286.10 SPEAKER_00 Как только вы добавите какое-то поле внутрь вашей сущности, и при этом этого поля не будет в ДТОшке, то мапперли выдаст вам ворнинг, он спросит, вы поле пропустили сознательно или по глупости человеческой. +4286.10 4292.26 SPEAKER_00 Если по глупости, вы можете его добавить, если сознательно, вы можете его явно проигнорировать, и тогда он перестанет ругаться. +4292.26 4294.50 SPEAKER_00 В общем, таким образом он создает маппинги. +4294.50 4298.90 SPEAKER_00 В отличие от автомаппера, мапперли работает на сорс-генераторах. +4298.90 4307.98 SPEAKER_00 То есть там никакого рефлекшена нет, это работает быстро, красиво, и вы плюс можете зайти туда внутрь и посмотреть, что он там вам нагенерил, то есть как выглядит сам сгенерированный код. +4307.98 4309.74 SPEAKER_00 В общем, что довольно-таки удобно. +4309.74 4318.22 SPEAKER_00 Агентам это позволяет, опять же, с нескольких сторон облегчить жизнь. +4318.22 4330.58 SPEAKER_00 Во-первых, агенты не должны помнить, что при добавлении нового поля в ваш бизнес-объект, нужно пойти в какое-то другое место и там не забыть это поле переложить в ДТОшку. +4330.58 4342.58 SPEAKER_00 Ситуация немножко похожа с тем, что мы разбирали с вами с контейнерами, то есть в контейнерах агент должен был не забыть пойти куда-то в реестр и там зарегистрировать сервис. +4342.58 4347.10 SPEAKER_00 Вот это тоже код, который оторван от самого объекта, с которым сейчас работает агент. +4347.10 4349.22 SPEAKER_00 Вот с маппингом та же самая ситуация. +4349.22 4354.86 SPEAKER_00 У нас код, по сути, оторван маппинга, оторван от самого объекта. +4354.86 4356.98 SPEAKER_00 В общем, и из-за этого возникают трудности. +4356.98 4368.06 SPEAKER_00 И плюс еще мапперли выдает ворнинги, когда ты забыл перемапить, поэтому агент, в принципе, по этому ворнингу может примерно смолчать, что он что-то забыл, и пойти каким-то образом исправиться. +4368.06 4377.38 SPEAKER_00 Следующая рекомендация – используйте ручные моки вместо моканых фреймворков, то есть фреймворков для мокирования. +4377.38 4380.98 SPEAKER_00 Очень, наверное, неочевидный вывод. +4380.98 4383.02 SPEAKER_00 Давайте же посмотрим, как автор к нему пришел. +4383.02 4398.10 SPEAKER_00 Ну, пришел он на самом деле довольно просто, потому что, когда вы начинаете сетапить мок фреймворк, то же самое моку или другие, то там всегда используется довольно чужеродный синтаксис. +4398.10 4406.18 SPEAKER_00 И вот с этим чужеродным синтаксисом, особенно когда сетапится какая-нибудь сложная логика, у ИИшки очень большие проблемы. +4406.18 4410.18 SPEAKER_00 Ну, наверное, потому что, опять же, нет спецификации на такой синтаксис. +4410.18 4411.18 SPEAKER_00 Ну, как нет? +4411.18 4416.72 SPEAKER_00 Она не так распространена, допустим, как спецификация на сам C# язык, допустим. +4416.72 4426.14 SPEAKER_00 Не так распространена спецификация, может быть, не так много кода или еще какие-то проблемы, но автор говорит, что не нашел мок фреймворка, который хорошо работает с ИИшкой. +4426.14 4427.74 SPEAKER_00 У них у всех проблемы. +4427.74 4436.86 SPEAKER_00 Они даже похожие сетапы делают, а эти сетапы даже хорошо компилируются, но в рантайме выдают и работают абсолютно не так, как вы рассчитываете. +4436.86 4439.90 SPEAKER_00 То есть симулировать моки у него почему-то не получается. +4439.90 4460.46 SPEAKER_00 Вот он мучился-мучился, искал-искал какие-то фреймворки, а потом попробовал написать моку вручную, и мок вручную довольно хорошо распознался агентам, хорошо написался и хорошо внедрился во все тесты, потому что, опять же, он пишется на синтаксе C#, а C# агенты знают великолепно. +4460.46 4466.38 SPEAKER_00 И вот он пришел к выводу, что, в принципе, не надо юзать мокнутые фреймворки, они больше никому не нужны. +4466.38 4471.62 SPEAKER_00 Ну, действительно, если мы задумаемся, какие причины у нас в том, что мы юзаем фреймворки для мока. +4471.62 4481.74 SPEAKER_00 Прежде всего, причина - это сохранить время разработчика на то, чтобы сделать какие-то интерфейсы, реализовать какие-то заглушки в методах, допустим. +4481.74 4490.00 SPEAKER_00 В общем, сделать какой-то мок, сделать какой-то тестовый дубль для того, чтобы его потом использовать в ваших тестах. +4490.00 4491.30 SPEAKER_00 Мы просто-напросто экономили время. +4491.30 4501.68 SPEAKER_00 Но так, сегодня, когда мы говорим про яичные инструменты, которые участвуют в разработке наших продуктов, у нас нет такой проблемы. +4501.68 4507.76 SPEAKER_00 Нам не нужно экономить время на том, чтобы реализовать, допустим, какой-то интерфейс с моками. +4507.76 4535.84 SPEAKER_00 Мы просто нам говорим о яичке, вот тебе интерфейс сервиса, сделай для него какие-то моки, и у вас ровно через секунду появятся вот эти моки, которые будут написаны на нормальном языке, без всяких хитровыдуманных синтаксисов, которые будут понятны любой яичке, которые будут хорошо тестировать и которые их можно будет изменить очень гибко под ваши тесты, потому что они будут конкретно в вашем коде. +4535.84 4546.92 SPEAKER_00 Поэтому автор приходит к выводу, что в принципе мок фреймворки больше не нужны, и все те функции, которые раньше они выполняли, вполне можно сделать на яичке довольно быстро, хорошо и понятно. +4546.92 4549.08 SPEAKER_00 Теперь перейдем к именованию. +4549.08 4556.80 SPEAKER_00 Естественно, если мы говорим про красивый качественный хоккод, про чистую красивую архитектуру, как мы можем обойти именование. +4556.80 4564.04 SPEAKER_00 Именование наше все, поэтому для яички именование тоже имеет очень высокий вес. +4564.04 4575.24 SPEAKER_00 Ну, например, переменная, которая называется "Approved email addresses", она намного чище и понятнее, чем если бы вы назвали эту переменную просто "Approved list" или если вы переменную назвали просто "Approved". +4575.24 4579.34 SPEAKER_00 Не очень понятно, кто там "Approved", что там лежит и так далее. +4579.34 4580.34 SPEAKER_00 Особенно, если у вас там вар стоит. +4581.10 4598.18 SPEAKER_00 Так вот, осмысленные переменные, которые требуют большевики с самого начала C#, здесь играют огромную роль, потому что яичка воспринимает переменные не просто как названия переменных, не просто как какие-то заголовки или названия. +4598.18 4612.94 SPEAKER_00 Она реально спаршивает из них бизнес-смысл, то есть она реально пытается их внедрить в тот контекст, где она выполняет этот процесс и пытается понять, а каким образом эти переменные должны в этом контексте взаимодействовать, что они должны делать, каким образом они там участвуют. +4612.94 4619.66 SPEAKER_00 Таким образом у нас получается полноценный бизнес-процесс. +4619.66 4627.78 SPEAKER_00 У нас есть метод, который декларирует процесс, у нас есть переменные, которые есть участники этого процесса и у нас есть какой-то workflow из операторов, который этот процесс реализует. +4627.78 4637.50 SPEAKER_00 И яичка – это такой жонглер данным процессом и чем лучше вы назовете всех участников системы, тем лучше она будет жонглировать этим процессом. +4637.50 4640.90 SPEAKER_00 Что еще можно использовать для повышения бизнес-контекста? +4640.90 4655.42 SPEAKER_00 Это комментарии, то есть если у вас какой-то сложный процесс происходит, то высокоуровневый комментарий оставить, что здесь происходит проводка товара и там уже можно расписывать детальнее, что собственно обозначает проводка товара. +4655.42 4660.58 SPEAKER_00 Это тоже яичке очень сильно помогает бизнес-контекст получить и правильно обработать. +4660.58 4667.90 SPEAKER_00 Теперь же помните, что яичка в основном отлично работает с бизнес-контекстом, поэтому чем больше и глубже вы ее туда погрузите, тем лучше. +4667.90 4683.14 SPEAKER_00 Другие способы можно упомянуть, вспомнить, которые помогают нам бизнес-контекст обозначить – это именование не только переменных, но именование классов, именование методов, в общем именование всей этой иерархии, в которой мы сейчас находимся. +4683.14 4695.26 SPEAKER_00 Также немаловажным элементом бизнес-контекста являются value-тайпы, e-mail адреса, допустим, фон-намберы, они не должны являться просто стрингами и строчками. +4695.26 4712.02 SPEAKER_00 Опять же, как только мы добавляем больше информации о типе, когда мы говорим, что эта строчка – это не просто стринг или нулябельный стринг, а эта строчка обозначает фон-намбер, то яичка начинает уже работать как с телефонным номером с этой переменной, а не просто со строкой. +4712.02 4721.14 SPEAKER_00 И у нее появляется дополнительный контекст, у нее появляются дополнительные знания, дополнительные именования в рамках домена телефонных номеров, в общем она это все подхватывает. +4721.14 4745.70 SPEAKER_00 Поэтому вот эти наши primitive obsessions, нейминги, выделение логики в отдельные методы, вот эти все best practices, они снова актуальны, снова в жизни, поэтому если кто-то думал, что он избавится от знаний о best practice дизайн-паттернах и будет программировать счастливо, то нет, дизайн-паттерны снова в моде. +4745.70 4758.58 SPEAKER_00 И последний пункт, рекомендация, который опять же довольно не очевиден, но прекрасен, это именование приватных полей внутри класса. +4758.58 4825.06 SPEAKER_00 Я напомню, что у нас существует старый подход, именование полей это когда мы перед приватным полем ставим подчеркивание, автор его тонко называет LegacyJunk Prefix, то есть такой мусорный устаревший префикс в виде подчеркивания, он пришел к нам из как мохнатых сей, плюсов и вот оттуда, в общем почему-то народ его очень сильно тащит и держится, хотя в самых первых рекомендациях C# было именно не использовать ни в коем случае никаких префиксов для приватных полей и других полей, в общем, так называем венгерскую нотацию, если допустим S подчеркивание, там имя селда у нас уже как-то отвалилось, редко кто использует для статических свойств, может быть только команда .NET и все, другие тоже, венгерские вот эти нотации тоже у нас отвалились, то вот этот последний эрудимент в виде подчеркивания приватных филдов во многих компаниях все еще держится. +4825.06 4831.42 SPEAKER_00 И вот против него выступает Ишка, давайте разберемся почему. +4831.42 4854.74 SPEAKER_00 Дело заключается в том, как токенизируется имя переменной, то есть, допустим, представим, у нас есть опять же приватный филд и называется он там подчеркивание name и второй приватный филд, который называется просто name, два варианта, каким образом происходит токенизация? +4854.74 4960.30 SPEAKER_00 Если мы посмотрим внимательно на то, каким образом C# код разбирается на уровне токенов, а токены это обычно такой семантический минимальный элемент, можно сказать в общем случае, что это слова, но обычно он бывает даже меньше или даже больше, чем слово, например, может быть, слово вместе с запятой или с оператором, а может быть, если часто изменяется там окончание или приставки, это будет какая-то часть слова, в общем, токен это семантически значимая для нейроночки какая-то часть. Так вот, если мы посмотрим на то, как разбирается имя нашего филда на базе токенов, то мы увидим, что то имя филда, которое начинается с подчеркивания разбивается на два токена. Первый токен это подчеркивание, а остальная часть это имя переменной. Если же мы возьмем тот филд, который не имеет подчеркивания, то у него получается один красивый, приятный, классный токен. Вот этот излишний токен с подчеркиванием, естественно, никуда не создается, его нет. И здесь важно заметить, что каждый токен, каждая операция над токеном, они по сути независимые. То есть, с точки зрения семантики, с точки зрения иишки, подчеркивание и имя переменной - это два независимых токена. То есть, по факту, они, грубо говоря, в ее менталитете могут ходить порознь, то есть они никак не соединены. Ну просто она видит, что в коде они часто используются вместе. Ну ладно, она тогда тоже их часто использует вместе. Но в общем случае они для нее совсем независимые вещи, то есть она их вполне разделяет. И более того, с каждым запросом, который возвращает, который код генерируется, вы по сути вместо одного токена используете для генерации два токена. +4960.30 4979.06 SPEAKER_00 То есть, по сути, вы в два раза быстрее транжирите свой лимит токенов. Ну так вот, для того, чтобы уменьшить расход токенов и для того, чтобы улучшить читабельность и понимаемость кода, то есть чтобы ишка понимала какой код один и тот же. В общем, как он сравнивается. +4979.06 5009.14 SPEAKER_00 Рекомендуется избавиться от этого исторические легеси наследования и прекратить писать префиксы в приватных филдах. Вот такая хорошая, интересная, жирная точка в этой статье. Ну а в общем, если подводить итоги, то итог, наверное, можно все-таки выразить той фразой, которую я уже упоминал, что если вы пишете хороший, красивый, понятный код для человека, то и для ишки этот код будет прекрасным, читабельным и хорошим. Поэтому пишите код для людей и ишки тоже к вам подтянутся. +5009.14 5044.42 SPEAKER_00 Все так, все так. Ну а также смотрите, как ишка реагирует на ваш продукт, если вы используете на ваш код и наверняка увидите какие-то собственные паттерны, как правильнее, как лучше и что дописать в какой-нибудь Redmi или Legends, чтобы стало хорошо. Тут надо экспериментировать, смотреть и понимать, что как происходит. Так, ну что, у нас осталась небольшая темка про новые докладики SPB, даже не SPB.dotnet, а dotnet.ru. +5044.42 5116.98 SPEAKER_00 Действительно, как вы, наверное, слышали в одном из наших предыдущих анонсов, мы делаем митапы, это вы, наверное, слышали во многих наших предыдущих анонсах, в одном из недалеких мы рассказали, что у нас открылся новый филиал dotnet.ru, который находится в славном городе Героя Севастополя и оттуда к нам уже идут пачками доклады, уже было проведено три митапа и вот с последнего третьего митапа у нас готовы записи, поэтому если вы вдруг хотите посмотреть, присоединиться, то, возможно, вам будет интересно. А именно, сухорукий Кирилл рассказал нам про монады в C# и элементы теории категорий. Ну, хорошая тема, мы тоже несколько раз делали подход к этому снаряду, всегда интересно поговорить, интересно поломать мозг, но, опять же, не торопитесь тащить это впрот, а лучше вот послушайте, посмотрите профессионалов, насколько у них с этим хорошо дела. Мжачев Илья рассказал про Postgres partitioning, как управлять данными и про тонкости производительности .NET вместе с Entity Framework. Partitioning, как это по-русски будет? Партиционирование? +5116.98 5136.78 SPEAKER_00 Да, партиционирование. Ну, допустим. В общем, партиционирование – это хороший способ разделения, управления даже нагрузкой, перформансом и необходимо знать, как он работает, необходимо знать, что с ним можно делать и на примере больших компаний, конечно же, лучше это все узнавать. +5136.78 5149.78 SPEAKER_00 Ну и в Питере у нас проводятся регулярные митапы и доступ на парочку интересных докладов. Первый – это Хетек Ситиропла, который рассказал нам про Web3 для самых маленьких. +5149.78 5162.58 SPEAKER_00 Он там затронул огромное количество различных технологий, интересных распределенных файловых систем, тот же самый блокчейн и куча-куча всего другого, что можно построить на базе распределенных идей, технологий, алгоритмов. +5162.58 5199.22 SPEAKER_00 В общем, если вы никогда не сталкивались, то посмотрите, хорошо расширяется знание. И Светлана Мелешкина рассказала нам о том, а как же она в своей компании готовит код-ревью с помощью искусственного интеллекта, как он ей помогает, какие советы дает, как она научилась с ним управляться и какие практические хаки выдумала для того, чтобы работа у нее шла быстрее и интереснее. В общем, такие интересные докладики. Может быть, к тому моменту, когда этот выпуск выложится, еще несколько появится, поэтому заходите на наш канальчик dotnet.ru и посмотрите, какие там классные, веселые и крутые доклады бывают. +5199.22 5215.46 SPEAKER_00 Все так, а на сегодня будем заканчивать. Дело близится к Рождеству, статей маловато. Надеемся, что после Нового года прям попрет-попрет и будет много всяких разных новостей. Когда у нас там первый превью? Дотнет ожидается. +5215.46 5221.50 SPEAKER_00 Слушай, ну у нас, получается, последний выпуск в этом году, да? Можно поздравить всех с наступающим. +5221.50 5236.96 SPEAKER_00 Да, можно поздравить с наступающим, с The Legion последним десятым и юбилейным в каком-то смысле дотнетом. Будем ждать большого количества интересных статей в Новом наступающем году. +5236.96 5244.14 SPEAKER_00 Будем ждать новых крутых фич. Посмотрим, что нового наконец-таки, может быть, добавят в C# большого интересного. +5244.14 5268.06 SPEAKER_00 Да, это, скорее всего, не один год придется ждать, но мы подождем, нам не привыкать. У вас, друзья, всех с наступающим Новым годом, хороших апельсинок, подарков, друзей вокруг и всего наилучшего. Слушайте обязательно наш подкаст и также советуйте его друзьям. Да, до новых встреч в следующем году. Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-129.txt b/input/Radio/Transcriptions/RadioDotNet-129.txt new file mode 100644 index 0000000..77e25fe --- /dev/null +++ b/input/Radio/Transcriptions/RadioDotNet-129.txt @@ -0,0 +1,539 @@ +0.00 14.00 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Radio.net и в студии его постоянный ведущий Анатолий Кулаков и Игорь +÷÷14.00 15.00 "Игорь Лабутин" Лабутин. +15.00 16.00 "Анатолий Кулаков" Всем привет. +16.00 21.44 "Анатолий Кулаков" Выпуск 129, я не помню, сказал или нет, но в общем, в принципе, да, уже какие-то круглые цифры пошли там. +21.44 53.88 "Анатолий Кулаков" В общем, до такого выпуска мы дошли не просто так, потому что нам помогали наши любимые помогаторы – Александр, Сергей, Владислав, Гурий Самарин, Александр Лапердин, Виктор, Руслан Артамонов, Сергей Бензенко, Шевченко Антон, Ольга, Эспрессо, Макиято, Перфаворы, Бондаренко, Сергей Краснов, Константин Ушаков, Постарнаков Андрей, Дмитрий Сорокин, Дмитрий Павлов, Александр Ерыгин, Егор Сычев, Гольдебаев Александр, Лазарев Илья, Тимофей, Виталий, Анатолий Крыжановский, Александр Гаранин, Евгений Асташев, Юрий Лодейкин, Котков Михаил и Михаил Королев. +53.88 56.20 "Анатолий Кулаков" Спасибо всем, друзья, спасибо, кто нас поддерживает. +56.20 63.84 "Анатолий Кулаков" И если вы вдруг ещё не в этом списке, то заходите на Boosty и смотрите, что там есть интересного. +63.84 82.16 "Игорь Лабутин" Интеграция с внешними провайдерами данных есть во многих продуктах, но в Altenar, чтобы написать хорошую интеграцию, профильные дотнет-команды нужно не только разбираться в сетевых протоколах, но и понимать правила различных видов спорта, причём не только таких популярных, как футбол, но и более экзотичных, на вроде бейсбола или кёрлинга. +82.16 84.20 "Игорь Лабутин" Возникает вопрос, зачем? +84.20 91.58 "Игорь Лабутин" Задумывались ли вы, как информация о забитом голе моментально разлетается по всему миру, начиная с партийных трансляций и заканчивая официальными сайтами? +91.58 97.96 "Игорь Лабутин" На стадионе находится скаут, который регистрирует события в планшете и посылает сигналы в информационную систему компаний и провайдера данных. +97.96 110.76 "Игорь Лабутин" Таких компаний-скаутов много, именно с ними интегрируются ребята из Altenar, чтобы максимально быстро получать информацию о матчах с места событий, а чтобы наиболее точно понимать, какое событие принял скаут и не перепутать гол с угловым, изучают правила различных видов спорта. +110.76 114.00 "Игорь Лабутин" Таких интеграций у ребят уже десятки, и их количество постоянно растет. +114.00 123.28 "Игорь Лабутин" Чтобы оптимизировать процесс разработки, снизить количество копипасты и boilerplate, ребята пробуют разные подходы, о которых готовят доклад, который я надеюсь мы скоро услышим или увидим где-нибудь. +123.28 137.36 "Анатолий Кулаков" Ну что ж, Microsoft нас в принципе новостями не сильно радует, но зато мы собрали много других и интересных статейчик, о которых мы сегодня, о некоторых из них мы сегодня и поговорим. +137.36 143.16 "Анатолий Кулаков" В частности, хотелось бы начать с прекрасной новости, что нас, наконец, ждет новая IDE. +143.16 146.80 "Анатолий Кулаков" В общем, не было, не было у нас очень долго. +146.80 154.84 "Анатолий Кулаков" Много десяток лет мы жили с Visual Studio, с Rider, потом какой-то VSCode попытался как-то в нашу дотнетную инфраструктуру вмешаться. +154.84 165.60 "Анатолий Кулаков" Но все это какие-то уже относительно старперские какие-то веяния, а вот, наконец, появилась новая, новая IDE, никак не связанная ни с кем, и называется она Sharp IDE. +165.60 170.00 "Анатолий Кулаков" Это современная кроссплатформенная open-source IDE для дотнета. +170.00 176.64 "Анатолий Кулаков" Построена она на базе dotnet 10 и самая примечательная Godota, то есть на базе Godot. +176.64 184.88 "Анатолий Кулаков" На GitHub'е нужно собирало больше 3000 звездочек, ну то есть такой довольно мощный проект залетел. +184.88 188.56 "Анатолий Кулаков" И чем он выделяется? +188.56 191.04 "Анатолий Кулаков" Ну, как я уже отметил, выделяется он Godot'ом. +191.04 194.44 "Анатолий Кулаков" Если кто не знает, Godot - это игровой движок, на котором обычно пишут игры. +194.44 200.20 "Анатолий Кулаков" Действительно, где у нас UI-ные интерфейсы и игры, они там, в общем, недалеко. +200.20 218.48 "Анатолий Кулаков" Казалось бы, зачем нам использовать различные вот эти нативные контроллы с нашей операционной системой, если у нас уже есть хорошая какая-нибудь GPU-шная библиотека, которая умеет отрисовывать прекрасные шрифты со всякими альязингами, даже трехмерностью, тенями и прочими игровыми безобразиями. +218.48 220.72 "Анатолий Кулаков" И вот на базе этого можно построить IDE. +220.72 225.36 "Анатолий Кулаков" Вот, кажется, ребята и решили сделать IDE и посмотреть, что из этого получится. +225.36 231.96 "Анатолий Кулаков" Что получится, в принципе, каждый из вас может посмотреть, потому что можно зайти на GitHub и там прям скриншотики красивенькие будут. +231.96 235.40 "Анатолий Кулаков" Что хочется отметить, вот сразу глядя на эти скриншоты? +235.40 238.24 "Анатолий Кулаков" Ну, во-первых, это такой здоровый, красивый минимализм. +238.24 242.68 "Анатолий Кулаков" Как, в принципе, сейчас модно, как сейчас принято, как сейчас выпускается. +242.68 251.76 "Анатолий Кулаков" Прям хорошо, без лишних излишеств, шрифты хорошие, сглаженные, темы подсвечиваются, синтексис есть, все нужные кнопки на месте. +251.76 266.32 "Анатолий Кулаков" Но, безусловно, нет всей этой развесистости и всего того функционала, который есть у нас, конечно же, в больших Visual Studio, в Ryder и в Visual Studio Code с ее многочисленными плагинами. +266.32 287.00 "Анатолий Кулаков" Но, скорее всего, по функциональности она не будет сильно отступать от Visual Studio Code, потому что, опять же, скорее всего, юзает тот же самый LSP, который дает подсветку синтексиса и IntelliSense, и тут функциональность будет та же самая, как и у остальных IDE-шек, у остальных блокнотиков C#. +287.00 294.92 "Анатолий Кулаков" Но эта IDE-шка, она все-таки хочет стать чем-то большим, чем блокнотик, и, судя по амбициям автора, у нее есть все шансы. +294.92 296.88 "Анатолий Кулаков" В общем, что она умеет? +296.88 298.64 "Анатолий Кулаков" Давайте пробежимся все-таки коротенько. +298.64 301.80 "Анатолий Кулаков" Во-первых, как я уже сказал, есть у нее нормальный код completion. +301.80 308.84 "Анатолий Кулаков" Код completion, который подсказывает различные методы, свойства, в общем, как и положено, все, что мы ждем. +308.84 326.56 "Анатолий Кулаков" Есть у нее хороший синтексис-хайлайтинг, то есть со стандартной схемой, очень похоже на Visual Studio, естественно, есть у нее нормальный интерфейс с табиками, есть у нее нормальный Solution Explorer, и, в принципе, вот такого для базового Hello World всего у нее достаточно. +326.56 339.76 "Анатолий Кулаков" Более того, есть базовые рефакторинги и экшены, то есть можно там заэкстрактить метод, можно сделать переименование, и какие-то базовые вещи тоже уже есть, уже поддерживаются. +339.76 353.96 "Анатолий Кулаков" Есть информация о символах, то есть мы можем посмотреть, какие у нас методы есть в стандартном фреймворке, мы можем посмотреть к ним документацию, их типы, аргументы, в общем, как положено, символы она тоже понимает. +353.96 369.36 "Анатолий Кулаков" Кроме C# подсветки, есть у нее еще подсветка Razer синтексиса, что тоже, в принципе, не каждый блокнотик умеет, например, в редакторе Z он Razer не умеет, а вот этот #IDE уже, в принципе, Razer подсвечивает. +369.36 378.12 "Анатолий Кулаков" Есть запуск, то есть мы можем запустить, запуститься, посмотреть логи, которые у нас при запуске получились, и более того, есть уже отладка. +378.12 387.92 "Анатолий Кулаков" Она сейчас находится в разработке, но такие базовые вещи, как посмотреть переменные, пройтись по стекам, прогуляться по различным методам, все это уже есть. +387.92 397.84 "Анатолий Кулаков" Естественно, она может собирать, выдавать ошибки, выдавать ошибки, запускать анализаторы, устанавливать нугет-пакеты, то есть всякие зависимости, может запускать тесты, есть уже тест-экспловер. +397.84 404.96 "Анатолий Кулаков" Кстати, опять же, у того же Visual Studio Code очень-очень долго не было тест-экспловера, и люди как бы мучились из консольки. +404.96 413.72 "Анатолий Кулаков" Здесь же сразу из коробки уже есть тест-экспловер, поэтому не самая бедная функциональность для каких-то первых версий, хочу сказать. +413.72 429.92 "Анатолий Кулаков" В общем, штука интересная, находится сейчас в активной разработке, поэтому если вдруг вы когда-то мечтали написать свою собственную IDE, легкую, быструю, красивую, с C#, может быть, с поддержкой еще других языков, то милости просим. +429.92 437.60 "Анатолий Кулаков" Автор всячески рекомендует контрибьютить, ищутся форки, pull-requests, все приветствуется. +437.60 440.96 "Анатолий Кулаков" Поэтому если вы хотели написать свою IDE, сейчас как раз самое время. +440.96 450.44 "Анатолий Кулаков" Кажется, что интересный проект, хорошо взлетел, и в принципе, если будет добавляться фичами, то у него есть все шансы занять свою нишу на рынке. +450.44 459.88 "Анатолий Кулаков" Потому что мы как раз в новогоднем выпуске грустили все дружно, что у нас нет какой-то нормальной, опенсорсной, наконец-то открытой, приличной IDE. +459.88 464.68 "Анатолий Кулаков" Кстати, новогодний выпуск уже есть на Boosty, если кто-то захочет послушать, заходите. +464.68 478.20 "Анатолий Кулаков" А вот здесь у нас как раз назревает какая-то IDE, которая вполне себе опенсорсная, вполне красивая, вполне быстрая, и есть все шансы стать довольно достаточно функциональной. +478.20 482.98 "Игорь Лабутин" Главное, чтобы автору все-таки хватило куража ее продолжать разрабатывать. +482.98 504.32 "Игорь Лабутин" Потому что как с любым таким, может быть не с любым, но со многими такими продуктами, когда ты написал основные крутые и клевые фичи, а дальше начинается необходимость нудно вычищать какие-нибудь мелкие баги и прочее, вот это как бы… Главное, чтобы в этом не наступило разочарование и желание куда-нибудь это все выкинуть. +504.32 511.36 "Анатолий Кулаков" Да, именно поэтому хорошо, если народ подхватит идею и будет обильно и сильно помогать, потому что это всегда мотивирует. +511.36 518.04 "Игорь Лабутин" Ну, пожелаем удачи, всегда хорошо, когда есть конкуренция. +518.04 554.44 "Игорь Лабутин" Надо сказать, что ты не называл, но вот у нас же была такая среда разработки как Monodevelop когда-то еще давно, и каких-то своих как бы, ну скажем так, пользователей она имела вполне, поэтому, наверное, даже столь узкоспецифичная и неполнофункциональная IDE сейчас поначалу, в смысле узкоспецифичная в том плане, что там не поддерживается довольно много фич сейчас, которые может быть вы хотели бы видеть в полноценной IDE, там какой-нибудь, не знаю, онлайн экзам, эдитор, превью, что-нибудь в таком духе, ну как бы когда-нибудь появится, а для простых случаев может и сойдет уже сейчас, и какие-то фанаты будут. +554.44 558.32 "Игорь Лабутин" Пожелаем удачи автору, а мы, наверное, пойдем дальше. +558.32 575.64 "Игорь Лабутин" К нам вернулась статья Джона Скита, в смысле Джон Скит вернулся, регулярно возвращается в свой блог, но в основном он там пишет про всякие какие-то не относящиеся к C#, мне кажется, вещи, но иногда C#-овые статьи проскакивают, и мы их радостно забираем. +575.64 580.84 "Анатолий Кулаков" Да, в дотнет-мир он заходит довольно редко, и это тот самый счастливый час. +580.84 604.84 "Игорь Лабутин" Не, он заходит как раз нормально, в смысле у него его продукт, который он там, я не знаю, продуктит или подпроджект, что-то там про выборы он пишет, он на C#, но вот как раз-таки когда у него возникает какая-то, как сказать, интересный момент на тему использования какого-то современного кусочка C# в его продукте на дотнете, вот он про это пишет небольшую статью. +604.84 609.24 "Игорь Лабутин" Мы уже недавно как раз по всяким immutable коллекциям проходились вместе с ним, и вот продолжение. +609.24 648.60 "Игорь Лабутин" У него довольно много кода основан на immutable коллекциях, которые immutable list, immutable dictionary, но тут ему в некоторый фидбэк прилетели вопросы, типа мол, по большому счету immutable list и immutable dictionary, ну это довольно древняя у нас коллекция, недавным-недавно, а сейчас есть immutable array и новомодный современный frozen dictionary, которые вообще кажется могли бы быть гораздо более эффективным для того стиля использования, который есть в коде у Джона, и ему предложили попробовать вообще, может они получше будут. +648.60 666.76 "Игорь Лабутин" Значит, Джон Скитт, соответственно, стал это дело анализировать и родилась вот эта статья, в которой сначала описывается вообще, а что вообще может быть, зачем могут быть полезны immutable коллекции, как вы их можете использовать. +666.76 693.00 "Игорь Лабутин" Традиционно, когда рассказывают про immutable коллекции, а все же что боятся, что у вас есть immutable коллекция, я же хочу в коллекцию добавлять элемент и получать новую immutable коллекцию, и дальше большая часть статей, мне кажется, в основном начинает крутиться вокруг того, а как же реализованы все эти immutable коллекции внутри, ради того, чтобы при добавлении вы же не будете копировать целиком огромную коллекцию, там деревья внутри, вот это все, ссылки на прошлые коллекции и все такое прочее. +693.00 755.32 "Игорь Лабутин" Это нормальный паттерн, все дела, но возможно, если вы такими пользуетесь, ну, может быть, immutability, конечно, хорошо и все дела, но если ваш паттерн использования примерно такой, как у Джона Скитта, то есть когда вы собрали, создали такую коллекцию один раз, а потом вы, в общем-то, ее особо не модифицируете, то вот это как раз, это вообще хороший пойнт использовать immutable коллекцию в этом месте, но, возможно, здесь как раз и подойдут лучше всякие штуки типа immutable array или frozen dictionary, которые в принципе не позволяют себя модифицировать, то есть frozen dictionary вообще, она той frozen, что она замороженная, да, мы уже рассказывали несколько раз про то, что внутри там используются хитрые алгоритмы, которые, понимая, на каком множестве индивидуализируется коллекция, генерируют там сам, в смысле, не генерируют, конечно, а выбирают нужные там компараторы и прочие алгоритмы тема того, чтобы эффективнее искать по нужной, по коллекции, по ключу, либо еще как-то. +755.32 769.96 "Игорь Лабутин" Вот, ну, Джон Скитт посмотрел, сказал, что ну да, вообще-то я действительно очень редко обновляю свои immutable коллекции, обычно я их в основном создаю и больше ничего с ними не делаю, кроме как читаю из них, поэтому, ну давайте действительно попробуем. +769.96 772.04 "Игорь Лабутин" Значит, как это дело смигрировать? +772.04 778.24 "Игорь Лабутин" То есть понятно, что у вас есть, если у вас есть большая кодовая база, то надо это как-то дело смигрировать. +778.24 779.24 "Игорь Лабутин" Как же это делать? +779.24 806.64 "Игорь Лабутин" Ну, делаться это довольно несложно, особенно для immutable dictionary и frozen dictionary, тут все просто, и то, и то является словарем, по факту нужно было добавить новый namespace, добавить, скажем так, переименовать некоторые extension методы, потому что у него вся работа с коллекциями происходит через extension методы, то есть создание их, ну и обновить, естественно, там где типы указаны. +806.64 824.96 "Игорь Лабутин" Никаких специфических способов создания immutable dictionary вне вот этих extension методов не было, поэтому достаточно было написать новый extension метод, типа to frozen dictionary, грубо говоря, обновить везде, везде где было to immutable dictionary на to frozen dictionary и все супер, отлично, все замечательно. +824.96 865.44 "Игорь Лабутин" А вот с заменой immutable листа на immutable array было гораздо более все нетривиально, потому что immutable list — это коллекция, это reference type, с ним все хорошо, нормально, а вот immutable array — это внезапно value type, то есть несмотря на то, что это коллекция, это value type, сделано это не просто так, потому что immutable array внутри себя содержит по факту одно единственное поле, которое ссылается на собственный массив, который является уже reference, но для того, чтобы по сути не держать такой маленький объектик в куче, в котором будет всего одно поле, его делают value type, чтобы его можно было практически бесплатно передавать, например, в аргументы, возвращать из функции и так далее, он тогда через стэк передается и все замечательно. +865.44 883.24 "Игорь Лабутин" Но проблема в том, что работа с reference type и с value type, она вообще говоря довольно-таки разная в dotnet, особенно в части некоторых случаев обработки null, но давайте по порядку. +883.24 893.20 "Игорь Лабутин" Ну, во-первых, понятно, что придется поменять код просто потому, что, например, свойства разные, у листа свойства называется count, у array, immutable array, свойства называется length. +893.20 899.20 "Игорь Лабутин" Ну, как бы, ладно, простое переименование, хотя возможно его довольно много где придется применить. +899.20 1025.16 "Игорь Лабутин" Дальше с nullability, с nullability проблема в следующем, если для листа у вас могла бы быть функция, которая принимает, допустим, какой-нибудь там immutable list вопросик, и если вы туда передаете null или какой-нибудь там не null тип, то все нормально как бы, если передать null, то тоже все хорошо, то вот с immutable array, то есть который value типа, с ним все сложнее, потому что если вы сделаете только nullable перегрузку, будет нехорошо, приходится делать две перегрузки, одна для nullable типа, другая не для nullable типа, чтобы не было там никакого боксинга по пути, ничего такого, то есть пришлось немножко добавить оверлодов, а дальше нужно было поменять практически все проверки на null, потому что раньше было как, раньше можно было в коде просто проверить if array is null, но теперь-то если это value тип, и если это не nullable value тип, то есть не nullable от immutable array, то array is null для value типа всегда, соответственно, false, и так не работает, поэтому нужно было аккуратненько все эти места переписать и там, где nullable стал array, то там есть два варианта, что вы можете с этим сделать, значит, один вариант, вы можете честно проверить, что if, значит, nullable тип is null, то тогда, допустим, с функции сделать сразу return, иначе везде начать использовать там array.value, то есть как бы доступиться к внутреннему контенту nullable t и так писать, но если вы несколько раз используете внутри функции этот, например, аргумент, то писать везде array.value как-то, ну, не то, поэтому для таких случаев jonskit рекомендует использовать оператор is, тогда вы пишете в начале функции if array is not immutable array от там вашего типа, от стринга, например, и сразу объявляете переменную array.value, то тогда return, иначе во все остальные функции можно уже использовать переменную array.value, и она будет гарантирована не nullable immutable array, не нужно будет везде писать array.value, такой, хороший прием использования вот этого волшебного оператора is и is not в данном случае. +1025.16 1029.84 "Игорь Лабутин" Что же получилось? +1029.84 1066.96 "Игорь Лабутин" Получилось действительно стало быстрее, причем довольно существенно быстрее, самый долгий вызов, самый долгий кусочек логики это функция validate, которая довольно много работала, как раз-таки и собирала все эти коллекции, проверяла, что в них все правильно, они там друг с другом правильно соответствуют и так далее, ее скорость в бенчмарках увеличилась, она была 5,5 миллисекунд, а сейчас она стала 0,8 миллисекунда, то есть по сути в 4, ну где-то раз в 6 она улучшилась, в 7 может быть даже, то есть это прям хорошо. +1066.96 1188.32 "Игорь Лабутин" Другое дело, что конкретно это улучшение скорее всего сильно там какие-то пользовательские характеристики не повлияло, потому что большинство операций, которые видит пользователь, они на самом деле упираются в кэш, который возвращает все нужные результаты, у него там все критические результаты кэшируются на 10 минут, поэтому в большей части то, что мы там оптимизировали в 7 раз операцию на 5 миллисекунд, ну она в бенчмарке 5 миллисекунд, в реальной жизни она может быть там чуть больше, чуть меньше, пользователь этого конечно же не увидит, если только он не попал на момент, когда что-то не закэшировано или что-то обновилось, но в целом, с другой стороны, практически бесплатное улучшение вроде как и хорошо, и вот вопрос, бесплатно ли оно, и здесь Джон Скитт делает несколько, так сказать, заметок, выводов, во-первых, у него довольно большой раздел статьи отнесен к тому, что что-то с неймингом не то, то есть у нас есть теперь иммьютабл коллекции, есть фроузен коллекции, которые с точки зрения поведения по большому счету одно и то же, то есть у нас и иммьютабл коллекция немутабельная и позволяет там себя читать и так далее, и фроузен коллекция немутабельная и позволяет себя читать, ну иммьютабл она как бы мутабельна путем создания новой, фроузен она как бы совсем немутабельная, у нас является ли такая разница в поведении достаточной для того, чтобы придумывать два разных названия, то есть я так понимаю, что его мысль была сделать все то же самое, прям вот, нельзя было бы сделать эти фроузен коллекции прямо внутри иммьютабл коллекции, под теми же коллекциями, но может быть было бы более консистентно, что ли, что у нас, не надо было думать какую именно иммьютабл взять, берешь просто иммьютабл, а дальше она там либо оптимизирована, либо не очень оптимизирована, я не знаю. +1188.32 1189.32 "Игорь Лабутин" Проблемы с value-тайпами. +1189.32 1204.56 "Игорь Лабутин" Не то, что проблемы, а вот эти все тонкости, нужно помнить, что это value-тип, иммьютабл array, если вы его используете, ну и соответственно не забывать, что у вас может внезапно появиться куда-то боксинг, но лоббилити соответственно не такой, как для reference-тайпов, но с этим можно тоже что-то сделать. +1204.56 1210.24 "Игорь Лабутин" В итоге вывод, общий вывод статьи примерно такой. +1210.24 1268.84 "Игорь Лабутин" В целом каких-то больших performance-бенефитов не получено, но небольшие performance-бенефиты получены, и при этом цена лейда не очень большая, то есть структура кода практически не поменялась, код остался достаточно красивым, то есть за счет всех этих операторов из нод и вот это вот все, получается вполне красиво написать код без необходимости какой-то очень сложной обработки value-типов, и поэтому в целом, по мнению Джона Скейта, то есть он для себя решил, что да, в будущем он будет больше использовать front-end dictionary, иммьютабл array сразу, конкретно для сценариев, когда вот мы создаем коллекцию и особо ее больше не трогаем, чтобы ее не пересоздаем, не добавляем как-то и так далее, в смысле пересоздаем только если изменились данные, пересоздаем с нуля, а не используя старую коллекцию, это вполне валидный паттерн, код получается красивым, поэтому вполне можно рекомендовать к этому использованию вместо обычных иммьютабл коллекций, ну вот примерно такая история. +1268.84 1276.52 "Анатолий Кулаков" Полезно знать, какие коллекции в какие моменты нужно применять, а какие не нужно. +1276.52 1280.84 "Анатолий Кулаков" Так что спасибо товарищу Джону, грамотную статью выдал. +1280.84 1296.56 "Игорь Лабутин" Да, давай мы, я знаю, что у нас сегодня почти не день Microsoft, у нас будет все-таки одна статья от Microsoft, но дальше мы пошли по таким, мне кажется, суровым темам, давай в сторону билдов углубимся. +1296.56 1307.32 "Игорь Лабутин" Вот я вижу, что ты сейчас про билды будешь рассказывать, но я еще про билды довешу, так что кому охота слушать про билды, готовьтесь, две суровых статьи про билды. +1307.32 1315.48 "Анатолий Кулаков" Ну тема хорошая, да, в принципе нужная, поэтому нужно знать не только какими коллекциями пользоваться, но и когда и как и билдите ваши проекты. +1315.48 1319.16 "Анатолий Кулаков" Ну, я не очень про билды, но недалеко, недалеко отсюда. +1319.16 1325.60 "Анатолий Кулаков" Я бы хотел вам рассказать о том, как делать свой собственный MS Build из ДК, нехило тогда заявление. +1325.60 1333.52 "Анатолий Кулаков" Ну прежде всего у вас должно возникнуть горизонтальный вопрос, зачем нам это делать, вот Игорь, ты когда последний раз делал свой .NET из ДК? +1333.52 1354.60 "Игорь Лабутин" .NET из ДК я не делал вообще никогда, ну нет, я один раз собирал его у себя на компе, давно, правда, было, в районе, по-моему, 6, ну вот когда там первые разы, они сказали, что, о, можно пробовать, один раз я, по-моему, собирал себе .NET из ДК, и довольно, ну много, но точечно писал MS Build таски, ну это было еще во времена .NET фреймворка. +1354.60 1356.60 "Игорь Лабутин" Вот примерно так. +1356.60 1365.84 "Анатолий Кулаков" Ну нормально, нормально, я тоже довольно давно этим занимался, но кажется, что пора стряхнуть порох с пороховницей и еще немножко залезть в эту тему поглубже. +1365.84 1376.72 "Анатолий Кулаков" В общем, мы с вами будем говорить о нечто среднем, мы не будем сам .NET из ДК трогать, и мы не будем просто-напросто писать MS Build таски, мы попробуем сделать MS Build из ДК. +1376.72 1380.48 "Анатолий Кулаков" Давайте для начала разберемся, зачем мы этого хотим, а потом уже обсудим как. +1380.48 1401.20 "Анатолий Кулаков" Разберемся мы на примере статьи от Геральда Боре, мы уже обсуждали несколько его статей про то, каким образом привести весь ваш код стайл в вашем проекте, в вашем репозитории как единому виду, каким образом расшаривать стандарты, каким образом расшаривать анализаторы, чтобы это было все удобно, поддерживаемо и красиво. +1401.20 1408.64 "Анатолий Кулаков" Статья хорошая, набрала много полуобложительных отзывов, поэтому продолжаем разговор в эту сторону. +1408.64 1433.32 "Анатолий Кулаков" Просто напомню, что у товарища Геральда, у него есть специальный пакет, который называется .NET кодинг стандарт, и в этот пакет он засунул абсолютно там все возможные общие стандарты в его компании, это какие-то там анализаторы, дефолтные настройки, какие-то общие инструменты, и данный подход позволяет ему очень легко обновлять стандарт во всей компании. +1433.32 1438.56 "Анатолий Кулаков" Ну допустим, вышел новый анализатор, все, что ему нужно сделать, это обновить версию пакета во всех проектах. +1438.56 1445.08 "Анатолий Кулаков" В принципе, операция довольно банальная, легко автоматизируется и делается довольно предсказуемо и хорошо. +1445.08 1449.56 "Анатолий Кулаков" Поэтому данный подход показал себя с довольно положительной стороны. +1449.56 1454.12 "Анатолий Кулаков" Но у этого Nougat пакета есть много ограничений. +1454.12 1459.08 "Анатолий Кулаков" Ну и в частности, самое главное ограничение в том, что Nougat это чисто декларативная вещь. +1459.08 1464.12 "Анатолий Кулаков" Он не может динамически принимать какие-то решения на основании каких-то характеристик. +1464.12 1470.52 "Анатолий Кулаков" Ну допустим, он не может добавить пакеты в какие-то определенные проекты и в какие-то проекты, допустим, не добавлять. +1470.52 1484.88 "Анатолий Кулаков" Например, в тестовые проекты мы обычно хотим добавить какие-то специальные библиотеки, ну которые мы используем в тестировании, настроить там логеры, чтобы они куда-то правильно писали и добавить, может быть, каких-то тестовых расширений или библиотек с ассертами и так далее. +1484.88 1492.04 "Анатолий Кулаков" В веб-приложения мы, допустим, хотим проинструментировать OpenTelemetry, настроить в них там какие-то коллекторы и так далее. +1492.04 1495.56 "Анатолий Кулаков" В общем, зависимости от типа проекта нам хочется разного. +1495.56 1499.20 "Анатолий Кулаков" Обычный .NET пакет такой магии сделать не позволяет. +1499.20 1501.04 "Анатолий Кулаков" И у нас есть выход. +1501.04 1503.92 "Анатолий Кулаков" Это как раз MSBuild SDK. +1503.92 1512.48 "Анатолий Кулаков" MSBuild SDK - это специальные скрипты на MSBuild, которые позволяют гибко делать практически все, что угодно. +1512.48 1515.52 "Анатолий Кулаков" Ну там полноценный Turing, полный язык программирования. +1515.52 1527.64 "Анатолий Кулаков" Поэтому они позволяют нам добавить различные пакеты в зависимости от любых условий, добавлять произвольные файлы, динамически конфигурировать любые параметры. +1527.64 1534.92 "Анатолий Кулаков" И все это основываясь на каких-то переменных сведы окружения, на типе проектов, на названиях, там, солюшенов и так далее. +1534.92 1537.60 "Анатолий Кулаков" Ну то есть все это очень-очень гибко. +1537.60 1546.60 "Анатолий Кулаков" Поэтому MSBuild SDK - это как раз очень гибкий путь для того, чтобы настраивать MSBuild проекты. +1546.60 1552.96 "Анатолий Кулаков" Они представляют собой набор, как я уже сказал, скриптов, которые запускаются в определенное время. +1552.96 1556.92 "Анатолий Кулаков" То есть они позволяют вам вклиниться в билд-процесс. +1556.92 1560.40 "Анатолий Кулаков" И очень гибко, там у них есть миллион точек для расширения. +1560.40 1562.40 "Анатолий Кулаков" Вы можете встроиться куда угодно. +1562.40 1567.20 "Анатолий Кулаков" И это позволяет вам полностью настроить вообще, что будет происходить. +1567.20 1573.44 "Анатолий Кулаков" Не только библиотечки там добавить, динамическую конфигурацию добавить, пакеты какие-то там проустановить и все такое. +1573.44 1578.40 "Анатолий Кулаков" Но и, допустим, вообще определить, какие файлы будут компилироваться, а какие не будут компилироваться. +1578.40 1589.64 "Анатолий Кулаков" MSBuild SDK представляет из себя коллекцию скриптов, которые обычно распространяются с расширениями .props и .target. +1589.64 1599.36 "Анатолий Кулаков" И в зависимости от того, как вы их назовете, как вы их задекларируете и как вы их подключите, они будут импортироваться в тот или иной момент времени билд-пайплайна. +1599.36 1606.20 "Анатолий Кулаков" И таким образом весь этот билд-пайплайн вы можете изменять. +1606.20 1609.60 "Анатолий Кулаков" SDK состоит из нескольких файлов. +1609.60 1620.54 "Анатолий Кулаков" Допустим, файл SDK.props, он запускается в самом начале вашего билд-процесса, вообще еще до того, как даже сам Microsoft определит какие-то первые переменные среды окружения. +1620.54 1627.84 "Анатолий Кулаков" То есть вы можете там настроить вплоть, все вплоть до того, до например фреймворка, под которым это все будет запускаться. +1627.84 1632.32 "Анатолий Кулаков" И второй тип файлов это, например, SDK.target, который запускается в самом конце. +1632.32 1635.76 "Анатолий Кулаков" Там вы можете тоже какие-то пост-билд действия сделать. +1635.76 1642.96 "Анатолий Кулаков" Вот этот весь SDK, он дает полный контроль над всем билд-процессом. +1642.96 1650.48 "Анатолий Кулаков" То есть вы можете выставить переменные среды, с которыми будет запускаться все инструменты, все компиляторы, все анализаторы, все ворнинги. +1650.48 1660.12 "Анатолий Кулаков" Вы можете модифицировать любые пайплайны, которые уже зарегистрированы, например, стандартным микрософтовским пайплайном. +1660.12 1666.48 "Анатолий Кулаков" Вы можете на основании каких-то условий добавлять файлы к компиляции или удалять файлы из компиляции. +1666.48 1670.14 "Анатолий Кулаков" Вы можете импортировать свои новые SDK или чужие новые SDK. +1670.14 1675.76 "Анатолий Кулаков" Естественно, вы можете устанавливать любые NuGet-пакеты, до которых сможете дотянуться. +1675.76 1680.16 "Анатолий Кулаков" Вы можете менять target-фреймворк даже, под которым все это будет билдиться. +1680.16 1681.72 "Анатолий Кулаков" То есть все это контролируется SDK. +1681.72 1686.36 "Анатолий Кулаков" Ну и вплоть до того, что определять, какие вообще файлы будут компилироваться, а какие компилироваться не будут. +1686.36 1698.92 "Анатолий Кулаков" Настоящий .NET SDK, который вы ставите из коробки .NET Framework, он внутри себя уже включает несколько MSBuild SDK. +1698.92 1710.32 "Анатолий Кулаков" Наверное, наверняка вы их видели, если открывали файлы с CSS-прош, это такие названия, как Microsoft.net.sdk, Microsoft.net.sdk.web, если у вас веб-приложение. +1710.32 1712.96 "Анатолий Кулаков" То есть они указываются обычно первой строчкой в CSS-прош-файле. +1712.96 1715.28 "Анатолий Кулаков" Поэтому, если вы файлы открывали, вы наверняка видели. +1715.28 1718.20 "Анатолий Кулаков" Вот это вот и есть MSBuild SDK. +1718.20 1720.84 "Анатолий Кулаков" Вы можете сделать вот точно такой же, только свой. +1720.84 1723.48 "Анатолий Кулаков" Это делается довольно легко. +1723.48 1730.08 "Анатолий Кулаков" Распространяются они в виде NuGet-пакета, поэтому вам достаточно просто сделать обычный NuGet-пакет, но со специальной структурой. +1730.08 1731.68 "Анатолий Кулаков" Структура тоже довольно банальная. +1731.68 1739.92 "Анатолий Кулаков" В вашем пакете в корне должна лежать директория, которая называется SDK. +1740.24 1745.12 "Анатолий Кулаков" Внутри этой директории должны лежать файлики SDK.props и SDK.target. +1745.12 1746.44 "Анатолий Кулаков" И, в принципе, все. +1746.44 1747.60 "Анатолий Кулаков" И этого достаточно. +1747.60 1751.04 "Анатолий Кулаков" Все остальные действия следуют из того, что написано в этих файликах. +1751.04 1757.16 "Анатолий Кулаков" Вот, в принципе, так легко и просто подготовить свой SDK. +1757.16 1759.40 "Анатолий Кулаков" Теперь мы поняли, как его готовить, давайте поймем все-таки зачем. +1759.40 1761.08 "Анатолий Кулаков" Что мы с помощью этого можем сделать. +1761.08 1766.20 "Анатолий Кулаков" Ну и для примера, что мы можем с помощью этого сделать, возьмем SDK товарища Геральда. +1766.20 1780.80 "Анатолий Кулаков" Так как он любит распространять всякие код-стандарты в своей компании, то с помощью вот этого подхода он может теперь еще больше делать, еще больше распространять код-стандартов, еще более наносить людям добро. +1780.80 1786.12 "Анатолий Кулаков" Давайте посмотрим, что он внес в этот SDK и, может быть, какие-то идеи у него можно позаимствовать. +1786.12 1794.00 "Анатолий Кулаков" Ну, во-первых, он встроил в распространение в свой SDK Editor Config для того, чтобы управлять консистентно форматированием. +1794.00 1802.04 "Анатолий Кулаков" Он добавил туда кучу анализаторов, встроенные микрософтовские анализаторы, свои собственные анализаторы, Bant API анализатор. +1802.04 1810.12 "Анатолий Кулаков" Кстати, хороший анализатор, который запрещает нам пользоваться некоторыми функциями, классами, методами от стандартного, допустим, фреймворка. +1810.12 1820.36 "Анатолий Кулаков" Не только от стандартного, в принципе, от любого можно запретить, но если от любого, вы можете просто пакетчу брать, например, то вот со стандартным вы ничего не сделаете. +1820.36 1827.16 "Анатолий Кулаков" Ну, допустим, вы не хотите, чтобы кто-то пользовался спанами в вашем приложении, вы можете его через этот анализатор просто заблокировать. +1827.16 1838.44 "Анатолий Кулаков" Дальше настраивается через этот SDK, опять же, стандартные MS Build свойства, такие как Threat Warning от As Errors, т.е. всегда ворнинги считать эррорами. +1838.44 1850.40 "Анатолий Кулаков" Включается, например, StrictMode, используются NullReferenceTypes, включается флаг AccelerateBuildInVisualStudio, это специальный магический флажочек, который заставляет билды Visual Studio проходить быстрее. +1850.40 1857.88 "Анатолий Кулаков" Включается NugetAudit, который запускает сканинг разных security уязвимостей во всех зависимостях. +1857.88 1878.40 "Анатолий Кулаков" Включается интеллектуальный поиск Target Framework, опять же, если вдруг вы в своем CessProje не хотите явно задавать какую версию языка, допустим, использовать или какой Target Framework использовать, то это вполне можно вывести в зависимости от версии SDK, которая там у вас установлена, которая доступна в этом, в этом солюшене. +1878.40 1886.76 "Анатолий Кулаков" Поэтому если она явно не задана, вот этот MS Build SDK выводит именно эту версию, эту версию выводит неявно. +1886.76 1896.04 "Анатолий Кулаков" Включается SourceLink, который позволяет вам дебажить внешние Nuget-пакеты гораздо более приятно с исходниками и прочими символами. +1896.04 1909.56 "Анатолий Кулаков" Включаются глобальные юзинги в зависимости от того, какой у текущего проекта Namespace, то есть вы можете под ваши текущие проекты, там имя компании, точка имя проекта и все такое глобальные юзинги сделать. +1909.56 1915.32 "Анатолий Кулаков" Это довольно гибко получается и хорошо, потому что они резолвятся как раз в то время, когда компилируется проект. +1915.32 1933.40 "Анатолий Кулаков" Также заполняется различная методата к вашим Nuget-пэкеджам, ну, например, авторы, иконки, README лицензии, то есть все вот эти банальные сотни полей, которые никогда руками не хочется прописывать, она тоже автоматически заполняется, как только вы инсталируете этот SDK. +1933.40 1940.44 "Анатолий Кулаков" Мы в самом начале упоминали, что хотели там, допустим, в зависимости от типа проекта, тоже что-то подставлять, что же он сделал. +1940.44 1952.40 "Анатолий Кулаков" Ну, допустим, к тестовым проектам, к тестовым проектам можно задетектировать в зависимости от того, какие там у них свойства настроены, какие они там библиотеки используют, какие референсы SDK они используют. +1952.40 1954.40 "Анатолий Кулаков" Поэтому тестовые проекты нормально детектируются. +1954.40 1983.92 "Анатолий Кулаков" Так вот, к тестовым проектам можно дополнительно настроить, например, VSTest или Microsoft Testing Framework, можно настроить тестовый логер, можно настроить тест-аутпут форматы, потому что тестеры, они тесты, они могут писать аутпут в различных там форматах, в XML, в бинарном, в текстовом и так далее, в зависимости от environment, где они запускаются, например, под CIM они в одном формате пишут, под EDE в другом формате и так далее. +1983.92 1986.16 "Анатолий Кулаков" Опять же, все это можно прозрачно настроить. +1986.16 2005.28 "Анатолий Кулаков" Потом настраиваются, например, GitHub Actions, в тот же самый GitHub Actions тест-логер подключается, если вдруг SDK видит, что мы компилируемся под GitHub, настраиваются прозрачно код-каверидж, то есть вообще ничего не нужно делать, проект сам начинает собирать код-каверидж для тех мест, где это нужно. +2005.28 2013.04 "Анатолий Кулаков" И там какие-то дефолты, настройки этого код-кавериджа проставляются, которые для проекта релевантны в данном случае. +2013.04 2018.48 "Анатолий Кулаков" Выставляются всякие тест-экстеншены, например, собирать, допустим, CrashDump, если вдруг какой-то тест рухнул. +2018.48 2034.20 "Анатолий Кулаков" Если у нас используется XUnit, это тоже можно динамически продетектировать, то прописываются всякие XUnit Global Usings для того, чтобы вы, например, ассерты писали или атрибуты XUnit писали без всяких Usings в чистом и красивом файлике. +2034.20 2035.20 "Анатолий Кулаков" Удобно? +2035.20 2036.20 "Анатолий Кулаков" Удобно. +2036.20 2039.12 "Анатолий Кулаков" Если у нас, допустим, веб-проект, что в веб-проекте можно настроить? +2039.12 2046.48 "Анатолий Кулаков" Ну, в веб-проекте можно настроить много чего, потому что там, например, есть холстчеки. +2046.48 2073.20 "Анатолий Кулаков" В общем, стандартный холстчек Endpoint можно подключить, опять же, стандартные, если вы знаете, что у вас там, допустим, используется какая-то база данных, можно стандартные холстчеки для этой базы подключить, можно холстчеки подключить для, допустим, вашего кэша еще куда-то, или, например, OpenTelemetry, тоже более-менее стандартная штука, которую используют практически все. +2073.20 2078.72 "Анатолий Кулаков" Ее можно настроить прямо из SDK, не обязательно в каждом проекте прописывать, что используем OpenTelemetry. +2078.72 2087.98 "Анатолий Кулаков" Также можно настроить экспортеры, если у вас есть какой-то монетный коллектор, вы туда трейсы, метрики, логи, все туда можете записывать. +2087.98 2103.48 "Анатолий Кулаков" Из интересного можно настроить Resilient для всех HTTP-клайентов, то есть, допустим, все HTTP-клайнты, которые приходят к вам из DI-контейнера, а это, скорее всего, все HTTP-клайнты, они будут использовать специальный Retry Policy, который у вас там в компании принято. +2103.48 2110.52 "Анатолий Кулаков" И для этого не нужно писать ни строчки кода, все это можно задать через конфигурацию SDK. +2110.52 2122.24 "Анатолий Кулаков" Здесь еще в качестве примера приходится выставление юзер-агента в HEADERA для всех HTTP-клиентов, интересная тема, никогда почему-то не выставлял юзер-агента для HTTP-клайнтов, но, наверное, полезная штука. +2122.24 2129.72 "Анатолий Кулаков" Можно подключить стандартные middleware, которые вы, допустим, подключаете, когда настраиваете веб-приложение, скорее всего, они у вас, опять же, одинаковые. +2129.72 2152.04 "Анатолий Кулаков" Использовать HTTP-редиректы, использовать HTTPS, раздавать статические файлы, включить аутентификации, корсы, рейт-лимитеры, HTTP-логинг и прочее, в общем, чтобы это не писать в каждом веб-проекте, потому что веб-проектов в компании миллион, и все они практически одинаковые, это можно зашить в SDK, которая, напомню, легко, красиво обновляется и централизованно управляется. +2152.04 2154.44 "Анатолий Кулаков" Что еще у нас в вебах? +2154.44 2164.96 "Анатолий Кулаков" Ну, JSON-конвеншены всякие, которые приняты в компании, например, Naming Convention, Null Value Handling, в общем, тоже, чтобы JSON во всех сервисах был одинаковым, децерализовался одинаково. +2164.96 2167.92 "Анатолий Кулаков" Как эта штука работает? +2167.92 2188.24 "Анатолий Кулаков" По дефолту она регистрирует source-генератор, который вклинивается в вызов веб-аппликейшен билд, поэтому, как только вы вызываете веб-аппликейшен билд, на стандартное создание вашего приложения, запускается специальный код, и в этом специальном коде source-генератор подключает и настраивает вот эту всю муть, которую я выше рассказал. +2188.24 2194.60 "Анатолий Кулаков" То есть вы можете заинжектировать туда абсолютно все сервисы, middleware, в общем, все, что только можно. +2194.60 2205.88 "Анатолий Кулаков" Естественно, это можно выключить, если вы не хотите, чтобы оно инжектировалось, как бы там ставится один маленький флажочек и руками как бы по старинке все прописываете для явности и красоты, если вдруг для вас это важно. +2205.88 2207.36 "Анатолий Кулаков" К чему это приводит? +2207.36 2210.92 "Анатолий Кулаков" Давайте посмотрим на маленький пример. +2210.92 2216.64 "Анатолий Кулаков" Самый минимальный, простой, банальный, но полностью функциональный веб-сервер. +2216.64 2217.64 "Анатолий Кулаков" Как пишется? +2217.64 2228.24 "Анатолий Кулаков" То есть у нас есть csproj файл, да, мы не какие-то minimal single файлы будем использовать, csproj, то есть файл проекта. +2228.24 2240.96 "Анатолий Кулаков" Обычно файл проекта, даже вот наш современный, модный, красивый, в котором уже не надо перечислять все файлы, которые компилируются, он все равно внутри себя содержит несколько повторяющихся нудных элементов. +2240.96 2247.52 "Анатолий Кулаков" Это target-framework, включение nullibility, какие-то там зависимости стандартные и так далее. +2247.52 2260.32 "Анатолий Кулаков" В общем, у Геральда ничего этого нет, там есть одна единственная строчка, строчка называется project sdk = и там прописывается его собственный sdk и все, и тег закрывается. +2260.32 2277.68 "Анатолий Кулаков" То есть из одного единственного тега состоит весь csproj файл, а все вот эти target, nullibility, dependency, пакеты, настройки, версии, кампании, все вот это, что мы привыкли видеть в csproj файле, оно автоматически выводится из этого sdk. +2277.68 2282.12 "Анатолий Кулаков" Динамически прям все, что нужно под этот конкретный solution. +2282.12 2285.40 "Анатолий Кулаков" Очень удобно, красиво и элегантно. +2285.40 2289.40 "Анатолий Кулаков" Теперь делаем минимальный cs файл. +2289.40 2295.40 "Анатолий Кулаков" Ну, минимальный cs файл, в принципе, у нас и так довольно несложно, там всего 4 строчки. +2295.40 2307.04 "Анатолий Кулаков" Это в Application create builder, затем вызывается builder build, получаем апп, у этого аппа делаем map get и на get возвращаем hello world. +2307.04 2309.88 "Анатолий Кулаков" Вот вам 4 строчки, которые полнофункциональный сервер вам запускают. +2309.88 2314.88 "Анатолий Кулаков" Здесь тонкость в строчке №2, builder build. +2314.88 2321.92 "Анатолий Кулаков" Как я уже говорил, sdk перехватывает, intercepted вот этот builder build и там регистрирует все middleware. +2321.92 2322.92 "Анатолий Кулаков" Что это значит? +2322.92 2363.04 "Анатолий Кулаков" Это значит, что несмотря на то, что мы написали там 4 банальных строчки из документации с hello world, да, то есть вообще стандартные, стандартнее вообще некуда, несмотря на это, вот эти 4 строчки нам не просто запустили обычный kestrel со стандартными настройками, они запустили нам стандартный kestrel, плюс открыли health-чеки, плюс проинструментировали все наши вызовы OpenTelemetry, настроили экспорт в OpenTelemetry коллектор, сделали все HTTP-клиенты с retry-повисами, зарегистрировали все возможные middleware с логированиями, редиректорами, HTTPS, и все это без каких-то явных конфигураций. +2363.04 2367.08 "Анатолий Кулаков" То есть все это прозрачно и стандартно для компании Геральда. +2367.08 2382.32 "Анатолий Кулаков" В общем, поэтому несмотря на вот этот минимализм, внутри весь вот этот проект, весь вот этот kestrel запустился в очень такой хорошем настроенном environment, в который в принципе и в прот уже можно выдавать, несмотря на 4 строчки кода. +2382.32 2388.24 "Анатолий Кулаков" Вот такую хорошую, интересную пользу приносит нам msbuild.sdk. +2388.24 2397.04 "Анатолий Кулаков" Следующая интересная возможность, что вот этот весь msbuild.sdk мы его делали для того, чтобы удобно обновлять вот эти стандартные методы. +2397.04 2411.96 "Анатолий Кулаков" Появился новый анализатор у нас в коде, мы должны просто обновить msbuild.sdk, и все наши проекты во всей нашей компании расподхвачивают новый анализатор, новый EditorConfig, новые какие-то ResilientPolicy и так далее, и так далее. +2411.96 2414.04 "Анатолий Кулаков" Давайте же подробнее посмотрим, а как его обновлять. +2414.04 2425.16 "Анатолий Кулаков" Как мы обновляем анализаторы зависит от того, как мы его используем, как мы задаем нашему solution, что мы хотим наш SDK использовать. +2425.16 2426.64 "Анатолий Кулаков" Есть несколько способов. +2426.64 2439.80 "Анатолий Кулаков" Самый простой способ это в самом csproj файле, то есть в файле проектов, указать в элементе проект, SDK, там мы указываем его имя, и плюс сразу там же можно указать и конкретную версию. +2439.80 2446.44 "Анатолий Кулаков" Это самый простой, самый понятный вариант, то есть в проектном файле указывается и имя SDK, и версия SDK. +2446.44 2457.32 "Анатолий Кулаков" Этот вариант простой, но у него есть минусы, так как эту строчку указывается во всех, ну в проектном файле, да, вам нужно будет указать ее во всех проектных файлах. +2457.32 2470.56 "Анатолий Кулаков" Поэтому, если у вас в solution этих проектов 200, то вы эту строчку будете 200 раз дублировать, и как только вам нужно будет обновить ваш SDK, то вам придется изменить 200 файлов, 200 проектных файлов. +2470.56 2480.36 "Анатолий Кулаков" Ну, что не очень красиво, да, это все равно лучше, чем как бы было до этого, но хотелось бы, хотелось бы что-то более, чего-то более элегантного, и более элегантный способ есть. +2480.36 2500.64 "Анатолий Кулаков" Есть файл, который называется global.json, и через этот global.json тоже можно указать версию SDK, то есть вы в global.json пишите какую версию SDK вы используете, а в файле проектов вы пишите только название вашего кастомного SDK, и все, без версии. +2500.64 2506.04 "Анатолий Кулаков" Затем global.json складываете в корень репозитория, и все, и все у вас работает. +2506.04 2515.08 "Анатолий Кулаков" Этот подход намного лучше, потому что если у вас 200 файлов проектов, то SDK у вас остается на месте, а меняете вы единственный файл, который называется global.json. +2515.08 2520.78 "Анатолий Кулаков" Именно там прописывается версия, то есть там поменяли, и в принципе все счастливы. +2520.78 2527.32 "Анатолий Кулаков" Существует еще один способ, как указать версию SDK. +2527.32 2529.96 "Анатолий Кулаков" Почему он может вам понадобиться? +2529.96 2549.16 "Анатолий Кулаков" Смотрите, он вам может понадобиться, если вы хотите соединить несколько SDK, то есть есть у вас какой-то SDK от Microsoft, вы не хотите замещать на свой собственный, а вы хотите свой собственный добавить к этому микрософтовскому SDK, тогда у вас есть элемент, который называется SDK. +2549.16 2560.44 "Анатолий Кулаков" Вы этим элементом можете не замещать элемент проект, то есть самый главный ротовый элемент в файле проектов, а прямо в элементе проекта задать элемент SDK, и тогда они вместе соединятся. +2560.44 2567.92 "Анатолий Кулаков" Но здесь вам необходимо помнить некоторые тонкости, которые это повлечет. +2567.92 2587.72 "Анатолий Кулаков" Во-первых, если вы добавите такой элемент SDK к существующему уже файлу проекта, элементу проекта, то у элемента проекта обязан быть свой SDK, скорее всего это будет какой-то стандартный микрософтовский, и ваш кастомный SDK, он будет резолвиться после того SDK, который указан в файле проектов. +2587.72 2590.76 "Анатолий Кулаков" А это, в принципе, может поменять порядок инициализации всех свойств. +2590.76 2609.56 "Анатолий Кулаков" То есть, как я вам раньше говорил, что вы теперь полностью владеете всем пайплайном инициализации, то когда вы внедряете свой SDK через уже зависимый элемент, вы уже не полностью влияете на весь порядок инициализации, потому что вас запускают после стандартного встроенного SDK, поэтому вы уже вынуждены подстраиваться как-то под него. +2609.56 2612.60 "Анатолий Кулаков" И это может каким-то образом, естественно, повлиять на ход компиляции. +2612.60 2626.56 "Анатолий Кулаков" Но у этого метода есть бесспорные плюсы, а плюс этого метода заключается в том, что вот этот элемент SDK, его необязательно заносить в сам файл проекта. +2626.56 2629.76 "Анатолий Кулаков" Вы его можете положить в директори билдпропс. +2629.76 2635.00 "Анатолий Кулаков" Директори билдпропс - это специальный магический файл, который подключается ко всем проектам. +2635.00 2640.96 "Анатолий Кулаков" То есть, ваши файлы проектов полностью остаются такими, какие они есть по стандарту. +2640.96 2648.84 "Анатолий Кулаков" То есть, они никак не меняются, в них встроены микрософтовские билды SDK, и они продолжают также точно успешно работать. +2648.84 2649.84 "Анатолий Кулаков" Они вообще никак не меняются. +2649.84 2659.08 "Анатолий Кулаков" А свой SDK вы кладете в файлик директори билдпропс, и он прозрачно, независимо ни от чего, подключается ко всем проектам. +2659.08 2662.64 "Анатолий Кулаков" Таким образом, вам не нужно вообще модифицировать стандартные файлы проектов. +2662.64 2666.64 "Анатолий Кулаков" И естественно, там же легко обменяется версия в одном единственном месте. +2666.64 2672.04 "Анатолий Кулаков" То есть, этот подход хорош тогда, когда вам нужно сохранить оригинальные файлы проектов. +2672.04 2674.24 "Анатолий Кулаков" Такое тоже часто бывает нужно. +2674.24 2678.48 "Анатолий Кулаков" В принципе, все подходы есть, выбирайте тот, который вам нужно. +2678.48 2681.36 "Анатолий Кулаков" Они довольно гибкие, понятные и довольно функциональные. +2681.36 2683.84 "Анатолий Кулаков" Можно сделать довольно хорошо и просто. +2683.84 2690.36 "Анатолий Кулаков" Ну и в конце хочется даже задать вопрос, а действительно ли вам нужно создавать свой собственный SDK. +2690.36 2713.96 "Анатолий Кулаков" Ну, кажется, что если вы хотите всей той мощи, которую он предоставляет, если вы хотите единых стандартов кодирования, анализаторов, референсов, библиотек, нугет-пакетов, версий, то есть, если вы не хотите со всем этим зоопарком мучиться, а хотите определять это все в одном месте, подтаскивать всем компаниям, ко всем солюшенам, ко всем проектам, то это очень хороший инструмент. +2713.96 2717.36 "Анатолий Кулаков" Сконфигурировать единообразно все проекты. +2717.36 2724.76 "Анатолий Кулаков" Но тут необходимо помнить, что вместе с той пользой, которую он приносит, здесь у вас появляется небольшая сложность. +2724.76 2726.68 "Анатолий Кулаков" Ну, то есть, сложность в вашем проекте. +2726.68 2729.08 "Анатолий Кулаков" У вас теперь есть некая инфраструктура. +2729.08 2733.52 "Анатолий Кулаков" Она не явная, то есть, многие разработчики, скорее всего, поначалу про нее даже не будут знать. +2733.52 2744.36 "Анатолий Кулаков" Они понятия не имеют, откуда у них появились халтчеки, почему у HTTP-клайентов начались retry policy, откуда они берут токены и откуда у них в юзер-агенте прописался какой-то хедр. +2744.36 2748.24 "Анатолий Кулаков" В общем, это все такая скрытая магия получается. +2748.24 2752.56 "Анатолий Кулаков" В общем, есть много способов борьбы со скрытой магией. +2752.56 2758.00 "Анатолий Кулаков" Доклады, документация, какие-то внутренние метапы и так далее. +2758.00 2761.00 "Анатолий Кулаков" Но просто нужно учитывать, что такая сложность скрытая, она у вас будет. +2761.00 2765.28 "Анатолий Кулаков" То есть, вы размениваете те бенефиты на какую-то магию. +2765.28 2770.64 "Анатолий Кулаков" В принципе, не так страшно, потому что, если задуматься, то весь ISP.net Core – это одна большая магия. +2770.64 2777.20 "Анатолий Кулаков" Каким образом эти запросы приходят и каким образом они выходят, довольно не все до сих пор знают. +2777.20 2787.16 "Анатолий Кулаков" Поэтому оценивайте риски, оценивайте сложности и применяйте очень хороший, интересный подход, очень хорошая, интересная статья за всеми подробностями и примерами. +2787.16 2788.56 "Анатолий Кулаков" Можно обращаться к ней. +2788.56 2798.36 "Анатолий Кулаков" Единственное, автор говорит, естественно, это СДК и все многие пакеты упомянутые, они есть на GitHub, поэтому берите, смотрите, пользуйтесь. +2798.36 2811.20 "Анатолий Кулаков" Единственное, автор упоминает, что не надо использовать этот СДК прямо его, такой, какой он написал, потому что он его писал под себя, под свои команды, под свои стандарты, под их собственные договоренности. +2811.20 2824.56 "Анатолий Кулаков" Поэтому, если вы хотите использовать такой же подход, вы можете форкнуть его СДК, адаптировать под те договоренности, которые есть в вашей компании, в вашей команде, и уже ее, вот этот СДК, которым вы договорились, уже его нужно использовать. +2824.56 2830.24 "Анатолий Кулаков" Так что, хороших вам настроек и единых стандартов для всех ваших проектов. +2830.24 2852.60 "Игорь Лабутин" Да, действительно, довольно мощная штука, но со своими проблемами, со своими тонкостями, и, наверное, это очень прикольно и удобно, когда у вас, не знаю, начиная, наверное, с десятков проектов, когда их, наверное, меньше десятка, может быть, нет смысла заморачиваться, хотя это интересный эксперимент, если вам интересно таким позаниматься, то почему бы и нет. +2852.60 2856.00 "Игорь Лабутин" Пока у вас, может быть, и меньше десятки проектов, потом будет больше, а у вас уже все готово. +2856.00 2865.56 "Анатолий Кулаков" Ну да, если вы на перспективу работаете, такой интересный инфраструктурный аспект получается, знаешь, когда можно подключить какой-то аспект, который дает тебе полностью новую инфраструктуру. +2865.56 2887.36 "Игорь Лабутин" Ну да, мне всегда нравилось возиться со всякими такими штуками около билдовыми, потому что она действительно работает как магия, то есть, когда оно все получает, его совершенно невозможно там отлаживать, было и так далее, особенно когда это MS Build таски были, зато когда это работает, это какая-то магия, ты собираешь, у тебя все автоматически обновляется, все здорово, валидируется, проверяется, вообще классно было. +2887.36 2890.56 "Анатолий Кулаков" Да, да, это великолепно, до тех пор пока оно работает. +2890.56 2893.56 "Анатолий Кулаков" В общем, а когда перестает работать, вот это уже было. +2893.56 2905.08 "Игорь Лабутин" Ну, снова засучиваешь рукава, либо отлаживаешь эту таску, либо придумываешь что-нибудь новенькое, а давай теперь напишем эту часть на питончик из криптом или на C# и так далее. +2905.08 2907.72 "Игорь Лабутин" Зато всегда есть работа, тоже здорово. +2907.72 2913.88 "Анатолий Кулаков" Да, да, да, если вы никогда не писали MS Build таски, то попробуйте, это действительно очень весело. +2913.88 2923.48 "Игорь Лабутин" Да, но мы пойдем дальше, и у нас таки единственная статья от Microsoft, это продолжение, точнее, это обещанная статья про сборку дотнета. +2923.48 2945.88 "Игорь Лабутин" Напомню, что я рассказывал про то, как устроена сейчас сборка дотнета, то есть, это большая виртуальная монорепа, которой собираются, на самом деле, ссылочки, точнее, не совсем ссылочки, сейчас расскажу подробнее, напомню, на другие репы всего того, что входит в дотнет, порядка 20 штук, и дальше все это собирается. +2945.88 2962.60 "Игорь Лабутин" И одна из ключевых фич, это то, что можно менять код, допустим, в продуктовых, так называемых, репах, то есть там какой-нибудь dotnet/runtime, dotnet/sdk, а можно менять в этой монорепе, dotnet/dotnet, и все эти изменения туда-сюда синхронизируются. +2962.60 2969.64 "Игорь Лабутин" И вот эта статья как раз довольно детально рассматривает, как это было сделано, зачем, почему и какие технологии используются. +2969.64 2972.32 "Игорь Лабутин" Поэтому давайте, собственно, разбираться. +2972.32 2988.72 "Игорь Лабутин" Ну, во-первых, напомню еще разок, действительно, есть то, что Microsoft называет virtual monolithic repository, это один-единственный гид-репозиторий, dotnet/dotnet, который содержит в себе весь исходный код и всю инфраструктуру, для того чтобы собрать dotnet/sdk. +2988.72 2993.88 "Игорь Лабутин" Утверждается, что достаточно склонировать этот репозиторий, и больше вам ничего не надо. +2993.88 2997.36 "Игорь Лабутин" То есть вроде как оно должно собираться даже на машине без интернета. +2997.36 3001.52 "Игорь Лабутин" Говорят, я пока не пробовал, но что-то у меня руки чешутся теперь попробовать. +3001.52 3004.92 "Игорь Лабутин" И посмотри, будет ли оно действительно собираться вообще без интернета. +3004.92 3005.92 "Игорь Лабутин" Посмотрим. +3005.92 3010.48 "Анатолий Кулаков" Слушай, ну заявление довольно смелое, откуда он возьмет компилятор-то? +3010.48 3011.48 "Игорь Лабутин" Самый главный вопрос. +3011.48 3012.48 "Игорь Лабутин" Хороший вопрос, да. +3012.48 3016.44 "Игорь Лабутин" Я пока не знаю, но я думаю, что я попробую. +3016.44 3023.08 "Игорь Лабутин" Может быть, даже попробую успеть к следующему выпуску, и, может быть, не полностью соберу, но хотя бы посмотрю, пытается ли, откуда он вообще берет компилятор. +3023.08 3024.84 "Игорь Лабутин" Ну или там поизучаю исходники. +3024.84 3031.20 "Анатолий Кулаков" Не могу же ли бинарник засунуть просто в репозиторий и все, какой-нибудь с компилятором, это же как-то будет совсем нехорошо. +3031.20 3039.08 "Игорь Лабутин" Это нехорошо, тем более, что по правилам линукса никаких как бы pre-built binaries быть не должно в репозитории, вроде как. +3039.08 3041.64 "Игорь Лабутин" Ну ладно, в общем, некоторый виртуальный репозиторий. +3041.64 3042.64 "Игорь Лабутин" Почему он называется виртуальным? +3042.64 3073.10 "Игорь Лабутин" Он, конечно, на самом деле вполне реальный, но он виртуальный из-за того, что это агрегация, как я сказал, всех репозиториев, то есть технически весь основной исходный код, и вся основная работа с исходным кодом .NET происходит в продуктовых репозиториях, то есть .NET Runtime, .NET SDK, .NET там чего-нибудь еще, Roslyn там, и они же в качестве директорий просто в этом виртуальном репозитории складываются тоже в нем как копии, ну а также там еще лежит некоторое количество скриптиков, которые нужны для собственной итоговой сборки. +3073.10 3099.16 "Игорь Лабутин" И самое главное, то, ради чего написано, то, о чем это написано эта статья, это механизм синхронизации, это двухсторонний синхронизатор, то есть разработчики могут работать в виртуальном репозитории, а могут работать в индивидуальном продуктовом репозитории, и все изменения туда-сюда автоматически синхронизируются через пул реквесты, поэтому оно автоматически, но не совсем автоматически, там есть, может быть, необходимость некоторого ручного вмешательства, сейчас мы до этого доберемся. +3099.16 3101.32 "Игорь Лабутин" Значит, как вообще все это начиналось? +3101.32 3119.16 "Игорь Лабутин" Исходно начиналось это все как требование, что вообще-то, ребят, для того, чтобы попасть в линуксовые дистрибутивы, в Ubuntu и прочее, нам нужно следовать следующим правилам, как я сказал, нам нужны только исходники, никаких бинарников, готовых заранее, и не должно быть доступ, ну, билд должен собираться без доступа в интернет. +3119.16 3120.16 "Игорь Лабутин" Что это означает? +3120.16 3129.52 "Игорь Лабутин" Ну, означает это, что нужно этот самый исходники как-то собрать в некоторый условный архивчик, который можно куда-то положить на машинку и на ней ее собрать. +3129.52 3135.44 "Игорь Лабутин" Для того, чтобы этот архивчик со исходниками собрать, раньше был следующий процесс. +3135.44 3182.72 "Игорь Лабутин" Мы .NET собирали по старинке из кучи разных репозиториев, но мы брали, грубо говоря, в момент сборки мы как-то собирали вот эти исходники, копировали их в отдельную папочку и так далее, в общем, получалось в итоге после всей большой сборки .NET, у тебя получалась отдельная папочка, куда скопированы все вроде как исходники .NET, из которых его теоретически можно бы и собрать, но выяснялось, что когда мы все это собираем вместе в единую кучу, то оно где-нибудь несовместимо, какие-то проблемы с сборкой, что-то с чем-то конфликтует, потому что напомню, что в основном .NET сборка, она была с бинарными зависимостями, то есть когда ты собираешь какой-нибудь .NET runtime, дальше он бинарно копируется в какие-то места, которым он нужен, например. +3182.72 3275.46 "Игорь Лабутин" В результате была использована механика, так называемая source build patches, то есть от начала это следующее, что мы взяли .NET, мы собрали обычный .NET с .DK как надо, параллельно мы подготовили вот этот самый архивчик условный с исходниками, которые можно положить в какой-нибудь Linux, но если мы выяснили, что этот архивчик почему-то не собирается, то мы брали какие-то, ну мы фиксили те самые проблемы, из-за которых он не собирался, прямо в коде, который вот собрался в этом архиве, не в исходниках, а прямо в этом коде, потому что эти изменения были нужны именно для сборки там под конкретный Linux, и в целом вроде бы и нормальный вариант, если бы эти изменения обратно клались бы в upstream, но это не всегда происходило, плюс не всегда это было возможно сделать, потому что изменения были специфическими и не нужны для всех платформ, например, или очень специфичны именно для вот этого unified source build, и поэтому это была проблема, то есть эти source build патчи, с ними надо было что-то делать, потому что если мы изменили .NET и собираем какую-нибудь следующую версию, следующую превью, то по сути эти source patch надо было либо генерить заново, либо переприменять, а код изменился, ну всякие разные проблемы, поэтому пошли делать следующую стадию, назывался это vvmr, virtual monolithic repository, light, read-only mirror, т.е. +3275.46 3307.22 "Игорь Лабутин" только для чтения, сделали следующее, от архивчиков отказались, перешли в git-репозиторий, именно в этот момент родился репозиторий .NET/.NET, и по сути это было просто зеркало только для чтения, синхронизация была только в одну сторону, т.е. мы из продуктовых репозиториев все аккуратненько копировали в вот этот git-репозиторий, выкидывали по пути всякие ненужные бинарники и все то, что не нужно для линукс билда, и ровно вот этот read-only репозиторий использовался для того, чтобы собирать восьмерку и девятку .NET на линуксе. +3307.22 3310.10 "Игорь Лабутин" Оно вполне успешно работало, нормально. +3310.10 3316.02 "Игорь Лабутин" И вот третья стадия, это то, где мы находимся сейчас, это уже этот vmr, который можно писать. +3316.02 3340.58 "Игорь Лабутин" Значит, цель следующая, что нам, как я говорил в прошлый раз, цель такая, чтобы процесс сборки обычного SDK, который Microsoft поставляет, и процесс сборки open-source линуксового билда были одинаковыми, ну с поправкой на то, что майкрософтский билд естественно включает в себя больше компонентов, которые там винду и т.д., но именно сам процесс должен быть одинаковый, вопрос только в списке исходных компонентов. +3340.58 3357.42 "Игорь Лабутин" Самое большое изменение, что этот vmr.net.net.salt.pl в нем была разрешена запись, и поэтому нам нужно было теперь поддерживать два так называемых flow, т.е. +3357.42 3372.54 "Игорь Лабутин" нам нужно, чтобы каждый продуктовый репозиторий синхронизировался в этот виртуальный репозиторий, ну он реальный, в смысле как копия, и обратно, нам нужно, чтобы изменения, которые мы сделали в vmr.net.net.salt.pl синхронизировались обратно. +3372.54 3374.10 "Игорь Лабутин" Зачем нам делать изменения в vmr.net.net.salt.pl? +3374.10 3377.02 "Игорь Лабутин" На самом деле это довольно оказалось удобным, т.е. +3377.02 3398.82 "Игорь Лабутин" исходно, как я понял статью, это рассматривалось ну не как основной кейс, но сейчас это иногда используется для фич, когда вы затрагиваете несколько репозиторий, т.е. например, если вы делаете какой-то рефакторинг, который затрагивает несколько репозиторий одновременно в дотнете, то теперь его гораздо удобнее сделать в едином монолитном репозитории одним-единственным пиаром. +3398.82 3405.86 "Анатолий Кулаков" Т.е. они нашли такой компромисс между монорепой и распределенными вот этими мелкими репозиториями, микросервисами, по сути. +3405.86 3406.86 "Анатолий Кулаков" По сути. +3406.86 3413.26 "Анатолий Кулаков" У монорепов всегда было преимущество, что их легко рефакторить, а у как бы мелких репозиториев, что их легко поддерживать и делить между командой. +3413.26 3414.82 "Анатолий Кулаков" Тут смотри, и то и все получили. +3414.82 3418.82 "Игорь Лабутин" Да, и то и все получилось, но ценой того, что нужно эти изменения туда-сюда гонять. +3418.82 3423.06 "Анатолий Кулаков" А это скорее всего большие конфликты должны быть. +3423.06 3424.06 "Игорь Лабутин" Вот. +3424.06 3425.06 "Игорь Лабутин" Вот. +3425.06 3426.06 "Игорь Лабутин" Значит. +3426.06 3430.24 "Игорь Лабутин" Соответственно, ты прав, есть проблемы. +3430.24 3437.10 "Игорь Лабутин" Как это работает, значит, ну, во-первых, давай начнем с самого начала. +3437.10 3446.90 "Игорь Лабутин" Гид-репозиторий - это на самом деле тоже неочевидный выбор, ну в смысле сам гид-репозиторий - это может быть очевидный выбор, но внутри гид-репозиторий можно сделать много чего другого. +3446.90 3451.02 "Игорь Лабутин" Т.е. например, можно было бы все эти репозитории продуктовой затащить сабмодулями. +3451.02 3453.22 "Игорь Лабутин" Как тебе идея? +3453.22 3458.98 "Анатолий Кулаков" Те, кто хоть раз в жизни использовал сабмодули, они больше второй раз никогда в жизни не будут использовать +3458.98 3459.98 "Игорь Лабутин" сабмодули. +3459.98 3460.98 "Игорь Лабутин" Все так. +3460.98 3461.98 "Анатолий Кулаков" Кроме того... +3461.98 3462.98 "Анатолий Кулаков" Это самая проклятая фича Китая, я думаю. +3462.98 3463.98 "Игорь Лабутин" Да. +3463.98 3486.54 "Игорь Лабутин" Кроме того, на самом деле, это чуть-чуть усложняет задачу собрать без интернета, потому что это надо сделать фич, потом рекурсивный фич всех сабмодулей, а исторически сложилось так, что в продуктовых репозиториях на самом деле тоже бывают сабмодули, т.е. в них тоже надо будет рекурсивно еще раз зафичить сабмодули, ну короче, не вариант. +3486.54 3492.54 "Игорь Лабутин" Потом там было еще некоторое количество разных вариаций, ну в общем пришли к тому, что нам нужен не кастомный процесс, без него никак. +3492.54 3498.42 "Игорь Лабутин" Значит, что сделали? +3498.42 3508.10 "Игорь Лабутин" Значит, сделали примерно следующее, что файлы в виртуальном этом самом репозитории - это просто, ну по сути, копия. +3508.10 3527.42 "Игорь Лабутин" То есть мы в виртуальном репозитории коммитим некоторые снэпшоты того, что происходит в продуктовом репозитории, причем, возможно, неполные, то есть это не значит, что у нас, например, в этом VMR-е есть полная копия dotnet/sdk, там она есть, но только за исключением тех файлов, которые мы точно знаем, что для линуксового билда не нужны. +3527.42 3536.42 "Игорь Лабутин" Вот, то есть, или еще что-нибудь такое, то есть те, которые не нужны для сборки, так скажем, вот. +3536.42 3542.34 "Анатолий Кулаков" Ну это такая преждевременная оптимизация, да, то есть это, в принципе, компилятор сам мог бы выяснить, что они ему не нужны и не использовать. +3542.34 3558.10 "Игорь Лабутин" Не совсем компилятор, нет, нет, нет, для сборки именно микрософтской версии - да, но для того, чтобы иметь возможность сказать линуксовым дистрибутивам "вот, возьмите этот git-репозиторий и из него собирайте", в нем не должно быть бинарников. +3558.10 3564.26 "Игорь Лабутин" Не то, что там они есть, но компиляторы их не используют, а их там быть не должно, по правилам. +3564.26 3567.06 "Анатолий Кулаков" То есть это так, чтобы просто соответствовать комплайну? +3567.06 3569.66 "Игорь Лабутин" Ну да, да, да, да, чтобы… Чуть более строгий. +3569.66 3571.02 "Игорь Лабутин" Да, да, да, да. +3571.02 3587.42 "Игорь Лабутин" Собственно, возникает вопрос, ну окей, есть у нас репозиторий, тут копия одного, тут, ну, есть, не знаю, репозиторий тут нет runtime, есть его копия, по сути, какие-то снапшотики, которые коммитятся в EMR в какой-то момент, как вообще эти изменения туда-сюда гонять? +3587.42 3594.54 "Игорь Лабутин" Ну, возникла первая мысль, окей, у нас есть стандартный, раз мы используем git, то у нас есть что? +3594.54 3597.06 "Игорь Лабутин" Правильно, у нас есть патчи. +3597.06 3601.98 "Игорь Лабутин" Обычные стандартные гитовые патчи. +3601.98 3616.42 "Игорь Лабутин" То есть мы можем сказать git diff --patch --binary для того, чтобы все эти чинджи сгенерить, зная откуда-докуда, мы про это поговорим чуть позднее, пойти в другой репозиторий и сказать git apply. +3616.42 3628.82 "Игорь Лабутин" Причем git apply он умный, он проверит, что на самом деле он правильно все, ну, в смысле, что там не будет совсем уж кривых конфликтов, что вы будете применять изменения туда, куда надо, вот это все. +3628.82 3634.34 "Игорь Лабутин" То есть, короче, git apply, он какие-то базовые проверки проверяет, того, чтобы не применить патчи вообще к какому-то левому коду. +3634.34 3668.34 "Игорь Лабутин" Плюс, подход с патчами хорош тем, что он на самом деле захватывает изменения не только с исходным кодом, в смысле, что вы поменяли контент файлов, но вы могли поменять, например, права на файлах, добавить исполнимый битик, ну, в смысле, не битик, как его, флаг, да, хорошее русское слово permission, вот, permission на исполнение, например, и это тоже в git отрекается, и git patch умеет это дело, git div точнее, оптай патч умеет это дело сохранить в патч файл и применить в другом git репозитории. +3668.34 3682.50 "Игорь Лабутин" Все замечательно, все здорово, была только с этим делом только одна проблема, знаешь ли ты, что в git вот этих патчек, да, в команде git apply есть лимиты на размер патча? +3682.50 3687.66 "Анатолий Кулаков" Слушай, они же применяются в линуксовском ядре, какие там могут быть после этого лимиты? +3687.66 3694.30 "Игорь Лабутин" Тем не менее, лимиты есть, оказалось, что git apply не умеет работать с бинарными патчами размером больше гигабайта. +3694.30 3696.34 "Анатолий Кулаков" А нам надо, да? +3696.34 3701.70 "Игорь Лабутин" Да, оказалось надо, .NET умеет генерировать гид патчи размером больше гигабайта. +3701.70 3706.78 "Игорь Лабутин" Меня тоже это удивило, но как бы, ну вот так. +3706.78 3733.62 "Игорь Лабутин" Короче, они столкнулись с этим лимитом, поэтому пришлось его поддерживать, они в этом случае, ну там логика примерно такая, они пытаются сделать гид див на корневой директории вот этого продуктового репозитория, если полученный, ну или там, когда они обратно, это скорее, наверное, проблема, когда они обратно синхронизируют, но тем не менее, то есть если получается патч размером больше гига, они просто рекурсивно по каждой из под директорий это делают, ну и разбивают на несколько мелких патчей. +3733.62 3736.86 "Игорь Лабутин" В принципе это как бы одно и то же. +3736.86 3737.86 "Анатолий Кулаков" Ну тем не менее. +3737.86 3742.50 "Анатолий Кулаков" Не надо же загоняться и делать более мелкие изменения, вот это все слишком сложно. +3742.50 3743.50 "Анатолий Кулаков" Да-да-да. +3743.50 3744.50 "Анатолий Кулаков" Да, ну вот. +3744.50 3745.50 "Анатолий Кулаков" Не для этого все объединяли. +3745.50 3746.50 "Игорь Лабутин" Да. +3746.50 3750.82 "Игорь Лабутин" Это, соответственно, такая чистая механика, то есть мы берем патчи и переносим их туда-обратно. +3750.82 3753.06 "Игорь Лабутин" Это именно как перенести изменения. +3753.06 3757.94 "Игорь Лабутин" Возникает вопрос, а как понять откуда-то мы эти изменения собирать? +3757.94 3759.98 "Игорь Лабутин" Потому что нужно знать, как бы, что поменялось-то. +3759.98 3764.58 "Игорь Лабутин" Для этого у нас есть механизм отслеживания, что где закомичено. +3764.58 3780.06 "Игорь Лабутин" В продуктовом репозитории есть файлик, в котором трекается последний коммит, который был отправлен в VMR, а в VMR, соответственно, есть файлик, который трекает… Точнее не так. +3780.06 3791.06 "Игорь Лабутин" В продуктовом репозитории есть коммит, последний коммит получен из VMR, то есть коммит ID из VMR-репозитории, а в VMR-е, наоборот, файлик, в котором есть коммит ID, последний полученный из продуктового репозитории. +3791.06 3793.30 "Игорь Лабутин" Таким образом, мы знаем, какой мы последний получили. +3793.30 3799.98 "Игорь Лабутин" Ну, мы знаем последний latest, head, так сказать, гид репозитории того бранча, который мы хотим синхронизировать. +3799.98 3803.94 "Игорь Лабутин" Ну и вот, соответственно, мы знаем, откуда, куда нужно взять в одну сторону и откуда, куда нужно взять в другую сторону. +3803.94 3810.34 "Игорь Лабутин" Соответственно, мы отлично знаем, в чем диапазон. +3810.34 3824.98 "Игорь Лабутин" Но возникает проблема тонкая, которую пока еще не решили, а проблема тонкая заключается в том, что получается, что мы внутри гид репозитория с исходными кодами храним ссылку на то, какой коммит гид репозитория нужно забрать. +3824.98 3833.94 "Игорь Лабутин" И если мы хотим что-то поменять, ну, например, мы ошиблись по какой-то причине, и нам нужно поменять вот этот файлик. +3833.94 3837.26 "Игорь Лабутин" Замена этого файлика меняет гид коммита последнего коммита. +3837.26 3838.26 "Игорь Лабутин" Понятное дело. +3838.26 3839.26 "Анатолий Кулаков" Ну да. +3839.26 3840.26 "Игорь Лабутин" Ну да. +3840.26 3841.26 "Игорь Лабутин" И с этим есть некоторые проблемы. +3841.26 3844.90 "Игорь Лабутин" Есть проблемы, когда мы мержим какие-то мержи между бранчами. +3844.90 3849.74 "Игорь Лабутин" Как они пишут, этот файлик могли перезатереть, если не внимательно мержишь. +3849.74 3852.10 "Игорь Лабутин" Ну, в общем, стандартная проблема мержа. +3852.10 3853.10 "Игорь Лабутин" Туда-сюда. +3853.10 3863.02 "Игорь Лабутин" Ну, в общем, получается, что проблемы есть, поэтому они сейчас рассматривают другие варианты, как хранить эту информацию, не в файлике, а используя механизм git нодс. +3863.02 3866.06 "Игорь Лабутин" Знаешь ли ты, что к каждому объекту в гиде можно добавить заметки? +3866.06 3867.06 "Анатолий Кулаков" Да, безусловно. +3867.06 3876.94 "Анатолий Кулаков" Наверняка все сталкивались с гид тегами, по сути, это та же самая заметка, которая позволяет вам определенный коммит пометить какой-то магической информацией, какой-то магическими нодами. +3876.94 3877.94 "Игорь Лабутин" Да. +3877.94 3887.42 "Игорь Лабутин" Но это ты действительно, это как бы теги, теги знают, а можно, в принципе, любые нодс делать, я не помню, как их можно категоризировать, но есть команда, ну, в общем, git нодс поищите, если вам вдруг интересно. +3887.42 3911.66 "Игорь Лабутин" Вот они сейчас думают, может быть, этим поразвлекаться и использовать, потому что по факту тебе нужно хранить именно вот текущее состояние, да, история, конечно, интересна, но может быть она не так, то есть историю-то как раз можно хранить в исходниках, да, какой-нибудь файлик там закидывать, чтобы она менялась, но вот какую-то именно текущую, которую будут тулы использовать, хранить именно в git нодс, как последнее. +3911.66 3914.98 "Анатолий Кулаков" Да, тем более гид теги, гид нодс, они как раз не меняют коммит. +3914.98 3915.98 "Анатолий Кулаков" Да. +3915.98 3916.98 "Игорь Лабутин" Никак. +3916.98 3921.70 "Игорь Лабутин" Ну вот, значит, ну, собственно, как происходит синхронизация? +3921.70 3945.58 "Игорь Лабутин" Для начала, собственно, по большому счету, несмотря на то, что синхронизация двухсторонняя, она, в общем-то, это две односторонних, можно сказать, поэтому сначала рассматриваем одностороннюю, как происходит односторонняя синхронизация, то есть как происходит синхронизация из продуктовой репозитории в VMR, обратная она примерно такая же. +3945.58 3964.42 "Игорь Лабутин" Значит, во-первых, у нас все еще есть механизм тех самых source build патчей, то есть несмотря на то, что у нас есть дотнет, пачка дотнет репозиториев, когда мы их всех собираем в единую монорепу, все еще нужны иногда некоторые патчи для того, чтобы все это собралось в едино, когда оно в едином репозитории. +3964.42 3981.50 "Игорь Лабутин" Я не смотрел специфику зачем, но говорят, надо, поскольку эти патчи, по сути, накатаны поверх того, что пришло из соседних репозиториев, то оно помешает, ну, апплай просто, скорее всего, зафейлится, если это же место поменяли в исходно-продуктовом репозитории, поэтому алгоритм такой. +3981.50 3987.06 "Игорь Лабутин" Сначала мы откатываем все source build патчи из VMR, ну, в каком-то бранче мы это делаем. +3987.06 4073.38 "Игорь Лабутин" Дальше для каждого репозитория мы откатываем некоторый дополнительный контент, то есть там есть механизм, который позволяет тебе не просто синхронизировать изменения из, допустим, дотнет рантайма, а сказать, что а еще в дотнет рантайм VMR затащи, пожалуйста, ресурсы из вот там, например, другого репозитория, то есть там довольно развесистая XML-ная конфигурация, которая говорит, что надо не просто затащить, синхронизировать изменения из там, ну, продуктового соответствующего репозитория, но и поверх дополнительно замапить что-то куда-то там из инсталлера какого-нибудь, потому что понятно, что, например, инсталлер как таковой при сборке на линуксе не нужен, это виндовая специфика, но в инсталлере лежит часть ресурсов, которые могут быть полезны для линукса тоже, их нужно как-то забрать, вот это делается таким специально, называется это Additionally Mapped Content, короче, его тоже откатываем, создаем патч в оригинальном репозитории, применяем его в VMR, проверяем сабмодули, напомню, что в исходном репозитории могут быть сабмодули, поэтому для них мы повторяем все это рекурсивно также, то есть для них мы тоже их обновляем в исходном репозитории, подготавливаем патч, применяем все патчи, сабмодулей уже в VMR нету, там все только снапшотами все сидит, после чего накатываем обратно Mapped Content и накатываем обратно Source Bill патчи, ну нормальный, понятный прямой алгоритм. +4073.38 4103.30 "Игорь Лабутин" Но, как только мы накатываем патчи, у нас могут быть проблемы, что может пойти не так, сначала был использован подход мержей, что делается, берем обычный стандартный бранчинг, то есть мы создаем бранч в таргетном репозитории, то есть в VMR, например, применяем туда патч и открываем pull request. +4103.30 4116.78 "Игорь Лабутин" Проблема как бы заключается в том, что у вас может быть такое, что в репозитории вы поменяли файлик из A в B, а в VMR в этот момент другой разработчик поменял из A в C. +4116.78 4127.74 "Игорь Лабутин" Понятно, что все эти синхронизации, они не там миллификутные, а все-таки происходят с каким-то достаточно возможно большими интервалами, и, соответственно, может быть такое, что файлик поменен там и там. +4127.74 4128.74 "Игорь Лабутин" Но это конфликт. +4128.74 4138.66 "Игорь Лабутин" И таких изменений, таких конфликтов на самом деле именно технических было довольно много. +4138.66 4161.04 "Игорь Лабутин" Но проблема в том, что большая часть из них — это не потому, что это реальный конфликт файлов, а потому, что вот эта синхронизация запускается не каждую условную секунду, и она не могла иногда увидеть, что на самом деле это линейная история, но все-таки, и там можно все мержить, это на самом деле не конфликт, но технически средствами ГИТА он понимал, что это конфликт. +4161.04 4173.04 "Игорь Лабутин" Если интересно, я сейчас не буду пытаться на словах описать все эти диаграммы, там в статье прямо есть красивые ГИТовые диаграммы, где написано, почему такое возникает, с последовательностью коммитов, кто кому парент, и вот это все. +4173.04 4200.72 "Игорь Лабутин" А самая главная проблема со всеми этими мержами была в том, что при обычном нормальном процессе разработки, когда мы имплементим фичу, иногда мы ее ревертим, то есть мы написали код, а потом мы его заревертили, и вот синхронизировать такие изменения, это прям было довольно сложно, в том плане, что результирующий ГИТ-патч иногда довольно-таки, ну, выглядел странно с точки зрения системы. +4200.72 4208.52 "Игорь Лабутин" В общем, эта логика синхронизации, она немножко как бы путалась и не понимала, что ей делать, вот. +4208.52 4217.64 "Игорь Лабутин" Иногда они теряли вот эти реверт-коммиты, и в итоге как бы получалось так, что фичу вроде удалили из сходного репозитория, а в VMware она есть. +4217.64 4246.40 "Игорь Лабутин" Это, в общем, приводило к проблемам, проблем было довольно много, поэтому перешли на другую версию, которая сейчас используется, которая озаглавлена кодовым именем Interactive Rebase, то есть они не пытаются мержать бранчи, то есть они так же создают бранч, все дела, но они пытаются, после того, как они сделали бранч, на который накатили патч, они пытаются его отребейзить поверх текущей головы в VMware, вот. +4246.40 4311.92 "Игорь Лабутин" Ну, соответственно, если при этом возникает конфликт, а при ребейзе, если какие-то проблемы, возникнет конфликт, то система теперь не пытается ничего делать, она просто останавливается и ничего не делает, и нужно, чтобы в этом пиаре пришел разработчик и что-то сделал, вот, руками, пофиксил какие-то моменты, после чего можно это закоммитить, ну и дальше система, понятно, продолжает автоматически работать, накатывает всякие нужные патчи, вот это все, это уже все делается автоматом, но вот этот момент, что если есть конфликт, должен прийти разработчик и посмотреть руками, он теперь есть, и надо сказать, что, казалось бы, нужно прийти и посмотреть руками, надо, но по факту оказалось, что таких моментов не очень много, и в целом этот подход сейчас как раз и работает, сейчас оно работает на таком штуке, то есть, грубо говоря, система этой синхронизации берет патч, закидывает в репозиторий назначения, в веточку, после чего эту веточку пытается отребейзить поверх головы, если получилось, ну здорово, не получилось, зовем разработчика, и разработчик посмотрит. +4311.92 4324.32 "Игорь Лабутин" Поскольку все это на GitHub и в пиарах, там всякие нотификации, уведомления, все работает, все замечательно, можно за пиарами смотреть, следить и понимать, что как, где подвисла синхронизация. +4324.32 4337.16 "Игорь Лабутин" Есть и проблемы сейчас, основные, с которыми, ну как, не проблемы, челленджи, что по-английски называется, которыми нужно сейчас что-то делать, про которые они думают. +4337.16 4342.76 "Игорь Лабутин" Во-первых, разные продукты имеют, как ни странно, разные расписания релизов. +4342.76 4406.24 "Игорь Лабутин" То есть, как мы знаем, как вы прекрасно слышите из нашего подкаста, релизы Visual Studio и релизы .NET, они, ну, в целом не связаны практически никак, вот, то есть, и возникает проблема, когда у нас есть, соответственно, репозиторий основной, бранчится для, правда, для там, релиза Visual Studio, если там нужны какие-то конкретные изменения, но VMR, он, соответственно, там сейчас бранчится параллельно для того, чтобы релизить SDK, и, в общем, там, я так понимаю, что с этим есть какие-то проблемы, потому что они как-то должны соотноситься, и эти изменения как-то должны гулять между бранчами, типа изменения из бранча для Visual Studio должны появиться в бранче для SDK, вот с этим пока есть некоторые проблемы, ну, и нужно, соответственно, эти PR-ы правильно переносить между бранчами, иногда бывает такое вручную, вот, ну, к счастью, вроде как пишут, что это не такая большая проблема, ну, частая проблема, но она есть. +4406.24 4534.80 "Игорь Лабутин" Дальше была проблема с релизными бранчами, то есть, если у нас, например, вы работаете над какой-то фичой, и вы поняли, что эта фича пойдет, ну, вот сейчас, например, у нас момент, когда мы можем сказать, окей, у нас скоро будет .NET Preview 1, я такой, окей, я буду писать первую фичу для Preview 1, я ее буду писать в Monorep, потому что она там затрагивает все, ну, там, несколько репозиториев, и я в Monorep создаю бранчу Preview 1, а в продуктовом репозитории такого бранча еще нет, и система такая, а что куда синхронизировать, непонятно, ну, то есть, как бы что-то надо, но куда непонятно, вот, сейчас, соответственно, есть для этого централизованный тул, который просто одновременно создает везде нужные бранчи, когда нужно, вот, ну, и как я говорил, есть проблема с тем, что мы храним метаданные в самом репозитории, и поэтому из-за мержей может получаться так, что эти метаданные немножко корраптятся в этих файлах манифестов, ну, приходится аккуратно мержить, вот, так что такие дела, при этом, несмотря на недостатки системы, сейчас позволяет, в общем-то, сотням девелоперов спокойно работать над этими десятками, двумя десятками репозиториев, то есть не знаю, на сколько там прям сотни, но, в принципе, open-source-ных коммитиров тоже довольно много внутри Microsoft, над каждым из кусочков разных бруталентов работают разные команды, так что, наверное, сотня там действительно наберется, вот, при этом можно работать как в индивидуальном репозитории, так и в большом Monorepi, пожалуйста, синхронизация в целом офигенно сложная штука, то есть как ты говорил, что ты получил бенфиты и индивидуальных микросервисных репозиториях и большого, это прям как бы, да, это ты получил бенфиты, но ценой огромнейшей сложности, требуется прям отдельная команда, ну, хотя бы несколько человек, которые поддерживают всю синхронизацию и радость, туда-обратно работающую, плюс это требует некоторой ручной работы от команды, в том числе, потому что теперь регулярно прилетают пиары просто ради того, чтобы синхронизировать исходники, вот. +4534.80 4544.40 "Анатолий Кулаков" Ну, напоминает мне чем-то философию девопса, то есть мы взяли себе, усложнили проблемы в сто раз, вынесли это в отдельную команду и больше они нас не касаются. +4544.40 4561.40 "Игорь Лабутин" Ну, в каком-то смысле, ну, может быть, это проще, ну, мы при этом решили проблему, да, как бы сборки под Linux, которая иначе бы, ну, решалась тоже довольно бы сложными способами, и вряд ли они бы начали решать эту проблему, не будь проблем, как бы, каких-то больших со сборкой на Linux. +4561.40 4565.56 "Анатолий Кулаков" Нет, подожди, зачем им нужно было обратно тащить коммиты? +4565.56 4573.16 "Анатолий Кулаков" Ну, то есть самая большая проблема в том, что они из монорепозитория начали почему-то, не оставили его редонли, а начали почему-то тащить его исходники в апстримы. +4573.16 4574.16 "Анатолий Кулаков" Ну, это было странное решение. +4574.16 4575.16 "Анатолий Кулаков" Ну, удобненько, удобненько работать. +4575.16 4579.00 "Анатолий Кулаков" Типа удобненько, да-да, может и удобненько, но идеологически абсолютно неверно. +4579.00 4593.48 "Игорь Лабутин" Ну, смотри, с другой стороны, как я говорил, есть некоторые изменения, которые ты делаешь при сборке в общей большой репозитории, и было бы неплохо, если эти изменения совместимы с обычной жизнью в обычном репозитории, их заапстримить. +4593.48 4595.16 "Игорь Лабутин" И это простой способ. +4595.16 4598.96 "Анатолий Кулаков" Не делай, не делай там, нельзя делать мастер-то мастер. +4598.96 4601.16 "Анатолий Кулаков" Как только начинаешь делать мастер-то мастер, у тебя начинаются конфликты. +4601.16 4608.96 "Анатолий Кулаков" Ну… У тебя апстрим должен быть мастером, а все остальное — это чисто вьюшка, вьюшка, она редонли всегда должна быть. +4608.96 4616.68 "Игорь Лабутин" Возможно, это сильно усложнит апстрим, если тебе нужно при этом это собрать для линуксов, т.е. тебе придётся какую-то кастомизацию поддержать. +4616.68 4617.68 "Игорь Лабутин" Ну, в общем… +4617.68 4625.56 "Анатолий Кулаков" Есть условные директивы, там, есть всякие мейкфайлы, и, в конце концов, тоже самый msbuild, который умеет абсолютно всё. +4625.56 4637.16 "Игорь Лабутин" Да-да-да, мне это напоминает очень давние времена, когда ты заходил в какой-нибудь там, не знаю, windows.h, если ты помнишь такое, на плюсах, и там это и в деф, и в деф он погоняет. +4637.16 4651.48 "Анатолий Кулаков" Да, а ты посмотри на сборку всех программ под линукс, это make, makeinstall, makeconfigure, вот это же все 10 тысяч конфигураций, это же не просто так придумано, они придуманы, потому что там сложность огромная под всевозможные процессоры и платформы этот компилировать. +4651.48 4653.40 "Анатолий Кулаков" Но путь уже есть, люди его прошли. +4653.40 4670.68 "Игорь Лабутин" Да, но, опять же, вспомни, что мы обсуждали в конце прошлой статьи, про то, что заниматься build.dom — это клёво, весело и интересно, поэтому ребята нашли проблему, ребята решили проблему, они нашли по пути ещё кучку проблем, теперь они решают ещё кучку проблем, отлично, команда занята, всем интересно, всё супер. +4670.68 4674.52 "Анатолий Кулаков" Ну, с этой точки зрения, безусловно, одобряем. +4674.52 4675.52 "Игорь Лабутин" Да? +4675.52 4676.52 "Игорь Лабутин" Молодцы. +4676.52 4689.76 "Игорь Лабутин" Попробую, если хватит времени, что-нибудь собрать ради интереса, если получится, там в какой-нибудь из следующих разов расскажу, что из этого получилось, хотя бы в рубрике кратко о разном, может, что-нибудь, свои собственные впечатления о сборке дотной расскажу. +4689.76 4690.76 "Анатолий Кулаков" Давай, давай. +4690.76 4693.88 "Анатолий Кулаков" Вы выясни, самое главное, откуда они берут первоначальный компьютер. +4693.88 4698.72 "Игорь Лабутин" Да-да-да, мне самому интересно стало, да, мне самому это стало интересно, я попробую разобраться. +4698.72 4699.72 "Игорь Лабутин" Вот такие дела. +4699.72 4700.72 "Игорь Лабутин" Собирайте дотнет. +4700.72 4701.72 "Игорь Лабутин" Больше разных дотнет. +4701.72 4709.12 "Анатолий Кулаков" И смотри, вот эта вся схема, она упростила то, что было раньше. +4709.12 4711.64 "Анатолий Кулаков" То есть вот эта упрощённая схема того, как собирается +4711.64 4712.64 "Игорь Лабутин" дотнет. +4712.64 4720.48 "Игорь Лабутин" Ну, смотри, она в каком-то смысле упрощённая, потому что для тебя, как вот, ну, и для меня, например, да, как человека, который будет собирать дотнет, это действительно просто ридонли штука. +4720.48 4727.28 "Игорь Лабутин" Как там туда попадает и с какими сложностями команда сталкивается, чтобы вмёрзнуть очередной пиар в эту монорепу, это как бы не мои проблемы. +4727.28 4730.64 "Игорь Лабутин" И мне эта штука как бы, ну, упростила, да. +4730.64 4736.80 "Анатолий Кулаков" Ну, да-да, в принципе, с этой точки зрения удобное решение получилось. +4736.80 4740.20 "Игорь Лабутин" А они, как вентер, прекрасно знают, что с этим делать. +4740.20 4741.20 "Игорь Лабутин" Вот. +4741.20 4748.32 "Игорь Лабутин" Ну, да, с этим, наверное, всё с билдами, на сегодня у нас осталось только кратко о разном, давай быстренько по нему попробуем пробежаться. +4748.32 4749.32 "Анатолий Кулаков" Давай. +4749.32 4759.32 "Анатолий Кулаков" Прежде всего наткнулся на статью на хабре, которая называется JSON to LINQ, то есть там автор изобрёл стилизацию фильтрации в Expression Trees. +4759.32 4763.56 "Анатолий Кулаков" Ну, в принципе, задача довольно нужная. +4763.56 4764.56 "Анатолий Кулаков" Зачем нужная? +4764.56 4767.04 "Анатолий Кулаков" Наверняка все из вас видели UI-ки. +4767.04 4769.48 "Анатолий Кулаков" У UI-к, как всегда, есть гриды. +4769.48 4777.32 "Анатолий Кулаков" Эти гриды все любят сортировать, фильтровать и перемещать там колоночки между ними, короче, всячески кастомизировать и баловаться. +4777.32 4788.80 "Анатолий Кулаков" И вот как только вы сталкиваетесь с этой необходимостью, а с ней вы сталкиваетесь обязательно, как только у вас там больше пяти элементов в этом вашем гриде, то у вас приходит задача как бы в голову, а как все это передать на сервер. +4788.80 4798.60 "Анатолий Кулаков" То есть, по сути, мы хотим сериализовать фильтр в некое представление, передать его на сервер, а на сервере мы очень любим фильтры представлять в виде Expression Trees. +4798.60 4806.32 "Анатолий Кулаков" Для того, чтобы закинуть его, конечно же, в базку, там оно сконвертируется все в SQL, чтобы SQL нам достал необходимые нужные компоненты. +4806.32 4807.32 "Анатолий Кулаков" Вот. +4807.32 4811.84 "Анатолий Кулаков" Я думаю, каждая крупная компания пишет обязательно собственную такую фигню. +4811.84 4815.60 "Анатолий Кулаков" У Microsoft была OData, это немножко можно сравнить с Google. +4815.60 4816.60 "Анатолий Кулаков" С GraphQL. +4816.60 4825.16 "Анатолий Кулаков" Короче, все компании более-менее пытаются решить эту штуку, но так как до сих пор нет нормального общепризненного стандарта, все пишут заново. +4825.16 4832.52 "Анатолий Кулаков" В принципе, в сети тоже бывает очень много уже библиотек под эту тему, но вышла еще одна, но почему бы и нет, не самая плохая. +4832.52 4835.96 "Анатолий Кулаков" И вот про нее автор на Хабре как раз написал и статейку. +4835.96 4843.96 "Анатолий Кулаков" Для тех, опять же, кто хочет разобраться в теме, как это пишется, зачем это нужно и может быть даже завязать в своих проектах, потому что библиотека получилась довольно мощная. +4843.96 4845.56 "Анатолий Кулаков" В общем, почитайте статью на Хабре. +4845.56 4851.08 "Анатолий Кулаков" Она позволяет сериализовать как раз фильтр и сериализовать его почему-то в JSON. +4851.08 4857.96 "Анатолий Кулаков" Автор утверждает, что это удобный формат, но в принципе JSON это самый убогий формат, который только можно вообще придумать. +4857.96 4860.20 "Анатолий Кулаков" Тем более для фильтрации, в общем, Монга не даст соврать. +4860.20 4868.56 "Анатолий Кулаков" Но, в принципе, как показали наши опшнсы, нет предела человеческой глупости, поэтому пусть будет JSON. +4868.56 4881.00 "Анатолий Кулаков" Конвертируются эти, как раз он конвертирует эти фильтры, умеет конвертировать из JSON в линку, при том с учетом Entity Framework, он знает про все линкопровайдеры, он не то что знает, что у него зависимости есть. +4881.00 4883.68 "Анатолий Кулаков" Естественно, никаких внешних зависимостей у него нет. +4883.68 4887.56 "Анатолий Кулаков" Просто он умеет, понимает и знает для чего это используется. +4887.56 4892.24 "Анатолий Кулаков" В общем, эта реализация получилась довольно решаемая, настраиваемая, гибкая. +4892.24 4899.56 "Анатолий Кулаков" Пока там нет селектов, грубаев, там только фильтры, но, в принципе, ничего не мешает их добавить. +4899.56 4903.20 "Анатолий Кулаков" Следующая интересная библиотечка – это Localization Resource Manager. +4903.20 4910.64 "Анатолий Кулаков" Это библиотека, которая помогает вам локализовать ваши строковые ресурсы, то есть, по сути, переводить на разные другие языки. +4910.64 4920.84 "Анатолий Кулаков" Опять же, тема не нова, существует еще с тех пор, как появились UI-ные интерфейсы, очень много инструментов есть и еще один, в принципе, кажется, что не самый плохой. +4920.84 4932.80 "Анатолий Кулаков" Базовая его бесплатная версия представляет собой Common Line утилиту, которая умеет не просто пользоваться какими-то сайтами-переводчиками, но и подключает различные иишные модели, как локальные, так и нелокальные. +4932.80 4954.24 "Анатолий Кулаков" Прекрасна тем, что она кроссплатформенная, опять же, из командной строки можно практически сделать все, что угодно, умеет обращаться с различным количеством файлов, есть хорошая UI-ка для терминала и для вебки, через которую это можно управлять, переводом ресурсов смотреть, сколько ресурсов переведено, какими-то блоками, секциями двигать и так далее. +4954.24 4955.24 "Анатолий Кулаков" В общем, удобно, красиво. +4955.24 4969.44 "Анатолий Кулаков" Поддерживается множество форматов, естественно, .NET-овский RISX, какой-то JSON-специальный транслейт, андроидовский, IOS-ный, GetText-овый, XLIF-овый, в общем, много хороших форматов, больших и разных. +4969.44 4986.72 "Анатолий Кулаков" Так, из нового у нас в сообществе SPB.NET вышло еще 4 новых записи, их с тех пор, как мы с вами не виделись, это доклад, видеодоклад Дмитрия Егорова, все записи можно посмотреть на нашем YouTube или ВКонтакте, в ВКонтакте видео. +4986.72 4995.52 "Анатолий Кулаков" Дмитрий Егоров нам рассказывал про JIT и рассказывал, объяснял нам, что это совсем не волшебство и показывал, как он работает и как желательно ему не мешать. +4995.52 5011.60 "Анатолий Кулаков" В общем, вся вот эта магия JIT-а, как он умеет оптимизировать, почему он умеет оптимизировать, как он все раскладывает там на стеке, на куче, перемещает указатели, в общем, куча-куча интересных кишочных вот таких подкапотных JIT-овых магий было. +5011.60 5025.68 "Анатолий Кулаков" Дмитрий плотно общался с контрибьюторами из Microsoft, которые все это поддерживают, в общем, доклад получился довольно хорошим, глубоким, интересным, поэтому если для вас эта тема важна, то обязательно посмотрите. +5025.68 5032.48 "Анатолий Кулаков" Руслан Каменский рассказывал про криптографию в .NET и показывал нам, где заканчиваются гарантии безопасности. +5032.48 5042.12 "Анатолий Кулаков" Основной вывод из доклада можно сделать такой, что нельзя доверять тем дефолтным конструкторам, тем дефолтным параметрам и дефолтным алгоритмам, которые нам по умолчанию предлагает .NET. +5042.12 5048.20 "Анатолий Кулаков" Они очень многие устарели, очень многие неправильные, очень многие уже подвержены каким-то компрометациям и атакам. +5048.20 5058.84 "Анатолий Кулаков" Поэтому, если вы хотите узнать, как правильно использовать криптографию в .NET, про что нужно не забывать, как настраивать хотя бы на самом базовом уровне, в общем, доклад Руслана просто must have. +5058.84 5085.48 "Анатолий Кулаков" Также там была довольно внушительная секция про квантовые алгоритмы шифрования, мы в нашем подкасте уже упоминали, что в новом .NET у нас появились алгоритмы шифрования, хеширования квантовые, в общем, Руслан их тоже хорошо раскрыл, зачем, кому, куда, когда нужны, почему применялись и, в принципе, в дискуссионной зоне, то есть в вопросах эта секция вызвала больше всего интереса, в общем, там ее раскрыли еще глубже. +5085.48 5089.72 "Анатолий Кулаков" Доклад Георгия Тормозова про подводные камни регулярных выражений. +5089.72 5098.28 "Анатолий Кулаков" Георгий работает в PVS-студии и рассказывал как раз про опыт того, каким образом регулярные выражения могут уничтожить ваше приложение. +5098.28 5135.32 "Анатолий Кулаков" Вы тоже упоминали в нашем подкасте, что было несколько прецедентов, когда в регулярных выражениях находили прям как такие критические баги, которые напрочь могли подвесить все что угодно, а это значит, что правильно сформировав например какой-нибудь веб-запросик и бросив в ваше приложение, этот запросик просто-напросто мог повесить ноду, она выжирала там всю CPU, могла выжирать память, могла просто зависнуть в зависимости вот от той баги, которая существовала, и таких багов в регулярных выражениях их немало, в общем зная такие интересные особенности, можно было творить чудесные вещи с приложениями конкурентов, но мы ни к чему не призываем. +5135.32 5156.16 "Анатолий Кулаков" Так вот, Георгий четенько рассказал, как вся эта штука работает, почему возникают такие баги, как их искать, как их использовать, в каких приложениях они были найдены, в общем и много-много всего интересного, то есть как буквально, просто использование регулярных выражений можно убить все ваше приложение, интересно, познавательно тоже смотрите. +5156.16 5209.72 "Анатолий Кулаков" И четвертый доклад, это Дмитрий Нестюк рассказывал нам про элементы расширения в 14 C#, я надеюсь, постоянные слушатели нашего подкаста знают про экстеншн-мемберы, которые наконец в новой версии C# 14 нам зарелизили, не раз мы про них уже жужжали, не раз рассказывали, наверное еще и будем рассказывать, и вот Дмитрий как раз покрыл эту тему, как бы от нуля до скольки возможно, до 100% просто, обошел со всех сторон, посмотрел, как можно использовать какие-то интересные примеры, очень много оригинальных интересных способов использования экстеншн-мемберов, приводил в своем докладе, которых я нигде не встречал, в общем доклад тоже шикарный, обязательно посмотрите, если вы собираетесь использовать экстеншн-мемберы, ну а вы их по-любому собираетесь использовать, если вы уже перешли на десятку, то грех не использовать, поэтому тоже доклад замечательный. +5209.72 5245.04 "Анатолий Кулаков" Ну и экстеншн-мемберы, как я уже упомянул, это новая фича 10-го Дотнета, 14-го C#, и это одна из фич, в общем у нас 29 января будет митап специальный SPB.net, в котором мы рассмотрим еще некоторые фичи Дотнета 10-го и C# 14-го, мы его так и назвали, в митап в честь запуска Дотнета 10, и там будет выступать 14 докладчиков, то есть у нас будет 14 новых докладов, в общем если будете в Питере 29-го, заходите, милости просим, будет весело. +5245.04 5273.88 "Игорь Лабутин" Ну да, в общем, на этом на сегодня, наверное, мы будем заканчивать, довольно много новостей, ну не то что новостей, статей разных, напомню, что мы посмотрели на новую, кратенько на новую #DE, новая DE-шка для Дотнета, посмотрели, что делать с immutable коллекциями, как JonesKit с ними работает, посмотрели на сборку кастомного MSBuild SDK и посмотрели, как Microsoft синхронизирует виртуальные монорепозитории Дотнета туда-обратно. +5273.88 5276.96 "Игорь Лабутин" И на этом на сегодня будем заканчивать. +5276.96 5284.60 "Анатолий Кулаков" Да, всем большое спасибо, шары, репосты, колокольчики и комментируйте наши выпуски, всем пока, до новых встреч. +5284.60 5285.32 "Игорь Лабутин" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-61.txt b/input/Radio/Transcriptions/RadioDotNet-61.txt index 1ade5c7..d0a8512 100644 --- a/input/Radio/Transcriptions/RadioDotNet-61.txt +++ b/input/Radio/Transcriptions/RadioDotNet-61.txt @@ -1,899 +1,890 @@ -0.00 11.24 SPEAKER_00 Здравствуйте, дорогие друзья, в эфире Radio.net выпуск номер 61. -11.24 15.00 SPEAKER_00 Прежде всего, хотелось бы поблагодарить наших помогаторов. -15.00 24.00 SPEAKER_00 Это прекраснейший список – Александр, Сергей, Владислав, Алексей, Шевченко Антон, Илья и Гурий Самарин, что давно не растет, задумайтесь уже. -24.00 27.24 SPEAKER_00 Спасибо большое всем, кто нас поддерживает. -27.24 30.60 SPEAKER_00 И начинаем выпуск, что у нас там сегодня интересного? -30.60 37.00 SPEAKER_01 Ну, во-первых, хочется напомнить, что прошел онлайн.next 3-4 ноября. -37.00 39.04 SPEAKER_01 Если у вас есть билет, доступны все записи. -39.04 57.64 SPEAKER_01 Если у вас билета еще нет, то в шоуноутах вы найдете промокод на скидку, который позволит вам посмотреть, во-первых, прошедшие записи, во-вторых, попасть на онлайн просмотр офлайн дня 20 ноября, либо даже купить офлайн билет и встретиться, в том числе, с нами в Москве 20 ноября на офлайн-дне конференции. -57.64 60.80 SPEAKER_01 Приходите, будет, я думаю, интересно. -60.80 63.12 SPEAKER_00 Да, всех будем ждать на офлайне, заходите. -63.12 85.56 SPEAKER_00 Еще хотелось бы сказать, что наверняка вы этот выпуск уже будете слушать, когда .NET Conf идет или уже прошла, мы же записываемся еще до нее, поэтому сейчас в этом выпуске пока ничего про .NET Conf не будет, а вот следующий выпуск, я думаю, мы полноценно посвятим всем новинкам, которые анонсируют, которые выйдут, которые напишут статьи, бенчмарки, ну и прочее-прочее, что там посмотрим. -85.56 97.96 SPEAKER_00 А сейчас пока насладимся буквально несколькими днями тишины перед большими анонсами и посмотрим, что у нас еще интересно было, вышло, заанонсилось в мире .NET за то время, пока мы с вами не виделись. -97.96 101.96 SPEAKER_01 Ну, сильно много не заанонсилось, как мне кажется. -101.96 104.36 SPEAKER_01 Мы начнем с Entity Framework. -104.36 116.80 SPEAKER_01 Не то, чтобы это новый анонс, это на самом деле штука, про которую мы уже рассказывали, это performance improvement в Entity Framework 7, которые вышли еще в 6 превью, это пару или тройку превью назад. -116.80 140.76 SPEAKER_01 Однако же эта статья интересна тем, на самом деле это даже несколько статей, они интересны тем, что это не просто Microsoft показала, как они сделали круто, это реальные ребята посмотрели в достаточно таких, ну наполовину, скажем так, реально практических кейсах, насколько же получается выигрыш от этих всех изменений в EF. -140.76 154.80 SPEAKER_01 Причем надо понимать, что это все, поскольку превью, то прям совсем production, конечно на EF Core не переводили, но попытались эмулировать, что будет происходить в реальной жизни, когда вы реально развернете приложение. -154.80 166.92 SPEAKER_01 Напомню, что было сделано, собственно, с EF Core, они убрали возможность, невозможность, они убрали часть вызовов для явной работы с транзакциями. -166.92 181.28 SPEAKER_01 То есть, если вы делаете insert одной всего лишь записи, то делать два дополнительных round trip в базу, чтобы сказать begin transaction и end transaction, ну или commit transaction, как бы вроде странно, база данных и так сама автоматически сделает транзакцию на этот единственный insert. -181.28 194.72 SPEAKER_01 Поэтому эта штука была убрана, и мы на этом сэкономили два round trip, два round trip, ну вроде как, как бы немного с одной стороны, с другой стороны это две трети от всей операции записи, и казалось бы, должно стать лучше. -194.72 224.40 SPEAKER_01 Они действительно это проверили, и проверили они следующим способом, они взяли три кейса, это база данных на том же компе, где entity framework, то есть по сути на localhost, дальше берем ажурную регионы и говорим, что база данных будет лежать в том же регионе, что и код, но на разных машинках, и берем код в одном ажурном регионе, а базу данных в другом ажурном регионе, ну вдруг у вас такая георепликация, и почему-то ваше приложение решило пойти в соседний регион писать базу данных. -224.40 234.48 SPEAKER_01 В данном случае был выбран регион для базы, по-моему, Америка, US West, а для кода, соответственно, Europe West. -234.48 238.40 SPEAKER_01 Между ними, согласно ажурным данным, latency 72 миллисекунды. -238.40 246.52 SPEAKER_01 И чиселки получились следующие, для localhost, EFCore 7 по сравнению с EFCore 6, получило примерно 6% улучшения. -246.52 257.36 SPEAKER_01 Ну там скорее всего, конечно, сыграли роль и там оптимизация runtime и все остальное, но в целом какие-то оптимизации, ну на roundtrip, в том числе для localhost тоже время тратится. -257.36 272.08 SPEAKER_01 Если база данных живет в том же регионе, что и код, но на разных машинках, то мы получили 13% экономии времени, что уже, ну не так, чтобы сильно много, но достаточно много, учитывая, что это всего лишь один единственный инсерт. -272.08 284.64 SPEAKER_01 А в случае, если у вас база живет вообще в соседнем регионе, по какой-то причине, относительно кода, то вы получили 65% экономии, то есть по сути приложение в целом стало в 2 раза быстрее в этом конкретном аспекте. -284.64 285.72 SPEAKER_01 Это уже прям немало. -285.72 300.08 SPEAKER_01 Вторая штука, которая была изменена, это то, как обрабатывается multiple insert, то есть если вы сделали много раз insert, insert, insert, insert, а потом save changes, то EFCore делает следующую штуку. -300.08 305.76 SPEAKER_01 Во-первых, он батчит, то есть он объединяет все эти инсерты в батчи по несколько штук. -305.76 308.04 SPEAKER_01 Помнишь ли ты, какой размер батчи по дефолту? -308.04 310.04 SPEAKER_01 Нет, как-то не приводилось. -310.04 312.56 SPEAKER_01 Ну, это число нужно знать, это 42. -312.56 314.92 SPEAKER_01 А, 42, да, мы же обсуждали эту штуку. -314.92 325.56 SPEAKER_01 Да-да-да, он по дефолту 42, это действительно не поменялось, то есть это не было какой-то шуткой, в релизе, судя по всему, тоже будет 42, и оно так и есть, в тестах, по крайней мере, пока это подтверждается. -325.56 342.28 SPEAKER_01 EFCore, соответственно, объединяет инсерты в несколько, ну в батчи по 42 штуки, если их больше, чем 42, после чего использует, если это SQL Server, например, то SQL Statement под названием Merge, который позволяет как раз таки сделать инсерт. -342.28 352.20 SPEAKER_01 Раньше он это делал с временной табличкой, то есть он результат забирал во временную табличку, и потом оттуда понимал, какие ID-шники были сгенерены. -352.20 366.20 SPEAKER_01 Теперь он использует более простую версию, он просто использует output statement для этого, но, к сожалению, у этого есть и достоинства, и недостатки, точнее, к счастью, у этого есть достоинства, к сожалению, у этого есть недостатки. -366.20 367.84 SPEAKER_01 Достоинство в том, что это работает быстрее. -367.84 372.20 SPEAKER_01 Недостаток в том, что если на вашей табличке есть триггеры, то, например, SQL Server такой не поддерживает. -372.20 376.08 SPEAKER_01 Нельзя делать merge с output, если на табличке есть триггеры. -376.08 390.32 SPEAKER_01 Поэтому если это так, то вам нужно в db-контексте явно указать, что на этой таблице есть триггеры, и тогда EFCore будет работать по-старому, но вы не получите всех бенефитов от того, чтобы все стало быстрее. -390.32 404.04 SPEAKER_01 И в этом случае, если все нормально, если триггеров нет, и если у вас количество инсертов меньше, чем размер батча, либо равно, то, опять же, не будет никаких дополнительных begin-end на транзакции. -404.04 409.04 SPEAKER_01 Ну, если батчей больше одного, то там begin-end явный будет в любом случае явным round-trip, тут без этого никак. -409.04 414.36 SPEAKER_01 В плане чиселок получается примерно следующее. -414.36 431.52 SPEAKER_01 На тех же, назовем это условиях теста, то есть localhost, тот же регион и другой регион, относительно кода и базы разной регионы, получилось на вставке 10 рекордов улучшение соответственно на 23%, на 40% и опять на 65%. -431.52 436.76 SPEAKER_01 То есть, короче, здесь прям слеттанс стало лучше на десятки рекордов сразу. -436.76 443.24 SPEAKER_01 Хотя непонятно, почему на десятки рекордов, прямо на localhost такая, четверть сэкономили, но, видимо, еще какие-то рантаймовые штуты помогли. -443.24 460.56 SPEAKER_01 И последнее, что в этой статье интересно, и связано с ней, это то же, это фича, которую я на самом деле особо не знал, ну, точнее, я знал, как она работает для гуидов, но не знал, что есть другой способ. -460.56 470.48 SPEAKER_01 Смотрите, если мы вставляем, допустим, у нас есть пара объектов, точнее, пара классов связанных, это, допустим, традиционный пост и коммент к нему. -470.48 492.16 SPEAKER_01 Когда мы добавляем пост и, допустим, сразу, не знаю, к нему хотим сохранить какой-нибудь коммент, то для того, чтобы Entity Framework такое сохранить, ему нужно сначала сохранить объект родитель, получить его id-шник обратно и потом сохранить dto, чтобы указать, собственно, foreign ключом, кто был родителем. -492.16 508.16 SPEAKER_01 Если вы используете в качестве id ваших объектов родителя гуиды, то в этом случае такого делать не нужно или этого можно избежать, потому что гуиды можно сгенерить на клиенте и сразу одним инсертом запихнуть и родителя и dto в базу одним roundtrip. -508.16 512.44 SPEAKER_01 Инсертом, конечно, не получится, это будет два инсерта, но это можно сделать одним roundtrip. -512.44 524.60 SPEAKER_01 Но мы не все используем гуиды, не везде это нормально, не везде этим хочется заниматься, и поэтому в Entity Framework есть такая фича под названием high-low. -524.60 526.68 SPEAKER_01 Вот четыре буквы. -526.68 529.36 SPEAKER_01 Она работает следующим образом. -529.36 537.36 SPEAKER_01 Можно завести специальную sequence в базе данных и Entity Framework сказать, что для этой таблички, для его ключей использую этот sequence. -537.36 555.64 SPEAKER_01 И тогда Entity Framework, когда вы ему говорите save changes, он смотрит, сколько нужно будет заинсертить записей, ну например, если мы добавляем сразу 10 блок-постов, то он сходит в базу данных и скажет, отдай мне, дорогой дизайнер, пожалуйста, n ID-шников. -555.64 557.60 SPEAKER_01 Следующий, так сказать, range. -557.60 566.00 SPEAKER_01 По дефолту n = 10, но разработчики Entity Framework говорят, ну, короче, дефолт 10, но это не очень правильный дефолт, ставьте сразу больше, там, сотню, ставьте, будет норм. -566.00 578.76 SPEAKER_01 Вот, и по сути, получится, что Entity Framework сразу получает себе локально сотню ID-шников, в базе sequence двигается, и любой следующий клиент, который тоже захочет инсертию, он получит другую сотню. -579.76 587.40 SPEAKER_01 А ваша, так сказать, копия в памяти будет использовать эту сотню, пока она не закончится. -587.40 590.12 SPEAKER_01 Как только закончится, он получит следующую сотню. -590.12 619.84 SPEAKER_01 Таким образом, получается, что если вы делаете много инсертов, и вам не важен порядок, потому что, если у вас, допустим, несколько, не знаю, нод ходят в одну и ту же базу данных, да, и все они инсертят, то понятно, что каждый получит свой range, а использовать они будут их в каком-то случайном порядке, куда там будут запросы приходить, и поэтому записи, которые будут вставляться, казалось бы, по порядку, будут получать ID-шники, ну, на самом деле, довольно рандомно. -619.84 633.96 SPEAKER_01 Плюс, если вы, допустим, у вас есть какая-то там нода или под в кубернет, который взял, получил этот range 600 элементов, и тут же помер, ну, эти 100 элементов потерялись, то есть у вас еще и будут дырки в ваших ID-шниках. -633.96 651.88 SPEAKER_01 Если вас это все устраивает, а по мнению как бы разработчиков EF Core в большинстве приложений это норм, то, может быть, это вполне себе хороший вариант, как сделать так, чтобы у вас были ID-шники числовые, и при этом не было такой просадки по перформансу, если вы часто вставляете детей с родителями вместе. -651.88 663.16 SPEAKER_01 Поэтому, если это ваш кейс, по бенчмаркете такой способ, возможно, это действительно хороший способ сэкономить на вставке в современном Entity Framework 7. -663.16 674.72 SPEAKER_00 Тут хотелось бы еще добавить, что Hilo - это, в принципе, общеизвестный алгоритм, он применяется во многих базах данных и как раз таки служит для того, чтобы нивелировать все проблемы с распределенными идентификаторами. -674.72 686.76 SPEAKER_00 Например, вы можете с помощью этого прекрасного подхода добиться того, что у вас есть несколько распределенных нод, вам нужно вставлять какие-то записи, и вы при этом не хотите почему-то использовать гуиды. -686.76 689.92 SPEAKER_00 Ну, такая проблема всегда решается по дефолту с помощью гуидами. -689.92 696.08 SPEAKER_00 Если вам кто-то скажет, что это невозможно, это неправда, потому что очень распространен метод, вот такой подход как Hilo. -696.08 709.28 SPEAKER_00 Он вам позволяет оставаться в интах, то есть у вас по-прежнему будут красивые более-менее идентификаторы, они будут идти более-менее по порядку, но опять же без гарантированного какого-то отсутствия дырок или без гарантированного порядка, как сказал Игорь. -709.28 713.88 SPEAKER_00 В общем, но при этом это намного короче, намного приятнее будет смотреться, чем гуиды. -713.88 721.12 SPEAKER_00 И этот алгоритм часто применяется, часто используется, опять же, главное смотреть и понимать его минусы и его плюсы. -721.12 727.04 SPEAKER_00 И в большинстве ситуаций он вам вполне может заменить гуиды, если они вам почему-то не нравятся. -727.04 740.04 SPEAKER_01 Да, но нужно выбирать размер вот этого ренжа, который каждый из ваших копий приложения получает, ну и смотреть, насколько у вас получаются при этом большие дырки, насколько все это хорошо работает. -740.04 743.96 SPEAKER_01 Я просто на самом деле что-то не знал, что EF Core его нативно поддерживает. -743.96 745.68 SPEAKER_01 Но, как выясняется, совпадное поддерживает. -745.68 756.56 SPEAKER_01 Причем, если вы используете Code First, то вам даже не нужно генерить ручную секвенцию, он по-моему сам генерирует его в нужном варианте. -756.56 766.84 SPEAKER_01 А вот если у вас Database First, то секвенцию вам нужно объявить в базе самому, а Entity Framework просто сказать вот для Hilo вот этой таблички используй вот тот секвенс под таким названием. -766.84 767.84 SPEAKER_01 И все будет работать. -767.84 775.76 SPEAKER_01 Давай пойдем дальше, кроме Entity Framework у нас сегодня день Performance Improvement. -775.76 782.80 SPEAKER_00 Ну, конечно, перед релизом всегда так, сначала там накидают, что только задали высший сахар, а потом начинают оптимизировать и перформанс улучшать. -782.80 791.36 SPEAKER_00 Ну, да, у нас еще есть на подходе статейка про ASP.NET Core, что же там случилось с перформансом, давайте посмотрим. -791.36 802.60 SPEAKER_00 Здесь, наверное, в этой статье очень прикольно на нее взглянуть с точки зрения вообще подхода, каким образом можно чинить самые распространенные проблемы с перформансом. -802.60 808.12 SPEAKER_00 Потому что я надеюсь, что вы знаете, что прежде чем чинить перформанс, вам нужно попрофайлить и найти точки, которые вас именно тормозят. -808.12 812.56 SPEAKER_00 Не так, как вам хочется и кажется, а реально, чтобы инструменты это вам подтвердили. -812.56 816.88 SPEAKER_00 И после того, как вы их нашли, у вас, соответственно, встает вопрос, а что же дальше с ним делать? -816.88 822.68 SPEAKER_00 В принципе, таких подходов, которые позволяют вам более-менее стандартные участки улучшать, их не так уж много. -822.68 828.92 SPEAKER_00 Я думаю, что если была бы какая-нибудь хорошенькая статейка или книжечка, то набралось бы несколько десятков и все. -828.92 833.68 SPEAKER_00 Если вы их выучите, вам их обычно хватит на всю жизнь, чтобы улучшать ваш перформанс. -833.68 834.68 SPEAKER_00 Да, ой-ой-ой. -834.68 838.92 SPEAKER_00 И здесь как раз-таки ярко выражены несколько таких подходов. -838.92 839.92 SPEAKER_00 Давайте посмотрим. -839.92 856.80 SPEAKER_00 Прежде всего, авторы нам хвалятся, что они смогли улучшить показатели на их специальной 80-ядерной машине на 514% для обычной дистиллизации текста и для 311% для JSON обработки запросов. -856.80 859.20 SPEAKER_00 В общем, как это они сделали? -859.20 863.72 SPEAKER_00 У них был очередь на входящие запросы для кестрила. -863.72 868.88 SPEAKER_00 Эта очередь была одна и, соответственно, она очень сильно локалась на контеншоне. -868.88 880.60 SPEAKER_00 Как только мы пытались распараллелить все запросы, только обработать их параллельно, все эти запросы лезли в одну очередь и оттуда доставали работу. -880.60 887.28 SPEAKER_00 Чтобы работа досталась только одному какому-то персонажу, только одному воркеру, там, естественно, был какой-то лок. -887.28 890.48 SPEAKER_00 В общем, это все было совсем нехорошо. -890.48 898.28 SPEAKER_00 Поэтому прежде всего эту очередь разбили на несколько очередей и теперь каждый воркер ходит к своей очереди. -898.28 903.72 SPEAKER_00 Это позволило избежать контеншона, то есть мы избавились от локов. -903.72 922.92 SPEAKER_00 И теперь у нас каждый воркер может забирать свою работу, но при этом немножко увеличилось время CPU, потому что бывают ситуации, когда воркер всю свою работу сделал и сидит без работы, а в это время другой воркер захлебывается от работы, не успевает разгрести свою очередь и в это время происходит так называемое воровство. -922.92 932.88 SPEAKER_00 То есть тот воркер, который халтурничает, он ворует работу у занятого воркера и вот здесь уже немножко нужно будет потратить CPU для того, чтобы это сделать. -932.88 940.92 SPEAKER_00 Но в принципе такой подход, он обычно дает больше плюсов, чем минусов, поэтому команда остановилась именно на нем. -940.92 948.64 SPEAKER_00 Также добавилась на Windows поддержка Windows I/O Completions в портабл ThreadPool. -948.64 954.52 SPEAKER_00 Давно уже переписали ThreadPool на портабл, но почему-то там Windows I/O Completions до сих пор не подтянули. -954.52 958.52 SPEAKER_00 Теперь это исправлено и это дало прирост на 11%. -958.52 970.56 SPEAKER_00 И также позволило убрать другую техдолг, который делал DoubleDispatch в Windows I/O, что увеличило еще на 18% производительность данных тестов. -970.56 975.32 SPEAKER_00 Еще одна интересная оптимизация - это исключения. -975.32 978.76 SPEAKER_00 Как вы наверное слышали, бросать исключения - это очень дорого. -978.76 993.80 SPEAKER_00 Конечно, если вы бросаете одно или два бизнес-исключения, может быть это не так страшно, но если мы говорим про уровень сокета и когда у нас там тысячи коннекций и там сокеты открываются-закрываются, то там исключения вполне могут дать какую-то просадку по производительности. -993.80 1011.20 SPEAKER_00 И вот авторы нашли одно место, которое бросало исключение на коннекшенах и это исключение в принципе было не обязательно, то есть вполне можно было бы обработать эту ситуацию без исключения, пробросать ее в более верхний слой обработки всех этих ошибок. -1011.20 1016.56 SPEAKER_00 В общем, просто-напросто убрали throw одного исключения. -1016.56 1029.68 SPEAKER_00 И это позволило уменьшить потребление CPU, только задумайтесь там с 50% до 40% на рынок-системах и всего лишь навсего выбрасывание одного исключения тогда, когда можно было бы этого не делать. -1029.68 1033.32 SPEAKER_00 В общем, бросать исключение это тоже зло, поэтому задумывайтесь прежде чем это делаете. -1033.32 1050.12 SPEAKER_00 И еще одна оптимизация, это новый классик, ну относительно новый, называется он PoolingAsyncValueTaskMethodBuilder, то есть это специальный класс, который применяется в довольно узких кейсах, когда вам нужно запулить value-таски. -1050.12 1056.96 SPEAKER_00 Если вы помните, что value-таски они сами были изобретены для того, чтобы в некоторых ситуациях можно было заменить таски. -1056.96 1062.48 SPEAKER_00 В общем, а теперь даже сами value-таски, сами структуры оказались слишком дорогими и их теперь можно пулить. -1062.48 1076.56 SPEAKER_00 Скорее всего вы никогда не встретите в своем коде надобности пулить value-таски, но если вы автор кестрила или там какого-нибудь сверхнагруженного протокола типа gRPC, вот там это вам может понадобиться. -1076.56 1091.08 SPEAKER_00 Если по цифрам, то запуская 1000 рядов swap-сокетов, раньше аллокейтилось 3000 стейт-машин, то есть стейт-машина, которая получается в результате вот этих await-тасков, то есть await-стейт-машина. -1091.08 1095.60 SPEAKER_00 Их было 3000 и они аллокейтились. -1095.60 1097.32 SPEAKER_00 Это было страшно. -1097.32 1104.20 SPEAKER_00 То есть ВЦ там тоже старался и это давало какие-то проблемы с перформансом. -1104.20 1111.84 SPEAKER_00 После того, как поставили пул в нужное место, а именно в дотнет-седьмом, таких аллокаций вместо 3000 стало 11. -1111.84 1115.00 SPEAKER_00 То есть это практически уже незаметно. -1115.00 1121.72 SPEAKER_00 Вот так пулинг нам помогает в каких-то местах, которым обращаются очень много раз. -1121.72 1126.16 SPEAKER_00 Каждое обращение, каждый аллокейт стейт-машины, он мизерный, он элементарный. -1126.16 1136.52 SPEAKER_00 Но если их набирается много-много, на 1000 клиентов, на 1000 коннекций, это уже становится существенно, это уже видно на профайлерах и это значит можно чинить. -1136.52 1138.92 SPEAKER_00 Следующие новинки по HTTP/2. -1138.92 1148.08 SPEAKER_00 В HTTP/2 у нас тоже была проблема с тем, что есть лог контеншен, то есть был лог контеншен. -1148.08 1153.76 SPEAKER_00 Там некоторые клиенты дрались за определенную очередь для того, чтобы разбирать себе задачи. -1153.76 1156.48 SPEAKER_00 И по-моему даже писать. -1156.48 1160.56 SPEAKER_00 Да, некоторые клиенты дрались для того, чтобы писать ответы уже после того, как все обработали. -1160.56 1162.80 SPEAKER_00 И здесь авторы пошли следующим путем. -1162.80 1165.00 SPEAKER_00 Они все переделали на ченнел. -1165.00 1177.16 SPEAKER_00 То есть в ченнел пишется определенные задачи, которые нужно сделать, а один-единственный консюмер обрабатывает эту очередь задач из ченнелов и делает всю основную работу для записи. -1177.16 1187.84 SPEAKER_00 То есть реально пишет один консюмер, то есть это значит, что мы в одном потоке загружаем весь сокет и никакой драки, никакого контеншена, ничего плохого не происходит. -1187.84 1199.64 SPEAKER_00 И соответственно это очень сильно убрало лог контеншен, подняло рпс с 1.2 млн до 6.8 млн рпс в данном конкретном бичмарке. -1199.64 1205.88 SPEAKER_00 Но самое интересное, что данная оптимизация подняла расход CPU на 100%. -1205.88 1212.08 SPEAKER_00 Раньше там были какие-то жалкие проценты, а сейчас CPU вырабатывал весь на 100% и это хорошо. -1212.08 1220.44 SPEAKER_00 Потому что теперь мы видим, что мы не упираемся в контеншен, то есть у нас работает железо на полную мощь, значит выдает максимум, что оно только может. -1220.44 1230.36 SPEAKER_00 Когда у нас был контеншен, у нас в профайле была ситуация, когда CPU еле нагружен, сеть еле нагружена, вроде как бы ресурсов полно, но ничего не происходит. -1230.36 1234.96 SPEAKER_00 Как раз таки все потому, что большинство воркеров ждали своей очереди на логах. -1234.96 1256.56 SPEAKER_00 В общем логи это страшная сила, поэтому если вы можете избежать их, обязательно избегайте, а если не можете избежать, то задумайтесь об одном из методов устранения логов, это вот в частности оставление одного консюмера, если это возможно, а все остальное загонять в очередь, или вот как мы обсуждали чуть выше, несколько воркеров, которые таскают задачи каждой своей очереди. -1256.56 1291.56 SPEAKER_00 Далее еще увеличили окно, так называемый upload window у кистерла в HTTP/2, что позволило загружать хорошо и быстренько большие файлы, например 100 мегабайтный файл, раньше грузился за 27 секунд, а сейчас он начал грузиться за 4 секунды, то есть вот такие большие огромные изменения, но опять же все нужно понимать, что игры с окном это тоже какой-то компромисс, в некоторых ситуациях он может дать какой-то плохой результат, в некоторых хороший, в общем здесь все на совести команды разработчиков, мы им поверим. -1291.56 1306.92 SPEAKER_00 В HTTP/3, HTTP/3 наконец-то вышел из экспериментальной стадии, теперь это вроде считается больше не эксперимент, но его по-прежнему не включили в .NET 7 по умолчанию, поэтому если вы захотите его юзать, вам придется его явно включить. -1306.92 1424.56 SPEAKER_00 Еще улучшили декодер и улучшили его в 900 раз, вот такие страшные цифры, вообще не понимаешь как оно раньше работало, ну не зря наверное это все в экспериментальном было, потому что там ничего не улучшали, 900 раз, тоже интересная техника, как добились 900 раз перформанса, все очень просто, заставили сжимать компрессор, заставили сжимать намного-намного эффективнее, чтобы вы понимали эффективность, раньше хидра сжимались до 109 байт, а теперь они сжимаются до 7 байт, это вообще все похоже на какой-то анекдот про архиватор, для которого осталось придумать только разархиватор, но на самом деле существует тоже такой интересный хак, когда у вас есть какой-то понятный предсказуемый набор список значений, как в нашем случае HTTP хедеры, ну наверное каждый из вас сталкивался, это какой-нибудь content type, content size, что там у нас еще есть, какой-нибудь агент, все сервер в его столице, какой-нибудь агент, еще что-то, ну вот стандартные HTTP хедера, они все объявлены спецификацией и каждый раз гонять полные их текстовые названия в ASCII строках, это довольно бессмысленно, даже если мы их сожмем, поэтому команда Durnet, команда ASP приняла следующее интересное решение, она просто-напросто присвоила каждому хедеру уникальный индекс и далее теперь пересылает не строчки с названиями хедеров, а индекс, вот там допустим индексу 42 соответствует хедер content type, сервер об этом знает, клиент об этом знает и соответственно если они оба договорились о правильных индексах, им не обязательно подправлять строки, они отправили там один байтик и уже всем все понятно какой хедер имеется в виду, вот такая немудреная оптимизация и сократила размер и увеличила перформанс и вообще позволила показать красивые графики нашим читателям. -1424.56 1434.24 SPEAKER_00 В Signal Area уменьшили аллокацию с помощью кэширования, аллокацию строк тоже популярная способ оптимизации, это кэширование, главное не забывайте когда его чистить. -1434.24 1466.52 SPEAKER_00 И в аутентификации также закэшировали policy_authorize_result, интересная оптимизация была сделана в http_results, http_results это такие специальные классики, которые возвращаются серверам в зависимости от того, что там произошло, самый частый случай это 200 окей, наверное все вам известны, когда возвращаете какой-то результат серверу, сообщаете ему, что все хорошо, в этот момент создается http_result, который умеет рендерить 200-ый респонс и он возвращается клиенту. -1466.52 1485.36 SPEAKER_00 Зоркий глаз заметил, что очень часто, особенно для каких-то общеизвестных статус кодов, вот эти http_results они по сути иммьютабельные, то есть в них практически никогда нет какого-нибудь стейта, и поэтому решили http_results просто закэшировать и переиспользовать. -1485.36 1503.72 SPEAKER_00 Но не просто закэшировали, а взяли и сгенерировали уже http_results по всем известным http кодам, потому что это очень частая ситуация, обычно наши клиенты не выдумывают каких-то хитроумных, наши серверы обычно не выдумывают каких-то хитроумных кодов, а возвращают то, что уже все знают и все давно есть. -1503.72 1511.36 SPEAKER_00 В общем вот эти всем известные коды взяли и закэшировали, то есть закэшировали, да, а для того, чтобы закэшировать их для начала сгенерили. -1511.36 1515.04 SPEAKER_00 И интересное в этой схеме в том, что сгенерили их с помощью t4-темплейтов. -1515.04 1533.68 SPEAKER_00 Вот мы как раз недавно обсуждали жив t4-темплейт или мертв, или его заменил рослин генераторой или что-то в этом духе, оказывается нет, жив, живее всех живых, и вот в последних релизах Dota 7 команда ISP активно использует t4-темплейты, отличная технология, хорошо, что живет. -1533.68 1551.72 SPEAKER_00 Еще один интересный момент в том, что для t4-темплейтинга они использовали не микрософтовскую реализацию, которая имеет свои минусы, а взяли монотекст-темплейтинг, то есть реализацию t4, ту, которая была сделана под моно, и вот ISP теперь юзает ее. -1551.72 1559.24 SPEAKER_00 Это кроссплатформенная реализация, соответственно, и дает все те плюсы t4, которые вы, скорее всего, сталкивались когда-нибудь под виндой. -1559.24 1578.72 SPEAKER_00 В общем, тоже прекрасная оптимизация, если вы можете что-нибудь сгенерить в дизайн тайме, то есть еще до того времени, когда вы начали компилировать, это всегда прекрасная идея, и самый лучший инструмент, который вам помогает это сделать, это t4, без него вообще никуда. -1578.72 1594.92 SPEAKER_00 У нас, кстати, недавно в сообществе SPB.net был докладик по t4, если кто-то вдруг не сталкивался, обязательно на доклад посмотрите, я думаю, многим может помочь, там как раз доклад очень практичный, упоминается очень много кейсов, в которых в том числе есть performance оптимизации. -1594.92 1596.60 SPEAKER_00 Так, погнали дальше. -1596.60 1610.24 SPEAKER_00 В фильтрах наконец-то додумались светлой умой заменить new object, то есть создание нового пустого массива на специальное редональное свойство, которое называется array.empty от object. -1610.24 1616.96 SPEAKER_00 Если вдруг в ваших проектах еще осталась аллокация нового пустого массива, то обязательно меняйте на array.empty. -1616.96 1620.32 SPEAKER_00 По-моему, сейчас уже все анализаторы это советуют, но вдруг вы почему-то упустили. -1620.32 1629.32 SPEAKER_00 И последняя оптимизация, о которой хотелось бы рассказать, это когда делают нескончаемый набор аргументов. -1629.32 1635.80 SPEAKER_00 Редко такая штука встречается, но иногда бывает, когда вам нужно передать количество аргументов, которые вы заранее не знаете. -1635.80 1638.44 SPEAKER_00 Вы обычно пишите по RAM и задаете это на массив объектов. -1638.44 1643.84 SPEAKER_00 Это стандартный подход, например, в логгерах он используется практически всегда. -1643.84 1647.40 SPEAKER_00 То есть, когда вы пишете log, вы не знаете, сколько параметров передастся. -1647.40 1650.84 SPEAKER_00 Там будет message template и плюс еще куча всяких параметров. -1650.84 1654.64 SPEAKER_00 В этом случае пишут обычно по RAM и массиву объектов. -1654.64 1656.52 SPEAKER_00 И все, и корренно все в огнем. -1656.52 1658.64 SPEAKER_00 Но хороший логгер, естественно, так не делает. -1658.64 1662.36 SPEAKER_00 И хорошие микрософтовские пайплайны в ASP тоже так не делают. -1662.36 1663.36 SPEAKER_00 Как делать правильно? -1663.36 1669.80 SPEAKER_00 Правильно все-таки взять, напрячься и скопипастить, сгенерить, добавить 10 отдельных методов. -1669.80 1675.52 SPEAKER_00 У первого метода будет один аргумент, у второго метода второй аргумент, у третьего три аргумента и так далее. -1675.52 1680.08 SPEAKER_00 То есть, поддержать самое адекватное, то есть, самое часто распространенное количество аргументов. -1680.08 1683.56 SPEAKER_00 И последнее можно сделать там уже с массивом объектов. -1683.56 1685.08 SPEAKER_00 Что это вам даст? -1685.08 1688.92 SPEAKER_00 Прежде всего, это позволит вам не аллокировать массив объектов. -1688.92 1695.72 SPEAKER_00 Потому что аллокация в частых случаях, ну, например, если мы возьмем логгер, логгер на самом деле пользуется очень часто. -1695.72 1702.08 SPEAKER_00 И там аллокация массива объектов – это уже какой-то performance penalty. -1702.08 1707.56 SPEAKER_00 То есть, уже могут с этим вылезти проблемы, и вы их на профилере точно увидите при интенсивном использовании. -1707.56 1708.56 SPEAKER_00 Вот. -1708.56 1714.08 SPEAKER_00 И вторая проблема – это в том, что обычно такой массив параметров, он задается как массив объектов. -1714.08 1716.48 SPEAKER_00 Потому что, по сути, вы не знаете, что туда положить. -1716.48 1718.24 SPEAKER_00 И это провоцирует боксинг. -1718.24 1723.44 SPEAKER_00 Боксинг – это еще одна такая невидимая штука, которая хорошо сажает performance. -1723.44 1730.68 SPEAKER_00 Если же вы делаете отдельные параметры, то вы можете использовать в этот момент дженерики. -1730.68 1739.72 SPEAKER_00 Никакого боксинга не будет, вы просто пишете t1, t2, t3, t4, и компилятор сам их раскладывает в правильные нужные вам типы, и эти типы подставляет во время компиляции. -1739.72 1743.00 SPEAKER_00 То есть, никакого боксинга не будет, никакого создания массива не будет. -1743.00 1751.56 SPEAKER_00 И в тех моментах, когда данные методы используются очень часто интенсивно, это очень сильно помогает вам улучшить performance. -1751.56 1756.24 SPEAKER_00 Вот такие основные новинки по performance в WSP.net Core. -1756.24 1760.96 SPEAKER_00 Думаю, что мы получим еще одни интересные тесты сразу после релиза. -1760.96 1769.96 SPEAKER_00 Пока ребята обновят какие-нибудь общие употребимые теком power, и посмотрим, что там у нас изменится с местами. -1769.96 1775.24 SPEAKER_00 Ну что ж, у нас осталась последняя статья по перформансу, давай перейдем уже к ней. -1775.24 1783.12 SPEAKER_01 Да, с перформансом у нас в этот раз все хорошо, и в этот раз мы посмотрим на перформанс MAUI, новую UI. -1783.12 1795.40 SPEAKER_01 Ну, не сказать, чтоб фреймворка, но по крайней мере, не сказать, чтоб нового, как наследника Xamarin.Forms, но тем не менее в нем тоже есть некоторые performance improvement по сравнению с .NET 6. -1795.40 1813.20 SPEAKER_01 MAUI в основном, ну он вообще предполагается то, что он должен быть полностью кроссплатформенным, но основной фокус сейчас, конечно же, на Android и на iOS, потому что там особые требования и к времени старта, и к размеру приложения, и там нужно более тщательно к этому всему подходить. -1813.20 1822.40 SPEAKER_01 Поэтому в этом релизе, в 7.NET, был фокус на Android и на iOS, и он был немножко разный. -1822.40 1834.88 SPEAKER_01 Согласно статье, для Android фокус был на производительности стартапа, то есть насколько быстро приложение запускается, потому что размер приложения был уже неплох, как у них написано. -1834.88 1835.88 SPEAKER_01 Was in good place. -1835.88 1845.60 SPEAKER_01 А для iOS наоборот, они фокусировались на размере приложения, потому что стартап тайм был in good shape, как опять же у них сказано. -1845.60 1851.36 SPEAKER_01 На одной платформе хорошо с размером, на другой платформе хорошо с временем старта. -1851.36 1858.64 SPEAKER_01 Но при этом у них был еще и кастомер фидбэк после шестерки, что в целом UI performance, то есть layout, scrolling и прочее надо улучшать. -1858.64 1861.60 SPEAKER_01 Ну в общем, примерно над этим и работали. -1861.60 1863.76 SPEAKER_01 И надо сказать улучшили. -1863.76 1877.96 SPEAKER_01 С одной стороны улучшили хорошо, с другой стороны чиселки ну прям такие как бы… когда я начал читать статью, они какие-то такие, ну не сказать смешные, но не очень убедительные что ли. -1877.96 1897.96 SPEAKER_01 То есть у них для примера, и мы может быть помните, обсуждали давным-давно, что у них появилось новое приложение, когда они начали разрабатывать Мауи, появилось новое, так скажем, модельное приложение, называется dotnet podcast app, то есть это некоторый каталог подкастов, который компилируется как Мауи приложение, и он кроссплатформенный. -1897.96 1914.24 SPEAKER_01 Соответственно для стартап тайма на андроиде это тестировалось на пятом пикселе, они улучшили по сравнению с шестеркой, было 814 мс, стало 759 мс, то есть улучшение где-то на 54 мс из 800. -1914.24 1922.60 SPEAKER_01 Ну как бы не знаю, лучше, но не сильно впечатляюще, было бы там 800-400, вот было бы да. -1922.60 1929.00 SPEAKER_01 А тут как-то улучшили, ну процентов на 7 получается, если так оценить. -1929.00 1940.12 SPEAKER_01 Немного, с размером на iOS примерно та же история, этот самый подкаст приложения занимал 25 мегабайт в варианте dotnet 6 и стал занимать 23.9 в варианте dotnet 7. -1940.12 1942.96 SPEAKER_01 Ну сэкономили 4% примерно. -1942.96 1948.64 SPEAKER_01 Не знаю, насколько это круто и хорошо, но наработали над этим много. -1948.64 1957.36 SPEAKER_01 И на самом деле вся статья это про то как раз-таки чем, какие подходы они использовали для того, чтобы этого всего добиться. -1957.36 1976.80 SPEAKER_01 И действительно можно посмотреть, что в некоторых местах startup time или с размером они прям выигрывали какие-то сотые доли секунды, не знаю там 16 мс сократили до 2 мс кусочки, то есть там они буквально профайлили вот такие вот места, то есть типа ооо вот здесь код занимает 16 мс, давайте его улучшим. -1976.80 1982.84 SPEAKER_01 Чего в обычной жизни конечно, ну вряд ли вы будете обращать свое внимание на код, который работает 16 мс. -1982.84 1987.64 SPEAKER_01 Здесь важна каждая мелочь, потому что даже она позволяет хоть что-то выиграть. -1987.64 1993.00 SPEAKER_01 И произвести свой вклад в общее дело. -1993.00 1999.24 SPEAKER_00 Ну знаешь, там 16 мс, здесь 16 мс, там уже 100 бабок это руб. -1999.24 2017.64 SPEAKER_01 Ну видимо на этом они и основывались, то есть понятно, что есть какие-то очень большие куски, которые возможно сейчас сделать сложно, ну просто потому что дотлен сам по себе, там требует поднять довольно много вещей, там и DC, и JIT, там где он доступен на андроиде, но все остальное они пытаются оптимизировать. -2017.64 2020.36 SPEAKER_01 И с деталями там примерно следующее. -2020.36 2029.36 SPEAKER_01 Во-первых, они сначала сделали приложеньку, на которой они пытались это все моделировать и измерять, насколько вообще хорошо-плохо. -2029.36 2035.48 SPEAKER_01 Приложенька есть вообще на самом деле стандартная, как они говорят, некоторые тесты такой модель на приложение, но они написали свое. -2035.48 2038.20 SPEAKER_01 Они написали свое в 5 вариантах. -2038.20 2051.04 SPEAKER_01 Приложенька, смысл этой приложеньки, он простой, он берет рандомный текст, ну на самом деле берет фиксированную строчку текста, и выводит его с рандомным поворотом и рандомным цветом на экран просто, в разных местах, опять же рандомно. -2051.04 2054.44 SPEAKER_01 И по сути просто мерить, сколько раз вы смогли это сделать за секунду. -2054.44 2076.96 SPEAKER_01 Текст они выбрали очень прикольный, текст они выводят лолы, поэтому у них метрика называется lols_per_seconds, и на Xamarin.Forms, если это написать прям стареньком, то это будет 179 штук в секунду, на .NET 6 Maui 327 штук в секунду, на .NET 7 493, то есть это в полтора раза больше. -2076.96 2098.08 SPEAKER_01 На .NET Android, то есть это .NET приложение, использующее нативные байнинги к Android, всяким контроллам и всему остальному, 594, то есть .NET Maui где-то на 20% отстает от полноценного .NET Android, и на Java он еще процентов на 20% отстает, на Java 682. -2098.08 2103.60 SPEAKER_01 Короче нужно .NET 7 Maui ускорить где-то раза в полтора, чтобы добраться до скорости Java. -2103.60 2108.60 SPEAKER_01 Ну Java, понятно, нативный язык для Android, поэтому там все быстрее максимально. -2108.60 2119.12 SPEAKER_01 И это на самом деле, вот это вот Interop с Java, это практически основной источник улучшения стартап тайма и вообще работы для .NET приложения. -2119.12 2124.68 SPEAKER_01 То есть и в стартапе требуется много Interop, и дальше при дальнейшей работе много Interop. -2124.68 2140.04 SPEAKER_01 И там написано в статье довольно много интересных и на самом деле довольно очевидных техник, ну типа если у вас есть пропертия, которые под капотом ходят в javaski Interop, ну наверное можно внутри одной функции эту пропертию запихнуть в локальную переменную и дальше пользоваться локальной переменной. -2140.04 2145.80 SPEAKER_01 Ну в C# мы привыкли, что пропертия обычно это дешевая штука, ну если правильно написано. -2145.80 2149.56 SPEAKER_01 То естественно код написан был исходя из того, что пропертия это дешевая штука. -2149.56 2160.28 SPEAKER_01 Но оказалось она в мире такого Interop и Maui не очень дешевая местами, и потому что идет в Java на каждую чтение пропертии, это не здорово. -2160.28 2169.24 SPEAKER_01 Во-вторых, есть например методы, которые вам нужно получить, например, дефолтную ширину-высоту экрана, для этого нужно дернуть javaski метод. -2169.24 2172.56 SPEAKER_01 Точнее вы дергаете два метода, получить ширину, получить высоту. -2172.56 2178.36 SPEAKER_01 Можно дернуть метод, который вернет структурку, но там накладные расходы на передачку этой структуры. -2178.36 2189.32 SPEAKER_01 Инфективнее всего передавать интеджеры или лонги, и поэтому они написали хелперный Java метод, который пакует ширину и длину в общий лонг, ну битовой магии, да, и потом это все возвращает в C#. -2189.32 2194.88 SPEAKER_01 В общем, такими методами 100 миллисекунд, 10 миллисекунд, вот таким образом это все и экономится. -2194.88 2198.24 SPEAKER_01 Дальше там пошли уже совсем какие-то извращенные техники с моей точки зрения. -2198.24 2206.40 SPEAKER_01 Например, они выяснили, что очень много времени уходит на вызов метода datetime_offset.now, но не метод на пропертии. -2206.40 2208.00 SPEAKER_01 Ну, по понятным причинам. -2208.00 2217.28 SPEAKER_01 UTC_NOW добыть легко, а NOW требует сходить в информацию о таймзоне, узнать, собственно, что за таймзона, зааджастить текущее время к текущей таймзоне. -2217.28 2221.48 SPEAKER_01 И вот эта вот загружка информации про таймзоны, она занимает время. -2221.48 2224.32 SPEAKER_01 Поэтому они сделали хитрый ход, я так и не понял, зачем. -2224.32 2235.12 SPEAKER_01 На старте они сначала читают информацию о таймзоне в джава-коде, передают ее из джава-кода в C# и используют эту информацию об оффсете во время стартапа. -2235.12 2246.88 SPEAKER_01 Одновременно они стартуют бэкграундный трет для загрузки этой же информации в C#-овый код, и как только эта информация загрузится, то все вычисления оффсетов переходят на C#-овые данные. -2246.88 2247.88 SPEAKER_01 Сложно. -2247.88 2248.88 SPEAKER_01 Сложно. -2248.88 2249.88 SPEAKER_01 Я не понял, в чем смысл. -2249.88 2256.84 SPEAKER_01 Возможно, потому что там что-то может поменяться, ну, по пути или еще как-то, или чтобы поведение точно соответствовало поведению C# везде и было одинаковым. -2256.84 2258.76 SPEAKER_01 Ну, а на стартапе будет немножко отличаться. -2258.76 2262.16 SPEAKER_01 Выглядит забавно, я не очень понимаю эту технику, но вот так сделано. -2262.16 2275.36 SPEAKER_01 Вот, в куче мест они постарались убрать передачу массивов, то есть часть AP-шек была сделана так, что она возвращает, например, не знаю, массив из трех элементов, ну, там RGB-компонент, например, или еще что-нибудь в таком духе. -2275.36 2276.36 SPEAKER_01 Вот. -2276.36 2284.12 SPEAKER_01 Интерроб массивов он сложный и медленный, как выяснилось, потому что для того, чтобы интерробить массивы между Java и C#, они их копируют всегда. -2284.12 2287.68 SPEAKER_01 То есть передача массива и туда и обратно - это обязательная копия. -2287.68 2295.84 SPEAKER_01 А поэтому, опять же, пришлось битовой магией схлопывать это все по возможности в одно число и передавать. -2295.84 2299.36 SPEAKER_01 Дальше к SAML они компилируют в IL-код сразу. -2299.36 2304.84 SPEAKER_01 То есть не хранят там в виде ресурсов, в виде еще чего-то, а стараются сразу компилировать в IL-код. -2304.84 2319.12 SPEAKER_01 Ну и для винды используют RadioTuran во все, значит, это самое, потому что RadioTuran - это хорошо, он там прикомпилирует все как надо, и тем самым улучшает стартап-тайм на десктопе на винде. -2319.12 2335.40 SPEAKER_01 Помимо этого пришлось делать кучу изменений в Mono, ну потому что под компотом там Mono крутится, интерпретатор, потому что, например, на iOS у вас нету JIT, а хочется поддерживать System Reflection Emit. -2335.40 2343.72 SPEAKER_01 Чтобы это сделать, на самом деле на iOS, как выяснилось, для меня это было новостью, вполне поддерживается System Reflection Emit. -2343.72 2347.84 SPEAKER_01 Но мы же не можем на iOS исполнять код, который мы только что сгенерили, там JIT нет. -2347.84 2353.20 SPEAKER_01 Поэтому для исполнения такого кода используется Mono Interpreter внутри, под компотом семерки. -2353.20 2372.04 SPEAKER_01 И туда завезли некоторый аналог Tyrate компиляции, то есть это, конечно, не компиляция, это интерпретация, но если Mono Interpreter понимает, что какой-то кусочек кода, который вы сгенерили, используется очень часто, он его как-то оптимизирует пооптимальнее и начинает выполнять быстрее. -2372.04 2385.36 SPEAKER_01 Ну и куча всяких разных, повыкидывали лишних вещей из джавовского кода, плюс вот это может быть практически интересная штука, написали тул, который позволяет мерить стартап тайм. -2385.36 2400.44 SPEAKER_01 Все измерения стартап тайма, которые я выше приводил, они сделаны не просто так секундомером, для этого написан специальный тул, который, если вам интересно, если вы вдруг зачем-то мерите стартап тайм вашего продукта, можете у Microsoft позаимствовать и использовать тот же самый тул. -2400.44 2406.08 SPEAKER_01 Может быть, они его даже оформят в виде полноценного dotnet тула, рассматривать такую возможность пока еще не сделали. -2406.08 2407.08 SPEAKER_01 Примерно так. -2407.08 2429.68 SPEAKER_01 Короче, MAUI — это такая забавная конструкция, то есть с одной стороны там довольно противоречивые требования, потому что и Android, и iOS, и десктопы, они все очень разные, везде свои особенности, везде свои проблемы, везде свои оптимизации, которые нужно делать, и они как-то пытаются это все балансировать так, чтобы в результате получилось удовлетворительный перформанс везде. -2429.68 2431.92 SPEAKER_01 Ну вот, как-то получается. -2431.92 2434.96 SPEAKER_01 Не знаю, я пока не видел, не знаю, слышал ты каких-нибудь, -2434.96 2443.44 SPEAKER_00 ну хоть каких-то приложений к этому MAUI? Наверное, еще нет, скорее всего все боятся, все ждут какую-то стабильную версию, и вот это, наверное, она и есть. -2443.44 2458.56 SPEAKER_01 Но с другой стороны, dotnet 7 — это не LTS, поэтому возможно сейчас на семерке начнут появляться какие-то экспериментальные приложения, и только к восьмерке, которая будет LTS, там вот уже, может быть, кто-то начнет что-то менять, переписывать или писать что-то новое. -2458.56 2480.92 SPEAKER_00 Так как UI-компоненты, то есть UI-продукты, вот эти, в общем, UI-ки — это довольно-таки сложные обычно вещи, и там очень много, очень плотная интеграция с самим фреймворком, то мне кажется, что те люди, которые, например, уже давно сидят на старых UI-ках и хотят куда-то переехать, то для них сейчас самое время уже начинать переписывать, чтобы к моменту стабильного выхода нового релиза через год у них уже было все готово. -2480.92 2486.24 SPEAKER_02 Да, согласен, но с другой стороны, как человек, который -2486.24 2501.68 SPEAKER_01 когда-то переписывал, ну не переписывал, а начинался писать на нестабильной версии WPF, ну как бы количество workaround-ов и bug-ов, которые были, не то чтобы это плохо, но эти workaround-ы жили потом долго даже после выхода стабильной версии. -2501.68 2504.96 SPEAKER_01 Поэтому… Да, такое тоже бывает, к сожалению. -2504.96 2507.36 SPEAKER_01 Тут надо будет тщательно балансировать. -2507.36 2518.44 SPEAKER_01 Ну ладно, в общем с performance у нас вроде как все, вернее как, ну у нас на этот выпуск все, мы скорее всего затронем, конечно, какой-то performance в следующем выпуске, когда будем говорить в целом про тот всем релиз. -2518.44 2522.72 SPEAKER_01 Еще раз напомню, что все стало лучше, выше, сильнее и быстрее. -2522.72 2525.44 SPEAKER_01 Ну а пока давай перейдем к другим вещам. -2525.44 2539.04 SPEAKER_00 Давай, я тут как раз наткнулся на одну такую фановую статьечку, которая нам расскажет и про новые методы, и про интеграцию с .NET, и вообще должна нас развлечь от всех вот этих performance низковыровневых вещей. -2539.04 2546.08 SPEAKER_00 А нашел я статью, которая рассказывает нам о том, а как добавить в WPF .NET экспериментальный новый метод. -2546.08 2560.76 SPEAKER_00 И я напомню, а для тех, кто не знал, расскажу, что сейчас в HTTP стандарте рассматривается новое ключевое слово, новый verb, новый глагол, который называется query. -2560.76 2564.76 SPEAKER_00 И вот его, в принципе, вы уже можете добавить в свои приложения. -2564.76 2568.40 SPEAKER_00 Давайте обсудим и посмотрим, как это можно сделать. -2568.40 2571.44 SPEAKER_00 Во-первых, что такое query и зачем он был нужен? -2571.44 2574.40 SPEAKER_00 Тут лучше всего начать с истории. -2574.40 2588.04 SPEAKER_00 Наверное, как многие из вас знают, что для того, чтобы запросить какую-то информацию с сервера, например, там список юзеров, список групп, еще какую-то подробную информацию об одном юзере, обычно люди используют метод get. -2588.04 2594.56 SPEAKER_00 Вы делаете get, потом передаете туда адрес ресурса, и вам возвращается то, что вы хотели. -2594.56 2603.00 SPEAKER_00 Если вы хотите добавить какие-то дополнительные параметры, например, вам нужен список не всех юзеров, а как-то вы хотите отфильтровать, это тоже делается элементарно. -2603.00 2611.52 SPEAKER_00 Вы просто в query строку записываете какой-нибудь фильтр с каким-нибудь экспрессионом, и тоже у вас, в принципе, все работает. -2611.52 2615.84 SPEAKER_00 Фильтр отработает на сервере, вам вернутся к значению, и в принципе все счастливы. -2615.84 2619.00 SPEAKER_00 Но у этого подхода есть большие ограничения. -2619.00 2624.40 SPEAKER_00 Во-первых, вся эта query строка, она должна быть заискепиана, заинкожена. -2624.40 2637.32 SPEAKER_00 После того, как она заинкожена, на нее накладываются всякие ограничения HTTP спецификации, что у нее там есть определенные ограничения по размеру, которые зависят тоже от браузера, от версии, от погоды на Марсе. -2637.32 2651.28 SPEAKER_00 Но суть в том, что если вам вдруг нужно эту query строку сделать большую, то вы упретесь в тот факт, что сделать это практически нереально, потому что HTTP протокол не поддерживает большие query строки. -2651.28 2655.64 SPEAKER_00 А строку сделать большую, на самом деле, это не такая редкая ситуация, как вам кажется. -2655.64 2673.60 SPEAKER_00 Если взять тот же самый произвольный фильтр, который вы туда накладываете, и прибавить туда какое-нибудь более сложное условие, например, если пользователь находится в таком-то списке имен и передавать туда список имен, то вы очень быстро уткнетесь в тот лимит, буквально передать там несколько десятков имен и все. -2673.60 2681.08 SPEAKER_00 И лимит достигнут, и ваше приложение уже не работает, уже агент делать не сможет. -2681.08 2686.52 SPEAKER_00 Человечество столкнулось с этой проблемой довольно давно, и, соответственно, есть несколько способов ее решения. -2686.52 2692.52 SPEAKER_00 Одним из самых простых и порицаемых – это использование вместо GET-а поста. -2692.52 2700.00 SPEAKER_00 POST в данном случае от GET-а отличается тем, что у GET-а не имеет права иметь BODY. -2700.00 2703.64 SPEAKER_00 То есть у GET-а BODY не бывает, у него только query-параметры. -2703.64 2707.44 SPEAKER_00 А вот в POST можно засунуть любой BODY. -2707.44 2716.68 SPEAKER_00 Соответственно, весь тот огромный запрос, который у вас не влез в предыдущем пункте в GET, вы очень легко можете селезнуть и засунуть его в BODY-поста. -2716.68 2722.44 SPEAKER_00 На BODY практически нет никаких ограничений, в общем, вам его хватит с головой всегда и везде. -2722.44 2738.20 SPEAKER_00 Соответственно, у нас уже будет метод, который называется POST к ресурсу, который называется USER, или может быть даже в этом случае уже GET-USER, и в качестве экспрессиона, в качестве фильтра мы в BODY передадим все, что нам нужно. -2738.78 2746.94 SPEAKER_00 Данный подход не зря полицаем народом, потому что POST имеет кучу проблем. -2746.94 2752.10 SPEAKER_00 Самая главная проблема, на которую все обращают внимание в первую очередь, это в том, что он не кашируется. -2752.10 2762.02 SPEAKER_00 Действительно, у нас HTTP в мир, у нас HTTP протокол, и вот этот весь World Wide Web, он существует на куче спецификаций и договоренностей. -2762.02 2767.62 SPEAKER_00 И одна из самых главных договоренностей существует в том, что метод GET можно кашировать. -2767.62 2774.42 SPEAKER_00 Если у него одинаковые параметры в query-строке, то значит можно безболезненно отдавать какой-то результат. -2774.42 2779.98 SPEAKER_00 Естественно, на какое-то время, не навсегда, но это очень сильно увеличивает перформанс. -2779.98 2793.06 SPEAKER_00 Я думаю, когда мы разбирали методы оптимизации и методы улучшения перформанса команды ISP.NET Core и прочих команд в Дот-нете, вы увидели, что очень много вещей решается там с помощью кэша. -2793.06 2798.90 SPEAKER_00 И кэш вам дает обалденный буст производительности, если вы знаете, когда его правильно чистить. -2798.90 2802.18 SPEAKER_00 И вообще это один из самых первых методов оптимизации. -2802.18 2805.94 SPEAKER_00 Поэтому кэширование на самом деле это очень важно. -2805.94 2816.44 SPEAKER_00 Особенно если мы смотрим на сеть интернет, в которой там идут сексилиарды запросов в миллисекунду, то там кэширование становится просто ключевым фактором и просто так терять его не хотелось. -2816.44 2831.22 SPEAKER_00 Но если вы используете метод POST и передаете аргументы в BODY, то кэширование вы теряете на вот таких промежуточных узлах, которые вполне могли бы обеспечить более быстрый доступ к вашим методам. -2831.22 2835.50 SPEAKER_00 В большинстве случаев на это все забивали, потому что это было меньше изол. -2835.50 2840.22 SPEAKER_00 Если там мы просто в GIT не могли ничего сделать, то в POST мы всего лишь на все теряем кэширование. -2840.22 2850.74 SPEAKER_00 Ну, наверное, для большинства запросов это нормальная ситуация, но все же остаточек оставался. -2850.74 2862.14 SPEAKER_00 И как раз таки, чтобы убрать эту проблему, весь консорсум World Wide Web собрался и наконец-то в 21 веке придумал новое ключевое слово, которое называется QUERY. -2862.14 2881.06 SPEAKER_00 Это ключевое слово имеет полностью семантику GET, его же плюсы, то есть оно подразумевает, что все прокси будут кэшировать ответ, также подразумевается, что QUERY, так же как и GET, он иденпатентный, и ему прибавляется плюс POST. -2881.06 2883.42 SPEAKER_00 QUERY теперь может иметь BODY. -2883.42 2891.10 SPEAKER_00 В общем, в этот BODY можно засунуть опять же все, что вам угодно, даже тот expression, который вам нужно было бы передать, и он большой, страшный и все такое. -2891.10 2894.50 SPEAKER_00 Но теперь вы можете его засунуть в BODY, и это все будет кэшироваться. -2894.50 2897.14 SPEAKER_00 Вот ради этого изобрели новое слово. -2897.14 2900.06 SPEAKER_00 Слово, которое объединяет и GET, и POST. -2900.06 2902.94 SPEAKER_00 Теперь в BODY вы можете положить все, что угодно. -2902.94 2912.70 SPEAKER_00 Например, вы туда можете засунуть GRAPHQL, вы туда можете засунуть полноценный SQL SCRIPT, вы туда можете даже LINK положить, потому что теперь это можно. -2912.70 2916.14 SPEAKER_00 Теперь фильтр может быть вообще произвольной и произвольной длины. -2916.14 2921.82 SPEAKER_00 Теперь там можно и запросы вкладывать, и батчинги вкладывать, и скрипты вкладывать, вообще все, что вам только придет в голову. -2921.82 2925.38 SPEAKER_00 Вот консорциум такую штуку придумал. -2925.38 2928.46 SPEAKER_00 Отлично, но в официальном кестре она еще не появилась. -2928.46 2935.38 SPEAKER_00 Давайте же посмотрим, а как можно ее уже сейчас добавить в ваше приложение, и что для этого нужно сделать. -2935.38 2937.90 SPEAKER_00 Для начала рассмотрим MINIMAL API. -2937.90 2943.14 SPEAKER_00 На самом деле не нужно очень много кода для того, чтобы держать вот такую ключевую концепцию, как новое слово. -2943.14 2951.54 SPEAKER_00 А все потому, что на самом деле в HTTP протоколе не задекларирован какой-то строгий список этих глаголов. -2951.54 2954.62 SPEAKER_00 На самом деле вы туда можете передать абсолютно любой глагол. -2954.62 2958.58 SPEAKER_00 Другой вопрос, кто его будет поддерживать и как он будет обрабатываться, это дело десятое. -2958.58 2963.06 SPEAKER_00 Но вы можете, судя по самой спецификации протокола. -2963.06 2967.14 SPEAKER_00 Вот и здесь в принципе протокол никак нам не запрещает использовать новое слово. -2967.14 2973.30 SPEAKER_00 Нам осталось лишь научить наш MINIMAL API, наши хендлеры, наш ASP.NET обрабатывать эту штуку. -2973.30 2975.46 SPEAKER_00 И обработка тоже делается достаточно просто. -2975.46 2989.10 SPEAKER_00 Все, что вам нужно сделать, это сделать специальный метод, который называется MapQuery, по аналогии с другими экстеншн методами, который MapGet, MapPost, которые мапят соответствующий URL на его обработчик. -2989.10 3004.38 SPEAKER_00 В этом методе MapQuery у вас будет Endpoint Convention Builder, у которого достаточно вызвать метод MapMethod и передать ему этот глагол, то есть передать ему просто Query. -3004.38 3013.78 SPEAKER_00 В общем, этого достаточно для того, чтобы кестер сообразил, что как только вам приходит вот этот неизвестный глагол, должен вызываться ваш делегат. -3013.78 3017.62 SPEAKER_00 А в делегате уже непосредственно происходит обработка события. -3017.62 3026.78 SPEAKER_00 Этот делегат в MINIMAL API может принимать специальный класс, который описывает тот запрос к нему, как только к нему пришел. -3026.78 3029.14 SPEAKER_00 Это, допустим, класс Query. -3029.14 3040.74 SPEAKER_00 Теперь все, что вам нужно сделать, это создать вот этот класс Query и переопределить у него метод BindAsync, который при качестве параметра принимает HTTP контекст и параметр List. -3040.74 3055.78 SPEAKER_00 Как вы уже догадались, из HTTP контекста и из параметров вам нужно каким-то образом, известным только вашему обработчику, достать параметры, в нашем случае просто-напросто считать Body и положить его уже в какую-то заранее переменную для децерализованных данных. -3055.78 3058.14 SPEAKER_00 И дальше эта переменная будет доступна в делегате. -3058.14 3071.26 SPEAKER_00 Таким образом, вы можете теперь регистрировать ваши новые делегаты с помощью метода MapQuery, указывать route и принимать в качестве параметра тот децерализованный классик Query, который мы разобрали секунду назад. -3071.26 3073.62 SPEAKER_00 Обращаться, соответственно, к его свойствам. -3073.62 3075.10 SPEAKER_00 Все легко и просто. -3075.10 3078.54 SPEAKER_00 Как же сделать подобную штуку в ASP.NET Core MVC? -3078.54 3080.86 SPEAKER_00 На самом деле, еще проще. -3080.86 3088.78 SPEAKER_00 Вы просто-напросто добавляете еще один атрибут, например, HTTP Query атрибут, который наследуется от специального HTTP метод атрибута. -3088.78 3097.62 SPEAKER_00 И HTTP метод атрибут в конструкторе принимает список методов, которые поддерживает ваш вот этот вот атрибут. -3097.62 3100.30 SPEAKER_00 Естественно, вы туда передаете строку Query. -3100.30 3115.78 SPEAKER_00 Как только вы это сделали, со этого самого момента, вы можете навешивать ваш HTTP Query атрибут над вашими экшенами, над вашими методами контроллера, точно так же, как вы раньше навешивали HTTP GET, HTTP POST. -3115.78 3118.82 SPEAKER_00 Теперь у вас будет просто-напросто HTTP Query атрибут. -3118.82 3124.62 SPEAKER_00 И ваш метод уже будет дергаться непосредственно, как только придет Query глагол к кестрелу. -3124.62 3126.86 SPEAKER_00 Кестрел уже знает, что с ним делать. -3126.86 3127.94 SPEAKER_00 Вот в принципе вот так. -3127.94 3129.98 SPEAKER_00 Все намного проще, чем казалось. -3129.98 3133.26 SPEAKER_00 И поддерживается и в старых версиях, и в новых версиях, и где угодно. -3133.26 3137.98 SPEAKER_00 Лишний раз доказывается, что ASP.NET расширяется просто великолепно. -3137.98 3144.26 SPEAKER_00 В общем, если вы вдруг захотите использовать этот Query атрибут по-настоящему в вашем продакшн коде, то вот здесь вот сильно не торопитесь. -3144.26 3148.30 SPEAKER_00 Ну, во-первых, это все-таки еще экспериментальный метод. -3148.30 3151.86 SPEAKER_00 Все еще идут обсуждения, все еще идут какие-то договоренности. -3151.86 3157.26 SPEAKER_00 И в частности, он не поддерживается во многих сторонних инструментах. -3157.26 3160.58 SPEAKER_00 Во многих инструментах, которые окружают вас ежедневно. -3160.58 3168.18 SPEAKER_00 Ну, например, тот же самый Swashbuckle, который также известен как Swagger, который также известен как Open API Library. -3168.18 3171.14 SPEAKER_00 В общем, он еще не понимает этот новый кейворд. -3171.14 3177.34 SPEAKER_00 Соответственно, вы не сможете с помощью него отлаживать, запускать методы, которые вызываются с помощью Query. -3177.34 3182.78 SPEAKER_00 Также точно практически никто из инфраструктуры не поддерживает Query. -3182.78 3189.34 SPEAKER_00 То есть, вы можете потерять кэширование, load balancing и прочие вещи на сторонних каких-то инструментах. -3189.34 3194.02 SPEAKER_00 На Jinx, на Lastic Load Balancer и на прочей инфраструктуре. -3194.02 3196.74 SPEAKER_00 Они тоже пока еще не очень знают, что с ним делать. -3196.74 3205.86 SPEAKER_00 Эта поддержка добавляется, безусловно, я думаю, через некоторое время все главные библиотеки, все главные инструменты, которые развиваются, такую штуку к себе добавить. -3205.86 3208.62 SPEAKER_00 Но пока ситуация именно такая. -3208.62 3210.66 SPEAKER_00 Используется все на ваш страх и риск. -3210.66 3217.90 SPEAKER_00 Если вы вдруг захотите это использовать в продакшене, то обязательно смотрите, какими инструментами вы используетесь и проверяйте проверку у них. -3217.90 3225.18 SPEAKER_01 Ну, я что-то думаю, что пока это не будет поддержано в максимально большом количестве тулов, использовать это, ну не знаю зачем. -3225.18 3234.70 SPEAKER_01 Если это между вашими двумя приложениями, так можно и просто постом, а если куда-то наружу, так там в интернете мало кто это поддерживает, нормально пока еще, мне кажется. -3234.70 3240.02 SPEAKER_00 Да, к сожалению, мы не знаем через какие роутеры пройдет эта штука и какая версия, какого ПО там стоит. -3240.02 3241.58 SPEAKER_00 Поэтому мы можем только надеяться. -3241.58 3248.88 SPEAKER_01 Но пока у нас твой страх и риск, можно поэкспериментировать, не знаю, добавлять поддержку этой штуки в разные другие тулы. -3248.88 3250.86 SPEAKER_01 Вам, может, спасибо скажут за это. -3250.86 3253.22 SPEAKER_01 И потом все начнем использовать резко. -3253.22 3258.86 SPEAKER_01 Давай пойдем дальше, в другую часть нашего замечательного фреймворка. -3258.86 3261.22 SPEAKER_01 Ты знаешь ли ты, что такое memory model? -3261.22 3262.22 SPEAKER_01 Да, конечно. -3262.22 3264.50 SPEAKER_00 Знаешь ли ты, какая она у .NET? -3264.50 3267.62 SPEAKER_00 Я знаю в том, что она у .NET неформализованная. -3267.62 3268.62 SPEAKER_01 Ну, как? -3268.62 3270.90 SPEAKER_01 Значит, на самом деле у нас есть спека. -3270.90 3276.22 SPEAKER_01 Спека называется ECMO-335, насколько я помню, на рантайм, да? -3276.22 3279.00 SPEAKER_01 И технически там что-то описано. -3279.00 3289.96 SPEAKER_01 Но то, что там описано, оно очень, то, что называется weak, то есть оно слабое, то есть оно подходит под много чего и дает очень мало. -3289.96 3295.72 SPEAKER_00 Она мега абстрактная и какие-то конкретные вещи, которые вам нужно ответить на вопрос, а здесь что будет? -3295.72 3297.92 SPEAKER_00 Вот обычно на такие конкретные вещи она не отвечает. -3297.92 3301.20 SPEAKER_01 Ну, она не отвечает в том смысле, что она разрешает довольно много всего. -3301.20 3307.86 SPEAKER_01 То есть рантайм, который удовлетворяет ECMO-335, может делать, ну не то чтобы все что угодно, но там довольно мало ограничений. -3307.86 3332.06 SPEAKER_01 В реальной жизни рантайм, он гораздо более ограничен, потому что исторически .NET Runtime развивался на железе, которое чуть более ограничено, и даже сейчас, когда мы переехали, ну не переехали, а позволили поддерживать и армы и всякие странные процессоры, реалии таковы, что реальные железные ограничения все равно сильнее, чем ECMO, насколько я понимаю. -3332.06 3346.16 SPEAKER_01 Поэтому в репе .NET Runtime появилась наконец-таки идея сделать нормальное описание .NET Memory Model, а что же собственно текущий современный .NET Runtime в принципе сейчас предоставляет. -3346.16 3359.16 SPEAKER_01 Он предоставляет некоторый компромисс, чтобы быть разумно работающим на всех платформах и при этом все еще удовлетворять ECMO-335, и при этом чтобы это было как-то нормально, понятно, используемо. -3359.16 3373.16 SPEAKER_01 И появился pull request, он появился где-то в сентябре, если я правильно помню, в котором появилась некоторая, просто видите, страничка в том самом ботере буквы Runtime, где написано .NET Memory Model. -3373.16 3377.00 SPEAKER_01 Если вы хотели узнать, что же такое .NET Runtime Memory Model, вам туда. -3377.00 3399.64 SPEAKER_01 Это пока еще не финальный вариант, там активнейшее обсуждение, там пришли все самые умные люди из Runtime и все это дело активно обсуждают, то есть я там не то чтобы половину комментов не понял, но чтобы их понять надо реально хорошо вчитываться, кто там куда, кого заимствует, кто как читает, какие reordering разрешены и все такое прочее. -3399.64 3408.68 SPEAKER_01 Но если вам это интересно, если вы всегда хотели узнать, как же по-настоящему работает volatile, что он гарантирует, что он не гарантирует, то идите туда и посмотрите. -3408.68 3421.60 SPEAKER_01 Также там есть интересная секция, последняя в этом документе, это практически примеры того, как же нужно реализовывать правильно паттерны, то есть типа условный double check log для singleton, вот этого всего. -3421.60 3436.04 SPEAKER_01 Там это все написано правильно, ну даже не то чтобы правильно, а минимально необходимо, то есть понятно, что можно все обвесить логами и все будет работать, но на самом деле местами достаточно делать volatile read и volatile write и все тоже будет работать. -3436.04 3440.28 SPEAKER_01 Вот там написано как бы минимально правильные примеры, как это нужно все делать. -3440.28 3448.52 SPEAKER_00 Вот это интересный вопрос, знаешь, обычно на собеседование задают, типа реализуйте мне самый примитивный какой-нибудь double checking log. -3448.52 3472.12 SPEAKER_00 На самом деле, если придерживаться официальной спецификации memory module, то однозначно реализовать его невозможно, потому что, ну однозначно примитивный, самый минимальный реализовать невозможно, потому что мы не знаем, как ведет себя memory module и мы не знаем, где эта штука будет запускаться, это зависит от рантайма, от версии и от железа и от много всего еще. -3472.12 3478.04 SPEAKER_00 Поэтому такой простейский вопрос, на который, наверное, уже каждый джун отвечает, на самом деле не имеет ответа. -3478.04 3482.00 SPEAKER_01 Ну, как бы да, каждый джун отвечает, делаем log, да. -3482.00 3483.92 SPEAKER_01 Да, делаем два лока и все хорошо. -3483.92 3487.24 SPEAKER_01 Нет, подожди, один log, два if, if log, if. -3487.24 3488.24 SPEAKER_01 Да, два if. -3488.24 3497.76 SPEAKER_01 Вот, и как бы везде, где работает dotnet, работать будет, потому что dotnet runtime, он вот некоторые гарантии дает. -3497.76 3501.88 SPEAKER_01 Но на самом деле можно написать его чуть более оптимально, вот это все. -3501.88 3515.76 SPEAKER_01 Поэтому если вам интересна тема вот этих всех memory modules, да, acquired read, write, reordering, вот это все, идите, читайте, участвуйте в обсуждении, задавайте вопросы, там довольно все активно живет. -3515.76 3526.24 SPEAKER_01 PR, не знаю, когда будет реально закоммичено, я думаю, что они будут долго обсуждать, пока не придут к какому-то общему пониманию и правильным примерам и терминологии. -3526.24 3532.52 SPEAKER_01 Там не только обсуждается непосредственно, что же мы реализовали и как оно на самом деле работает, но и какими примерами это лучше иллюстрировать. -3532.52 3540.20 SPEAKER_01 То есть там часть, по крайней мере, комментов, которые я читал к этому pull request, они про то, что вот этот пример не совсем характерен, давайте лучше вот такой возьмем. -3540.20 3552.36 SPEAKER_01 А если вы новичок и вам, в принципе, интересно, что такое memory module, то у нас в шоу-ноутах будет еще ссылочка на очень старый доклад Саши Гальштейна на dotnext про C++ и CLR memory modules. -3552.36 3573.84 SPEAKER_01 Тогда не было ничего еще стандартизированного и формализованного, но некоторое понимание того все-таки, как работает CLR memory module в то время, это 6 лет назад, уже было, некоторое понимание было, и он как раз-таки рассказывает вообще, что это такое, как к этому подходить и какие основные термины, концепции есть и чем они на самом деле отличаются от плюсов, если вам это интересно. -3573.84 3585.04 SPEAKER_00 Кажется, именно там у него есть такие смешные демки, которые казалось бы абсолютно правильный код, и который все пишут и все такое, работает немножко не так, как на самом деле. -3585.04 3598.64 SPEAKER_01 Да, я помню, что доклад был хороший, давно его не пересматривал, надо будет действительно как-нибудь посмотреть, как раз и memory module почитать современную, чтобы уяснить себе-таки, как оно работает, и как же правильно надо отвечать на вопросы на собеседованиях. -3598.64 3609.20 SPEAKER_00 Я думаю, когда этот доклад выйдет, мы там не один доклад на эту тему еще должны увидеть, услышать и не одну статейку прочитать, потому что труд действительно нужный, монументальный. -3609.20 3615.96 SPEAKER_00 Конечно, интересно, что его делают постфактум, когда уже все состоялось, и обычно memory module делают в самом начале, когда пишут runtime. -3615.96 3617.96 SPEAKER_00 Но что имеем, то имеем. -3617.96 3627.00 SPEAKER_01 Не, ну как бы, может быть она в каком-то виде и есть в головах у тех, кто пишет этот самый runtime, просто это некоторая попытка его формально записать в понятном виде. -3627.00 3634.76 SPEAKER_00 Я думаю, она есть в коде, то есть runtime как-то работает по какой-то модели, и сейчас пытаются именно ее описать и как-то подогнать под теорию. -3634.76 3644.56 SPEAKER_01 Ну и хорошо, пошли в еще одну интересную тему, как я сказал, дотунайт работает много где, и в том числе на Raspberry. -3644.56 3648.00 SPEAKER_00 Да, продолжаем рубрику, расширяем горизонты. -3648.00 3656.48 SPEAKER_00 Хочется еще об некоторых технологиях вам рассказать, может быть, которые почему-то вы еще не слышали, и это мы устраним с помощью нашего образовательно-новостного подкаста. -3656.48 3665.36 SPEAKER_00 Хочется рассказать о том, каким же образом все-таки запустить дотнет через WASM на Raspberry Pi. -3665.36 3669.24 SPEAKER_00 Вот такая сложная цепочка, давайте посмотрим по каждому пункту в отдельности. -3669.24 3672.24 SPEAKER_00 Во-первых, для тех, кто в танке, что такое WASM. -3672.24 3677.84 SPEAKER_00 Вы с WASM знакомы, наверное, давно, когда еще в дотнете появились первые версии Blazor, Blazor WebAssembly. -3677.84 3685.68 SPEAKER_00 Это такая специальная технология, которая позволяет вам дотнет компилировать прямо под браузер, грубо говоря, под движок джаваскрипта. -3685.68 3693.60 SPEAKER_00 И, соответственно, браузер может выполнять вашу программу, не обращаясь к серверу, даже вообще не имея никакого коннекта к серверу, вообще даже офлайн. -3693.60 3696.36 SPEAKER_00 Он один раз загружает сборочку и выполняет ее. -3696.36 3699.08 SPEAKER_00 И это достигается с помощью технологии WASM. -3699.08 3703.60 SPEAKER_00 WASM прекрасен тем, что он не только для дотнета. -3703.60 3713.92 SPEAKER_00 Поэтому, когда сравнивают почему-то Blazor с Silverlight, вот здесь, безусловно, нужно учитывать, что это не какая-то плагина от Microsoft, которая нужна только для дотнета. -3713.92 3715.48 SPEAKER_00 Нет, WASM пошел другим путем. -3715.48 3720.48 SPEAKER_00 Теперь это встроенная фишка во все современные браузеры, в том числе в мобильные. -3720.48 3730.12 SPEAKER_00 Поддерживается она очень многими производителями и достойными всеми нормальными языками. -3730.12 3735.48 SPEAKER_00 На самом деле это набор бинарных инструкций для специальной stack-based virtual машины. -3735.48 3744.48 SPEAKER_00 Это, как я уже сказал, язык программирования, который не зависит от архитектуры. -3744.48 3751.68 SPEAKER_00 То есть он очень портабельный, он выполняется абсолютно везде, где может выполняться в данном случае браузер и JavaScript. -3751.68 3754.92 SPEAKER_00 А это, как мы понимаем, практически любая платформа. -3754.92 3759.48 SPEAKER_00 Он очень низкоуровневый, он больше похож на Assembler. -3759.48 3770.68 SPEAKER_00 Если вы когда-нибудь интересовались, заглядывали или гуглили, как выглядят Assembler инструкции, или если вы заглядывали в .NET.IL, то WASM напоминает именно его. -3770.68 3774.56 SPEAKER_00 То есть это минимальные Assembly инструкции для виртуальной машины. -3774.56 3783.12 SPEAKER_00 Он бинарный и он очень компактный, потому что сразу рассчитывалось на то, что будут передавать по сети, поэтому он должен быть очень сжатым, красивым, быстрым. -3783.12 3786.28 SPEAKER_00 В общем, и этого удалось достигнуть. -3786.28 3795.02 SPEAKER_00 И самое интересное, что его перформанс довольно высокий, потому что многие браузеры его поддерживают нативно. -3795.02 3806.32 SPEAKER_00 И там были выбраны специально, подобраны инструкции таким образом, чтобы они хорошо ложились на векторизацию, на нативные команды процессора, на нативные команды видеокарт и прочее, прочее. -3806.32 3821.60 SPEAKER_00 То есть язык разрабатывался специально для трехмерной реальности, для виртуальных игр, для еще вот таких вот очень ресурсов, таких активностей, которые требуют очень много производительности. -3821.60 3825.80 SPEAKER_00 Поэтому он получился довольно компактный, довольно хорошо производительный. -3825.80 3834.72 SPEAKER_00 И как я уже упомянул, нормальные языки, такие как C#, C, C++, Rust, все недавно умеют и хорошо компилироваться именно в WASM. -3834.72 3841.56 SPEAKER_00 Таким образом у нас получается, что WASM — это такой интересный кроссплатформенный формат. -3841.56 3850.88 SPEAKER_00 Наверное, многие большевики рассчитывали и надеялись на то, что у нас появится какой-нибудь формат, куда можно один раз скомпилировать и запускать абсолютно на всех платформах, на везде. -3850.88 3856.24 SPEAKER_00 Но вряд ли кто-то мог представить, что это будет какой-то там отросток от JavaScript. -3856.24 3858.28 SPEAKER_00 Но по сути получилось именно так. -3858.28 3870.12 SPEAKER_00 Намного легче было написать кроссбраузерный JavaScript, захватить мир и потом на JavaScript сделать оптимизированный общесистемный низкоуровневый язык. -3870.12 3871.12 SPEAKER_00 Получилось смешно. -3871.12 3874.12 SPEAKER_00 Но, как ни странно, получилось очень хорошо. -3874.12 3879.88 SPEAKER_00 И народ подхватил эту идею и подумал, а зачем нам обязательно запускать это все в браузере. -3879.88 3883.32 SPEAKER_00 В принципе, получился отличный формат, поддерживается многими языками. -3883.32 3890.16 SPEAKER_00 Он быстрый, он компактный, он интересный, он довольно легко читается и понимается. -3890.16 3896.12 SPEAKER_00 А давайте мы будем его использовать как обычный формат для любого языка программирования. -3896.12 3902.68 SPEAKER_00 То есть, по сути, запускать все эти приложения не в браузере, а запускать все эти приложения вообще на любом хосте. -3902.68 3905.48 SPEAKER_00 И таким образом появился Wasi. -3905.48 3908.64 SPEAKER_00 Wasi – это WebAssembly System Interface. -3908.64 3918.96 SPEAKER_00 Это как раз-таки отдельный стандарт для Wasmo, который рассказывает о том, каким образом Wasmo взаимодействовать с любым окружением на хосте. -3918.96 3921.68 SPEAKER_00 Хостом может быть любая операционная система. -3921.68 3927.56 SPEAKER_00 Его можно запускать на чистом Linux, на Android, на Windows и вообще где угодно. -3927.56 3929.08 SPEAKER_00 Везде, где что-то запускается. -3929.08 3938.20 SPEAKER_00 Вот каким образом из песочницы JavaScript перетащить его на полноценную операционную систему, этим и занимается как раз вот этот System Interface. -3938.20 3944.56 SPEAKER_00 То есть, это набор API, с помощью которого WebAssembly может вызывать нативные хостовые методы. -3944.56 3951.40 SPEAKER_00 Таким образом, Wasi помогает вам запустить вашу Wasm-сборку без браузера на чистом хосте. -3951.40 3956.76 SPEAKER_00 И для того, чтобы это сделать, нам нужны соответствующие рантаймы, которые реализуют данный подход. -3956.76 3962.32 SPEAKER_00 Из известных есть WasmTime, Wasmir или WasmEdge. -3962.32 3964.52 SPEAKER_00 Давайте же теперь посмотрим, как это все связано с .NET. -3964.52 3966.76 SPEAKER_00 На .NET очень легко получить Wasi Project. -3966.76 3973.04 SPEAKER_00 Для этого вам достаточно всего лишь на все немножко поменять стандартный WebAPI проект. -3973.04 3979.88 SPEAKER_00 После этого вы можете создать обычный WebAPI проект, допустим, даже с дефолтным вот этим приложением, который там погодку нам показывает. -3979.88 3983.92 SPEAKER_00 Оставим его таким же точно пустым, сделаем .NET Publish -c release. -3983.92 3993.64 SPEAKER_00 И в результате, на выходе в Output мы уже получим не какую-то сборочку или .exe, а получим файл с расширением Wasm. -3993.64 3997.88 SPEAKER_00 Этот файл можно запустить, допустим, прямо на Windows. -3997.88 3999.68 SPEAKER_00 Для этого нам понадобится WasmTime. -3999.68 4004.72 SPEAKER_00 WasmTime – это очень быстрая и security runtime для WebAssembly. -4004.72 4014.04 SPEAKER_00 Это как раз таки и есть та запускалка, которая способна интерпретировать код Wasm на многих операционных системах. -4014.04 4018.56 SPEAKER_00 Мы можем скачать WasmTime с GitHub. -4018.56 4020.08 SPEAKER_00 Вызывается все довольно просто. -4020.08 4026.84 SPEAKER_00 WasmTime, пробел и указываем имя того Output приложения, которое у нас появилось с расширением .wasm. -4026.84 4029.56 SPEAKER_00 Как только мы его указали, у нас запустится это приложение. -4029.56 4035.68 SPEAKER_00 Можно сделать проще, можно просто даже запустить .NET Run, если мы находимся в каталоге с нашим Wasi Solution. -4035.68 4039.68 SPEAKER_00 И .NET Run вам, соответственно, запустит приложение. -4039.68 4048.32 SPEAKER_00 Вы после этого можете открыть браузер, зайти на Localhost и убедиться, что весь WPPI отвечает вам стандартными отчетами про коду. -4048.32 4054.30 SPEAKER_00 Вот так просто получить из .NET Wasm. -4054.30 4055.60 SPEAKER_00 Мы на этом не останавливаемся. -4055.60 4059.16 SPEAKER_00 Мы хотим запульнуть наш Wasm на Raspberry Pi. -4059.16 4066.44 SPEAKER_00 Если кто не знал, то в последних Windows давно SSH и SCP входят в коробочную версию. -4066.44 4069.16 SPEAKER_00 То есть, поставляются out of box эти утилиты. -4069.16 4078.80 SPEAKER_00 С помощью SSH мы можем коннектиться к удаленному хосту по протоколу SSH, а с помощью SCP мы можем просто-напросто скопировать какой-то файлик на удаленный хост. -4078.80 4080.16 SPEAKER_00 Чем мы, собственно, и займемся. -4080.16 4085.64 SPEAKER_00 Возьмем этот файлик с Wasm и скопируем его с нашего PC на Raspberry Pi. -4085.64 4090.36 SPEAKER_00 После этого мы с помощью SSH можем подконнектиться к Raspberry Pi. -4090.36 4094.40 SPEAKER_00 Там нам нужно снова установить WasmTime для Raspberry Pi. -4094.40 4100.84 SPEAKER_00 Это делается с помощью скачивания с GitHub, разархивирования и у нас уже есть готовый запускальщик в WebAssembly. -4100.84 4108.24 SPEAKER_00 Точно так же WasmTime, пробел, наш файлик .wasm и на Raspberry Pi все точно так же запускается. -4108.24 4116.24 SPEAKER_00 Вот таким образом выглядит эра кроссплатформенности, межязыковости и так далее. -4116.24 4122.28 SPEAKER_00 Тут уже опять еще раз стоит напомнить, что эти Wasm файлы их может генерить абсолютно любой язык программирования. -4122.28 4124.48 SPEAKER_00 Любой нормальный современный язык программирования. -4124.48 4129.12 SPEAKER_00 То есть вы можете собрать какие-то утилиты с помощью разных языков. -4129.12 4131.96 SPEAKER_00 Вы можете писать плагины с помощью разных языков. -4131.96 4138.76 SPEAKER_00 Уже мы никак не опираемся на совместимость с архитектурой, с операционной системой, еще с чем-то. -4138.76 4142.76 SPEAKER_00 Wasm предоставляет нам такой хороший абстрактный слой. -4142.76 4146.60 SPEAKER_00 Соответственно мы с вами посмотрели каким образом создаются Wasm модули в дот-нете. -4146.60 4155.64 SPEAKER_00 Каким образом можно сделать Web API прямо на чистом Wasm и как его запустить под виндой, как его запустить под Raspberry Pi. -4155.64 4159.12 SPEAKER_00 И познакомились с утилитой WasmTime. -4159.12 4162.72 SPEAKER_00 Таких утилит, которые способны запускать их несколько, WasmTime это одна из них. -4162.72 4166.60 SPEAKER_00 Вот такое интересное будущее рисует нам WebAssembly. -4166.60 4176.56 SPEAKER_01 Ну да, кажется, что если мы туда можем купить вообще все что угодно и запускать это везде, где может быть запущен Wasm, то это такой почти докер. -4176.56 4177.56 SPEAKER_00 Именно так. -4177.56 4188.96 SPEAKER_00 Когда мы разговаривали про чистый Wasm, то при его разработке учитывалась та специфика, что он как раз таки будет запускаться всегда в браузере. -4188.96 4192.36 SPEAKER_00 А браузер это должна быть очень секурная песочница. -4192.36 4199.64 SPEAKER_00 Потому что из браузера никогда ваш ни JavaScript, ни какие-то другие скрипты, которые вы скачали из сторонних сервисов выбраться не должны. -4199.64 4206.12 SPEAKER_00 Потому что как только в этой песочнице найдется дыра, то сразу в мире можно заразить миллиарды компьютеров, миллиарды пользователей. -4206.12 4208.00 SPEAKER_00 Это очень-очень-очень страшно. -4208.00 4210.96 SPEAKER_00 Поэтому в браузерах обычно железобетонные песочницы. -4210.96 4217.36 SPEAKER_00 В самом Wasm есть специальные механизмы, которые позволяют железобетонные песочницы поддерживать. -4217.36 4225.04 SPEAKER_00 То есть это штука, которая изначально проектировалась именно для того, чтобы секурно запускаться в песочницах. -4225.04 4229.48 SPEAKER_01 Ну и это как раз то, что нужно для докера по большому счету. -4229.48 4230.88 SPEAKER_01 Ну или для чего-то, что может заменить докер. -4230.88 4234.12 SPEAKER_01 Только более, не знаю, легковесное что ли. -4234.12 4251.76 SPEAKER_00 Вот эта возможность запускаться в неком контейнере, который может быть ограничен по ресурсам, который обязательно ограничен по секьюрности и который распространяется в виде какого-то межплатформенного формата, которым вы тоже не должны задумываться, под какую архитектуру его скомпилить. -4251.76 4254.44 SPEAKER_00 Кажется, что это прекрасная замена контейнером. -4254.44 4263.40 SPEAKER_00 Более того, если вы используете Kubernetes, то под Kubernetes уже есть специальное расширение, которое позволяет вам запускать не контейнеры, а именно вот эти Wasm файлы. -4263.40 4269.40 SPEAKER_00 Именно как обычный докер-контейнер, как в обычных ваших приложениях. -4269.40 4270.40 SPEAKER_01 Прекрасно. -4270.40 4273.08 SPEAKER_01 Ну в общем, посмотрим, куда это все сдвинется. -4273.08 4285.24 SPEAKER_01 Кажется, что в ближайшее время, ну я пока не слышал о таком широком распространении этой техники, назовем это так, но действительно потихонечку появляются всякие плагины и поддержка этого дела. -4285.24 4290.96 SPEAKER_01 Так что может быть мы и увидим переход с докер-контейнеров на Wasm-контейнеры или как их там назовут. -4290.96 4298.48 SPEAKER_00 А также смотри, можно дойти до операционной системы, которая ничего не умеет, кроме как интерпретировать Wasm, которую запускать Wasm. -4298.48 4313.04 SPEAKER_00 Теперь можно на Wasm записать операционную систему, все модули расширения, все плагины, все программы писать под ней, у тебя автоматически получится, все программы будут изолированными, будут мега-секьюрными, и очень сложно будет под такую штуку писать вирусы, например. -4313.04 4315.36 SPEAKER_00 В общем, эта дорожка может привести нас очень далеко. -4315.36 4319.16 SPEAKER_01 Ну посмотрим, как далеко и как быстро она нас туда приведет. -4319.16 4333.64 SPEAKER_01 Ну а потом еще в одну тему у нас давно достаточно лежит в бэклоге статья от Маони, главного архитектора Garbage Collector в Дотнете, и наконец-таки мы до нее добрались. -4333.64 4348.92 SPEAKER_01 И статья продолжает цикл довольно редких статей от Маони про Garbage Collector и раскрывает, куда же немножко они двигаются, точнее немножко раскрывают, куда они двигаются или планируют двигаться. -4348.92 4375.76 SPEAKER_01 Напомню, что в шестом Дотнете появились и в седьмом уже были официально включены так называемые регионы вместо сегментов, то есть Garbage Collector у нас работал раньше на сегментах, это большие куски памяти, там от сотни мегабайт и больше, где внутри них уже каким-то образом распределялись там нулевое первое поколение в эфемерный сегмент или сегменты, а второе поколение в прочий сегмент, но тоже большой. -4375.76 4408.92 SPEAKER_01 В какой-то момент было принято решение, что мы переходим на регионы, это уже более маленькие, ну скажем так, блоки памяти по 4 мегабайта или около того, которые можно свободно переиспользовать между разными сегментами, и одна из целей это была возможность декомитить какое-то количество памяти, но также это открывает некоторые возможности более правильной оптимизации, более интересных, так скажем, оптимизаций с точки зрения того, как мы работаем вообще с памятью не только с точки зрения garbage collection, а вообще работаем с памятью. -4408.92 4414.56 SPEAKER_01 И одна из оптимизаций как раз таки описана в этой статье, называется она более точные write barriers. -4414.56 4423.32 SPEAKER_01 Вы можете подумать, что если мы говорим про барьеры, это про memory model, который мы обсуждали чуть выше, потому что там тоже есть понятие memory barrier, но это не про то. -4423.32 4428.68 SPEAKER_01 Это про другую штуку, которая именно в контексте garbage collection. -4428.68 4439.80 SPEAKER_01 Представьте себе, что у вас есть некоторое поле в каком-то объекте, назовем его field, и новый объект, object, который вы присваиваете в это поле. -4439.80 4445.72 SPEAKER_01 Ну, операция, которую вы делаете очень часто, да, сохраняете ссылку на объект в каком-то поле. -4445.72 4456.04 SPEAKER_01 Каждый раз, когда вы выполняете такой код, у вас на самом деле выполняется метод внутри JIT, точнее JIT вызывает метод, называется JIT write barrier. -4456.04 4465.28 SPEAKER_01 И исходная цель заключается в том, чтобы, собственно, на основе этого у нас и получается сделать поколенческий garbage collector. -4465.28 4473.28 SPEAKER_01 То есть нам нужно знать, какие поколения смотреть, когда мы будем собирать, точнее, какие объекты смотреть, когда мы будем собирать то или иное поколение. -4473.28 4493.84 SPEAKER_01 Для этого нужно знать, какие объекты в каком поколении вообще потенциально могли измениться или могли получить, не то чтобы измениться, а получить новых родителей, точнее новых, как это сказать, не родителей, тех, кто их удерживает в памяти, вот удаление новых там, рутов, назовем это так. -4493.84 4513.28 SPEAKER_01 Если вы читали книжку "Кондрат Кокос" или слушали какой-то из наших подкастов из древних, где мы хоть что-то описывали про garbage collector, вы, может быть, знаете такой термин как cartable, это, грубо говоря, некоторая такая масочка по всему адресному пространству памяти, где одному битику соответствует некоторое количество килобайт в памяти. -4513.28 4528.84 SPEAKER_01 И если вот такое присвоение меняет хоть какой-то объект в этом регионе памяти, то в cartable этот битик проставляется в единичку, это значит, что когда сработает следующий garbage collector, он знает, в какие регионы памяти нужно посмотреть на предмет появившихся новых ссылок на объекты. -4528.84 4533.00 SPEAKER_01 Возможно, там ничего не появилось, но может быть, появилось. -4533.00 4541.40 SPEAKER_01 Когда .NET был спортирован на Linux, работа в RightBarrier заключалась ровно в том, что там нужно просто проставить этот самый битик. -4541.40 4548.64 SPEAKER_01 На самом деле проставлялся байтик, потому что атомарно поставить битик сложно, а байтик, ну как бы, архитектуру поддерживает. -4548.64 4555.84 SPEAKER_01 Когда это все спортировали на Linux, в эту функцию gRightBarrier добавили еще одну функциональность. -4555.84 4560.84 SPEAKER_01 На Linux дело в том, что нет такой штуки, как PageRightWatch, которая поддерживает винда. -4560.84 4569.24 SPEAKER_01 То есть винда умеет идентифицировать процесс о том, что в какую-то страничку памяти что-то записали в этом процессе. -4569.24 4572.84 SPEAKER_01 Linux такого не умеет, поэтому теперь RightBarrier занимается примерно тем же самым. -4572.84 4582.34 SPEAKER_01 И в случае с сегментами у этой функции RightBarrier была следующая задача. -4582.34 4605.64 SPEAKER_01 Во-первых, нужно было понять, пишем ли мы куда-то в heap или может быть мы присваиваем, не знаю, в поле структуры, которое лежит на стейке, и тогда нам не надо ничего добавлять ни в какой CardTable, потому что стейк у нас по дефолту будет, да, крутый, мы его в любом случае будем просматривать при сборке мусора, и тогда ничего писать никуда не надо. -4605.64 4616.40 SPEAKER_01 Для того, чтобы понять, есть ли это ссылка в heap, ну ссылка, куда мы пишем, она в heap или не в heap, для сегментов было просто, сегменты они большие, у каждого есть начало и конец. -4616.40 4625.36 SPEAKER_01 Особенно для эфемерного сегмента все просто, в Workstation GT он вообще один, и поэтому у вас здесь по сути два адреса, начало сегмента и конец сегмента. -4625.36 4632.28 SPEAKER_01 Сравнили адрес, куда мы пишем, с этим двумя и точно поняли, мы попадаем в эфемерный сегмент или не попадаем. -4632.28 4643.48 SPEAKER_01 С серверным GC все сложнее, потому что там есть несколько эфемерных сегментов, поэтому там была другая логика, там CardTable он обновлялся вообще безусловно. -4643.48 4648.44 SPEAKER_01 Если мы дернули какой-то кусочек памяти и он не на стейке, то мы считаем, что он в heapе и обновляем. -4648.44 4649.44 SPEAKER_01 Вот. -4649.44 4674.12 SPEAKER_01 В седьмом дотнете вот эти write barriers стали гораздо более точными, потому что у нас есть регионы, региончики они маленькие, они могут быть раскиданы где угодно, между ними могут быть какие-то дырки, и поэтому мы не можем себе позволить просто так считать, что вообще все это heap, потому что регионов много, и, ну, они не такие последовательные, может быть их будет слишком много и они будут раскиданы слишком далеко по виртуальной памяти. -4674.12 4679.28 SPEAKER_01 И самое главное, что каждый регион может быть вообще говоря в любом поколении, у нас теперь нету такой строгой последовательности. -4679.28 4690.00 SPEAKER_01 Для регионов у нас хранится так называемая generation info map, это некоторая, ну, словарик карта того, в каком поколении соответствует какой регион. -4690.00 4713.84 SPEAKER_01 Она хранится достаточно компактно, потому что в отличие от cart table, где по-моему на один бит требовалось около, в смысле один бит описывал по-моему странички то ли по 4, то ли по 16 килобайт, ну не странички, а регионы памяти, здесь у нас один регион это 4 мегабайта как минимум, поэтому количество битов для описания того, в каком поколении этот регион находится, ну, нужно говорить, гораздо меньше. -4713.84 4720.92 SPEAKER_01 Майкрософт утверждает, что настолько мало, что в принципе эта информация частенько попадает нормально в кэшброса и там хранится. -4720.92 4735.12 SPEAKER_01 Поэтому сейчас, вот, собственно, после этой оптимизации, алгоритм теперь выглядит следующим образом, того, что делает, того, что emitted JIT, по сути, вызов вот этой функции JIT write barrier, и она делает теперь следующую штуку. -4735.12 4745.16 SPEAKER_01 Сначала мы берем номер поколения того, куда мы пишем, то есть того адреса, куда мы пишем по вот этому generationInfoMap, это быстрая и простая операция. -4745.16 4750.44 SPEAKER_01 Если это нулевое поколение, вообще ничего делать не надо, то есть мы сохранили ссылку на объект в объект нулевого поколения. -4750.44 4758.04 SPEAKER_01 И объекты нулевого поколения мы в любом случае будем просматривать при следующей фазе сборки мусора, поэтому ничего дополнительно отмечать не надо. -4758.04 4772.72 SPEAKER_01 Если мы, если же это все-таки не объект нулевого поколения, а там первого или второго, то может быть мы сделали следующее, может быть мы свежесозданный объект, который сейчас живет в нулевом поколении, ссылку на него положили в какой-нибудь долго живущий объект. -4772.72 4787.56 SPEAKER_01 И это значит, что когда мы будем собирать нулевое поколение, нужно не забыть проверить в качестве рутов еще и те объекты, которые мы затронули в более старших поколениях, потому что иначе, если мы их не посмотрим, то мы не найдем ссылок на этот новый объект в нулевом поколении и его соберем. -4787.56 4788.56 SPEAKER_01 Вот плохо. -4788.56 4794.84 SPEAKER_01 Поэтому мы берем и выясняем, собственно, поколение того объекта, который мы присваиваем. -4794.84 4799.40 SPEAKER_01 Возможно оно нулевое, возможно первое, возможно второе. -4799.40 4807.68 SPEAKER_01 Если поколение объекта, который мы присваиваем, больше либо такой же, чем поколение филда, в который мы его присваиваем, то делать ничего не надо. -4807.68 4812.64 SPEAKER_01 То есть мы положили ссылку на более старший объект, ссылку в более новый объект. -4812.64 4814.32 SPEAKER_01 Ничего страшного, все нормально. -4814.32 4827.12 SPEAKER_01 А вот если наоборот, то есть мы сохранили ссылку на объект нулевого поколения в второе поколение, например, и перешли в первое, то тогда нам нужно таки update карт table. -4827.12 4835.96 SPEAKER_01 В результате получается из этого алгоритма, что мы гораздо реже обновляем карт тейбл, особенно в случае с сервером ГЦ, потому что раньше мы это делали безусловно. -4835.96 4850.64 SPEAKER_01 И в результате, когда у нас наступает фаза сборки мусора, Mark phase, когда мы пробегаемся по всем объектам и размечаем, кого удалить, кого не удалять, эта фаза протекает гораздо быстрее, потому что нам нужно просмотреть гораздо меньше объектов. -4850.64 4853.88 SPEAKER_01 Карт тейбл, собственно, используется как источник того, сколько нам посмотреть. -4853.88 4867.24 SPEAKER_01 Более того, после некоторых экспериментов Microsoft пришли к выводу, что на самом деле, несмотря на то, что вроде как архитектура у нас атомарно, по сути, мы можем поставить только байт, мы не можем атомарно поставить бит. -4867.24 4876.88 SPEAKER_01 Но фактически Microsoft теперь ставит бит, то есть она атомарно ставит байт, изменяя в нем один бит. -4876.88 4889.56 SPEAKER_01 То есть технически, если два конкурирующих потока будут проставлять один и тот же байт в карт тейбле, пытаясь поставить разные биты, то кто-то из них победит, а второму придется делать лишние захотные на простановку. -4889.56 4892.04 SPEAKER_01 То есть технически может быть больше контеншн. -4892.04 4895.56 SPEAKER_01 Но фактически эксперименты показали, что не так все +0.00 11.24 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Radio.net выпуск номер 61. +11.24 15.00 "Анатолий Кулаков" Прежде всего, хотелось бы поблагодарить наших помогаторов. +15.00 24.00 "Анатолий Кулаков" Это прекраснейший список – Александр, Сергей, Владислав, Алексей, Шевченко Антон, Илья и Гурий Самарин, что давно не растет, задумайтесь уже. +24.00 27.24 "Анатолий Кулаков" Спасибо большое всем, кто нас поддерживает. +27.24 30.60 "Анатолий Кулаков" И начинаем выпуск, что у нас там сегодня интересного? +30.60 37.00 "Игорь Лабутин" Ну, во-первых, хочется напомнить, что прошел онлайн.next 3-4 ноября. +37.00 39.04 "Игорь Лабутин" Если у вас есть билет, доступны все записи. +39.04 57.64 "Игорь Лабутин" Если у вас билета еще нет, то в шоуноутах вы найдете промокод на скидку, который позволит вам посмотреть, во-первых, прошедшие записи, во-вторых, попасть на онлайн просмотр офлайн дня 20 ноября, либо даже купить офлайн билет и встретиться, в том числе, с нами в Москве 20 ноября на офлайн-дне конференции. +57.64 60.80 "Игорь Лабутин" Приходите, будет, я думаю, интересно. +60.80 63.12 "Анатолий Кулаков" Да, всех будем ждать на офлайне, заходите. +63.12 85.56 "Анатолий Кулаков" Еще хотелось бы сказать, что наверняка вы этот выпуск уже будете слушать, когда .NET Conf идет или уже прошла, мы же записываемся еще до нее, поэтому сейчас в этом выпуске пока ничего про .NET Conf не будет, а вот следующий выпуск, я думаю, мы полноценно посвятим всем новинкам, которые анонсируют, которые выйдут, которые напишут статьи, бенчмарки, ну и прочее-прочее, что там посмотрим. +85.56 97.96 "Анатолий Кулаков" А сейчас пока насладимся буквально несколькими днями тишины перед большими анонсами и посмотрим, что у нас еще интересно было, вышло, заанонсилось в мире .NET за то время, пока мы с вами не виделись. +97.96 101.96 "Игорь Лабутин" Ну, сильно много не заанонсилось, как мне кажется. +101.96 104.36 "Игорь Лабутин" Мы начнем с Entity Framework. +104.36 116.80 "Игорь Лабутин" Не то, чтобы это новый анонс, это на самом деле штука, про которую мы уже рассказывали, это performance improvement в Entity Framework 7, которые вышли еще в 6 превью, это пару или тройку превью назад. +116.80 140.76 "Игорь Лабутин" Однако же эта статья интересна тем, на самом деле это даже несколько статей, они интересны тем, что это не просто Microsoft показала, как они сделали круто, это реальные ребята посмотрели в достаточно таких, ну наполовину, скажем так, реально практических кейсах, насколько же получается выигрыш от этих всех изменений в EF. +140.76 154.80 "Игорь Лабутин" Причем надо понимать, что это все, поскольку превью, то прям совсем production, конечно на EF Core не переводили, но попытались эмулировать, что будет происходить в реальной жизни, когда вы реально развернете приложение. +154.80 166.92 "Игорь Лабутин" Напомню, что было сделано, собственно, с EF Core, они убрали возможность, невозможность, они убрали часть вызовов для явной работы с транзакциями. +166.92 181.28 "Игорь Лабутин" То есть, если вы делаете insert одной всего лишь записи, то делать два дополнительных round trip в базу, чтобы сказать begin transaction и end transaction, ну или commit transaction, как бы вроде странно, база данных и так сама автоматически сделает транзакцию на этот единственный insert. +181.28 194.72 "Игорь Лабутин" Поэтому эта штука была убрана, и мы на этом сэкономили два round trip, два round trip, ну вроде как, как бы немного с одной стороны, с другой стороны это две трети от всей операции записи, и казалось бы, должно стать лучше. +194.72 224.40 "Игорь Лабутин" Они действительно это проверили, и проверили они следующим способом, они взяли три кейса, это база данных на том же компе, где entity framework, то есть по сути на localhost, дальше берем ажурную регионы и говорим, что база данных будет лежать в том же регионе, что и код, но на разных машинках, и берем код в одном ажурном регионе, а базу данных в другом ажурном регионе, ну вдруг у вас такая георепликация, и почему-то ваше приложение решило пойти в соседний регион писать базу данных. +224.40 234.48 "Игорь Лабутин" В данном случае был выбран регион для базы, по-моему, Америка, US West, а для кода, соответственно, Europe West. +234.48 238.40 "Игорь Лабутин" Между ними, согласно ажурным данным, latency 72 миллисекунды. +238.40 246.52 "Игорь Лабутин" И чиселки получились следующие, для localhost, EFCore 7 по сравнению с EFCore 6, получило примерно 6% улучшения. +246.52 257.36 "Игорь Лабутин" Ну там скорее всего, конечно, сыграли роль и там оптимизация runtime и все остальное, но в целом какие-то оптимизации, ну на roundtrip, в том числе для localhost тоже время тратится. +257.36 272.08 "Игорь Лабутин" Если база данных живет в том же регионе, что и код, но на разных машинках, то мы получили 13% экономии времени, что уже, ну не так, чтобы сильно много, но достаточно много, учитывая, что это всего лишь один единственный инсерт. +272.08 284.64 "Игорь Лабутин" А в случае, если у вас база живет вообще в соседнем регионе, по какой-то причине, относительно кода, то вы получили 65% экономии, то есть по сути приложение в целом стало в 2 раза быстрее в этом конкретном аспекте. +284.64 285.72 "Игорь Лабутин" Это уже прям немало. +285.72 300.08 "Игорь Лабутин" Вторая штука, которая была изменена, это то, как обрабатывается multiple insert, то есть если вы сделали много раз insert, insert, insert, insert, а потом save changes, то EFCore делает следующую штуку. +300.08 305.76 "Игорь Лабутин" Во-первых, он батчит, то есть он объединяет все эти инсерты в батчи по несколько штук. +305.76 308.04 "Игорь Лабутин" Помнишь ли ты, какой размер батчи по дефолту? +308.04 310.04 "Игорь Лабутин" Нет, как-то не приводилось. +310.04 312.56 "Игорь Лабутин" Ну, это число нужно знать, это 42. +312.56 314.92 "Игорь Лабутин" А, 42, да, мы же обсуждали эту штуку. +314.92 325.56 "Игорь Лабутин" Да-да-да, он по дефолту 42, это действительно не поменялось, то есть это не было какой-то шуткой, в релизе, судя по всему, тоже будет 42, и оно так и есть, в тестах, по крайней мере, пока это подтверждается. +325.56 342.28 "Игорь Лабутин" EFCore, соответственно, объединяет инсерты в несколько, ну в батчи по 42 штуки, если их больше, чем 42, после чего использует, если это SQL Server, например, то SQL Statement под названием Merge, который позволяет как раз таки сделать инсерт. +342.28 352.20 "Игорь Лабутин" Раньше он это делал с временной табличкой, то есть он результат забирал во временную табличку, и потом оттуда понимал, какие ID-шники были сгенерены. +352.20 366.20 "Игорь Лабутин" Теперь он использует более простую версию, он просто использует output statement для этого, но, к сожалению, у этого есть и достоинства, и недостатки, точнее, к счастью, у этого есть достоинства, к сожалению, у этого есть недостатки. +366.20 367.84 "Игорь Лабутин" Достоинство в том, что это работает быстрее. +367.84 372.20 "Игорь Лабутин" Недостаток в том, что если на вашей табличке есть триггеры, то, например, SQL Server такой не поддерживает. +372.20 376.08 "Игорь Лабутин" Нельзя делать merge с output, если на табличке есть триггеры. +376.08 390.32 "Игорь Лабутин" Поэтому если это так, то вам нужно в db-контексте явно указать, что на этой таблице есть триггеры, и тогда EFCore будет работать по-старому, но вы не получите всех бенефитов от того, чтобы все стало быстрее. +390.32 404.04 "Игорь Лабутин" И в этом случае, если все нормально, если триггеров нет, и если у вас количество инсертов меньше, чем размер батча, либо равно, то, опять же, не будет никаких дополнительных begin-end на транзакции. +404.04 409.04 "Игорь Лабутин" Ну, если батчей больше одного, то там begin-end явный будет в любом случае явным round-trip, тут без этого никак. +409.04 414.36 "Игорь Лабутин" В плане чиселок получается примерно следующее. +414.36 431.52 "Игорь Лабутин" На тех же, назовем это условиях теста, то есть localhost, тот же регион и другой регион, относительно кода и базы разной регионы, получилось на вставке 10 рекордов улучшение соответственно на 23%, на 40% и опять на 65%. +431.52 436.76 "Игорь Лабутин" То есть, короче, здесь прям слеттанс стало лучше на десятки рекордов сразу. +436.76 443.24 "Игорь Лабутин" Хотя непонятно, почему на десятки рекордов, прямо на localhost такая, четверть сэкономили, но, видимо, еще какие-то рантаймовые штуты помогли. +443.24 460.56 "Игорь Лабутин" И последнее, что в этой статье интересно, и связано с ней, это то же, это фича, которую я на самом деле особо не знал, ну, точнее, я знал, как она работает для гуидов, но не знал, что есть другой способ. +460.56 470.48 "Игорь Лабутин" Смотрите, если мы вставляем, допустим, у нас есть пара объектов, точнее, пара классов связанных, это, допустим, традиционный пост и коммент к нему. +470.48 492.16 "Игорь Лабутин" Когда мы добавляем пост и, допустим, сразу, не знаю, к нему хотим сохранить какой-нибудь коммент, то для того, чтобы Entity Framework такое сохранить, ему нужно сначала сохранить объект родитель, получить его id-шник обратно и потом сохранить dto, чтобы указать, собственно, foreign ключом, кто был родителем. +492.16 508.16 "Игорь Лабутин" Если вы используете в качестве id ваших объектов родителя гуиды, то в этом случае такого делать не нужно или этого можно избежать, потому что гуиды можно сгенерить на клиенте и сразу одним инсертом запихнуть и родителя и dto в базу одним roundtrip. +508.16 512.44 "Игорь Лабутин" Инсертом, конечно, не получится, это будет два инсерта, но это можно сделать одним roundtrip. +512.44 524.60 "Игорь Лабутин" Но мы не все используем гуиды, не везде это нормально, не везде этим хочется заниматься, и поэтому в Entity Framework есть такая фича под названием high-low. +524.60 526.68 "Игорь Лабутин" Вот четыре буквы. +526.68 529.36 "Игорь Лабутин" Она работает следующим образом. +529.36 537.36 "Игорь Лабутин" Можно завести специальную sequence в базе данных и Entity Framework сказать, что для этой таблички, для его ключей использую этот sequence. +537.36 555.64 "Игорь Лабутин" И тогда Entity Framework, когда вы ему говорите save changes, он смотрит, сколько нужно будет заинсертить записей, ну например, если мы добавляем сразу 10 блок-постов, то он сходит в базу данных и скажет, отдай мне, дорогой дизайнер, пожалуйста, n ID-шников. +555.64 557.60 "Игорь Лабутин" Следующий, так сказать, range. +557.60 566.00 "Игорь Лабутин" По дефолту n = 10, но разработчики Entity Framework говорят, ну, короче, дефолт 10, но это не очень правильный дефолт, ставьте сразу больше, там, сотню, ставьте, будет норм. +566.00 578.76 "Игорь Лабутин" Вот, и по сути, получится, что Entity Framework сразу получает себе локально сотню ID-шников, в базе sequence двигается, и любой следующий клиент, который тоже захочет инсертию, он получит другую сотню. +579.76 587.40 "Игорь Лабутин" А ваша, так сказать, копия в памяти будет использовать эту сотню, пока она не закончится. +587.40 590.12 "Игорь Лабутин" Как только закончится, он получит следующую сотню. +590.12 619.84 "Игорь Лабутин" Таким образом, получается, что если вы делаете много инсертов, и вам не важен порядок, потому что, если у вас, допустим, несколько, не знаю, нод ходят в одну и ту же базу данных, да, и все они инсертят, то понятно, что каждый получит свой range, а использовать они будут их в каком-то случайном порядке, куда там будут запросы приходить, и поэтому записи, которые будут вставляться, казалось бы, по порядку, будут получать ID-шники, ну, на самом деле, довольно рандомно. +619.84 633.96 "Игорь Лабутин" Плюс, если вы, допустим, у вас есть какая-то там нода или под в кубернет, который взял, получил этот range 600 элементов, и тут же помер, ну, эти 100 элементов потерялись, то есть у вас еще и будут дырки в ваших ID-шниках. +633.96 651.88 "Игорь Лабутин" Если вас это все устраивает, а по мнению как бы разработчиков EF Core в большинстве приложений это норм, то, может быть, это вполне себе хороший вариант, как сделать так, чтобы у вас были ID-шники числовые, и при этом не было такой просадки по перформансу, если вы часто вставляете детей с родителями вместе. +651.88 663.16 "Игорь Лабутин" Поэтому, если это ваш кейс, по бенчмаркете такой способ, возможно, это действительно хороший способ сэкономить на вставке в современном Entity Framework 7. +663.16 674.72 "Анатолий Кулаков" Тут хотелось бы еще добавить, что Hilo - это, в принципе, общеизвестный алгоритм, он применяется во многих базах данных и как раз таки служит для того, чтобы нивелировать все проблемы с распределенными идентификаторами. +674.72 686.76 "Анатолий Кулаков" Например, вы можете с помощью этого прекрасного подхода добиться того, что у вас есть несколько распределенных нод, вам нужно вставлять какие-то записи, и вы при этом не хотите почему-то использовать гуиды. +686.76 689.92 "Анатолий Кулаков" Ну, такая проблема всегда решается по дефолту с помощью гуидами. +689.92 696.08 "Анатолий Кулаков" Если вам кто-то скажет, что это невозможно, это неправда, потому что очень распространен метод, вот такой подход как Hilo. +696.08 709.28 "Анатолий Кулаков" Он вам позволяет оставаться в интах, то есть у вас по-прежнему будут красивые более-менее идентификаторы, они будут идти более-менее по порядку, но опять же без гарантированного какого-то отсутствия дырок или без гарантированного порядка, как сказал Игорь. +709.28 713.88 "Анатолий Кулаков" В общем, но при этом это намного короче, намного приятнее будет смотреться, чем гуиды. +713.88 721.12 "Анатолий Кулаков" И этот алгоритм часто применяется, часто используется, опять же, главное смотреть и понимать его минусы и его плюсы. +721.12 727.04 "Анатолий Кулаков" И в большинстве ситуаций он вам вполне может заменить гуиды, если они вам почему-то не нравятся. +727.04 740.04 "Игорь Лабутин" Да, но нужно выбирать размер вот этого ренжа, который каждый из ваших копий приложения получает, ну и смотреть, насколько у вас получаются при этом большие дырки, насколько все это хорошо работает. +740.04 743.96 "Игорь Лабутин" Я просто на самом деле что-то не знал, что EF Core его нативно поддерживает. +743.96 745.68 "Игорь Лабутин" Но, как выясняется, совпадное поддерживает. +745.68 756.56 "Игорь Лабутин" Причем, если вы используете Code First, то вам даже не нужно генерить ручную секвенцию, он по-моему сам генерирует его в нужном варианте. +756.56 766.84 "Игорь Лабутин" А вот если у вас Database First, то секвенцию вам нужно объявить в базе самому, а Entity Framework просто сказать вот для Hilo вот этой таблички используй вот тот секвенс под таким названием. +766.84 767.84 "Игорь Лабутин" И все будет работать. +767.84 775.76 "Игорь Лабутин" Давай пойдем дальше, кроме Entity Framework у нас сегодня день Performance Improvement. +775.76 782.80 "Анатолий Кулаков" Ну, конечно, перед релизом всегда так, сначала там накидают, что только задали высший сахар, а потом начинают оптимизировать и перформанс улучшать. +782.80 791.36 "Анатолий Кулаков" Ну, да, у нас еще есть на подходе статейка про ASP.NET Core, что же там случилось с перформансом, давайте посмотрим. +791.36 802.60 "Анатолий Кулаков" Здесь, наверное, в этой статье очень прикольно на нее взглянуть с точки зрения вообще подхода, каким образом можно чинить самые распространенные проблемы с перформансом. +802.60 808.12 "Анатолий Кулаков" Потому что я надеюсь, что вы знаете, что прежде чем чинить перформанс, вам нужно попрофайлить и найти точки, которые вас именно тормозят. +808.12 812.56 "Анатолий Кулаков" Не так, как вам хочется и кажется, а реально, чтобы инструменты это вам подтвердили. +812.56 816.88 "Анатолий Кулаков" И после того, как вы их нашли, у вас, соответственно, встает вопрос, а что же дальше с ним делать? +816.88 822.68 "Анатолий Кулаков" В принципе, таких подходов, которые позволяют вам более-менее стандартные участки улучшать, их не так уж много. +822.68 828.92 "Анатолий Кулаков" Я думаю, что если была бы какая-нибудь хорошенькая статейка или книжечка, то набралось бы несколько десятков и все. +828.92 833.68 "Анатолий Кулаков" Если вы их выучите, вам их обычно хватит на всю жизнь, чтобы улучшать ваш перформанс. +833.68 834.68 "Анатолий Кулаков" Да, ой-ой-ой. +834.68 838.92 "Анатолий Кулаков" И здесь как раз-таки ярко выражены несколько таких подходов. +838.92 839.92 "Анатолий Кулаков" Давайте посмотрим. +839.92 856.80 "Анатолий Кулаков" Прежде всего, авторы нам хвалятся, что они смогли улучшить показатели на их специальной 80-ядерной машине на 514% для обычной дистиллизации текста и для 311% для JSON обработки запросов. +856.80 859.20 "Анатолий Кулаков" В общем, как это они сделали? +859.20 863.72 "Анатолий Кулаков" У них был очередь на входящие запросы для кестрила. +863.72 868.88 "Анатолий Кулаков" Эта очередь была одна и, соответственно, она очень сильно локалась на контеншоне. +868.88 880.60 "Анатолий Кулаков" Как только мы пытались распараллелить все запросы, только обработать их параллельно, все эти запросы лезли в одну очередь и оттуда доставали работу. +880.60 887.28 "Анатолий Кулаков" Чтобы работа досталась только одному какому-то персонажу, только одному воркеру, там, естественно, был какой-то лок. +887.28 890.48 "Анатолий Кулаков" В общем, это все было совсем нехорошо. +890.48 898.28 "Анатолий Кулаков" Поэтому прежде всего эту очередь разбили на несколько очередей и теперь каждый воркер ходит к своей очереди. +898.28 903.72 "Анатолий Кулаков" Это позволило избежать контеншона, то есть мы избавились от локов. +903.72 922.92 "Анатолий Кулаков" И теперь у нас каждый воркер может забирать свою работу, но при этом немножко увеличилось время CPU, потому что бывают ситуации, когда воркер всю свою работу сделал и сидит без работы, а в это время другой воркер захлебывается от работы, не успевает разгрести свою очередь и в это время происходит так называемое воровство. +922.92 932.88 "Анатолий Кулаков" То есть тот воркер, который халтурничает, он ворует работу у занятого воркера и вот здесь уже немножко нужно будет потратить CPU для того, чтобы это сделать. +932.88 940.92 "Анатолий Кулаков" Но в принципе такой подход, он обычно дает больше плюсов, чем минусов, поэтому команда остановилась именно на нем. +940.92 948.64 "Анатолий Кулаков" Также добавилась на Windows поддержка Windows I/O Completions в портабл ThreadPool. +948.64 954.52 "Анатолий Кулаков" Давно уже переписали ThreadPool на портабл, но почему-то там Windows I/O Completions до сих пор не подтянули. +954.52 958.52 "Анатолий Кулаков" Теперь это исправлено и это дало прирост на 11%. +958.52 970.56 "Анатолий Кулаков" И также позволило убрать другую техдолг, который делал DoubleDispatch в Windows I/O, что увеличило еще на 18% производительность данных тестов. +970.56 975.32 "Анатолий Кулаков" Еще одна интересная оптимизация - это исключения. +975.32 978.76 "Анатолий Кулаков" Как вы наверное слышали, бросать исключения - это очень дорого. +978.76 993.80 "Анатолий Кулаков" Конечно, если вы бросаете одно или два бизнес-исключения, может быть это не так страшно, но если мы говорим про уровень сокета и когда у нас там тысячи коннекций и там сокеты открываются-закрываются, то там исключения вполне могут дать какую-то просадку по производительности. +993.80 1011.20 "Анатолий Кулаков" И вот авторы нашли одно место, которое бросало исключение на коннекшенах и это исключение в принципе было не обязательно, то есть вполне можно было бы обработать эту ситуацию без исключения, пробросать ее в более верхний слой обработки всех этих ошибок. +1011.20 1016.56 "Анатолий Кулаков" В общем, просто-напросто убрали throw одного исключения. +1016.56 1029.68 "Анатолий Кулаков" И это позволило уменьшить потребление CPU, только задумайтесь там с 50% до 40% на рынок-системах и всего лишь навсего выбрасывание одного исключения тогда, когда можно было бы этого не делать. +1029.68 1033.32 "Анатолий Кулаков" В общем, бросать исключение это тоже зло, поэтому задумывайтесь прежде чем это делаете. +1033.32 1050.12 "Анатолий Кулаков" И еще одна оптимизация, это новый классик, ну относительно новый, называется он PoolingAsyncValueTaskMethodBuilder, то есть это специальный класс, который применяется в довольно узких кейсах, когда вам нужно запулить value-таски. +1050.12 1056.96 "Анатолий Кулаков" Если вы помните, что value-таски они сами были изобретены для того, чтобы в некоторых ситуациях можно было заменить таски. +1056.96 1062.48 "Анатолий Кулаков" В общем, а теперь даже сами value-таски, сами структуры оказались слишком дорогими и их теперь можно пулить. +1062.48 1076.56 "Анатолий Кулаков" Скорее всего вы никогда не встретите в своем коде надобности пулить value-таски, но если вы автор кестрила или там какого-нибудь сверхнагруженного протокола типа gRPC, вот там это вам может понадобиться. +1076.56 1091.08 "Анатолий Кулаков" Если по цифрам, то запуская 1000 рядов swap-сокетов, раньше аллокейтилось 3000 стейт-машин, то есть стейт-машина, которая получается в результате вот этих await-тасков, то есть await-стейт-машина. +1091.08 1095.60 "Анатолий Кулаков" Их было 3000 и они аллокейтились. +1095.60 1097.32 "Анатолий Кулаков" Это было страшно. +1097.32 1104.20 "Анатолий Кулаков" То есть ВЦ там тоже старался и это давало какие-то проблемы с перформансом. +1104.20 1111.84 "Анатолий Кулаков" После того, как поставили пул в нужное место, а именно в дотнет-седьмом, таких аллокаций вместо 3000 стало 11. +1111.84 1115.00 "Анатолий Кулаков" То есть это практически уже незаметно. +1115.00 1121.72 "Анатолий Кулаков" Вот так пулинг нам помогает в каких-то местах, которым обращаются очень много раз. +1121.72 1126.16 "Анатолий Кулаков" Каждое обращение, каждый аллокейт стейт-машины, он мизерный, он элементарный. +1126.16 1136.52 "Анатолий Кулаков" Но если их набирается много-много, на 1000 клиентов, на 1000 коннекций, это уже становится существенно, это уже видно на профайлерах и это значит можно чинить. +1136.52 1138.92 "Анатолий Кулаков" Следующие новинки по HTTP/2. +1138.92 1148.08 "Анатолий Кулаков" В HTTP/2 у нас тоже была проблема с тем, что есть лог контеншен, то есть был лог контеншен. +1148.08 1153.76 "Анатолий Кулаков" Там некоторые клиенты дрались за определенную очередь для того, чтобы разбирать себе задачи. +1153.76 1156.48 "Анатолий Кулаков" И по-моему даже писать. +1156.48 1160.56 "Анатолий Кулаков" Да, некоторые клиенты дрались для того, чтобы писать ответы уже после того, как все обработали. +1160.56 1162.80 "Анатолий Кулаков" И здесь авторы пошли следующим путем. +1162.80 1165.00 "Анатолий Кулаков" Они все переделали на ченнел. +1165.00 1177.16 "Анатолий Кулаков" То есть в ченнел пишется определенные задачи, которые нужно сделать, а один-единственный консюмер обрабатывает эту очередь задач из ченнелов и делает всю основную работу для записи. +1177.16 1187.84 "Анатолий Кулаков" То есть реально пишет один консюмер, то есть это значит, что мы в одном потоке загружаем весь сокет и никакой драки, никакого контеншена, ничего плохого не происходит. +1187.84 1199.64 "Анатолий Кулаков" И соответственно это очень сильно убрало лог контеншен, подняло рпс с 1.2 млн до 6.8 млн рпс в данном конкретном бичмарке. +1199.64 1205.88 "Анатолий Кулаков" Но самое интересное, что данная оптимизация подняла расход CPU на 100%. +1205.88 1212.08 "Анатолий Кулаков" Раньше там были какие-то жалкие проценты, а сейчас CPU вырабатывал весь на 100% и это хорошо. +1212.08 1220.44 "Анатолий Кулаков" Потому что теперь мы видим, что мы не упираемся в контеншен, то есть у нас работает железо на полную мощь, значит выдает максимум, что оно только может. +1220.44 1230.36 "Анатолий Кулаков" Когда у нас был контеншен, у нас в профайле была ситуация, когда CPU еле нагружен, сеть еле нагружена, вроде как бы ресурсов полно, но ничего не происходит. +1230.36 1234.96 "Анатолий Кулаков" Как раз таки все потому, что большинство воркеров ждали своей очереди на логах. +1234.96 1256.56 "Анатолий Кулаков" В общем логи это страшная сила, поэтому если вы можете избежать их, обязательно избегайте, а если не можете избежать, то задумайтесь об одном из методов устранения логов, это вот в частности оставление одного консюмера, если это возможно, а все остальное загонять в очередь, или вот как мы обсуждали чуть выше, несколько воркеров, которые таскают задачи каждой своей очереди. +1256.56 1291.56 "Анатолий Кулаков" Далее еще увеличили окно, так называемый upload window у кистерла в HTTP/2, что позволило загружать хорошо и быстренько большие файлы, например 100 мегабайтный файл, раньше грузился за 27 секунд, а сейчас он начал грузиться за 4 секунды, то есть вот такие большие огромные изменения, но опять же все нужно понимать, что игры с окном это тоже какой-то компромисс, в некоторых ситуациях он может дать какой-то плохой результат, в некоторых хороший, в общем здесь все на совести команды разработчиков, мы им поверим. +1291.56 1306.92 "Анатолий Кулаков" В HTTP/3, HTTP/3 наконец-то вышел из экспериментальной стадии, теперь это вроде считается больше не эксперимент, но его по-прежнему не включили в .NET 7 по умолчанию, поэтому если вы захотите его юзать, вам придется его явно включить. +1306.92 1424.56 "Анатолий Кулаков" Еще улучшили декодер и улучшили его в 900 раз, вот такие страшные цифры, вообще не понимаешь как оно раньше работало, ну не зря наверное это все в экспериментальном было, потому что там ничего не улучшали, 900 раз, тоже интересная техника, как добились 900 раз перформанса, все очень просто, заставили сжимать компрессор, заставили сжимать намного-намного эффективнее, чтобы вы понимали эффективность, раньше хидра сжимались до 109 байт, а теперь они сжимаются до 7 байт, это вообще все похоже на какой-то анекдот про архиватор, для которого осталось придумать только разархиватор, но на самом деле существует тоже такой интересный хак, когда у вас есть какой-то понятный предсказуемый набор список значений, как в нашем случае HTTP хедеры, ну наверное каждый из вас сталкивался, это какой-нибудь content type, content size, что там у нас еще есть, какой-нибудь агент, все сервер в его столице, какой-нибудь агент, еще что-то, ну вот стандартные HTTP хедера, они все объявлены спецификацией и каждый раз гонять полные их текстовые названия в ASCII строках, это довольно бессмысленно, даже если мы их сожмем, поэтому команда Durnet, команда ASP приняла следующее интересное решение, она просто-напросто присвоила каждому хедеру уникальный индекс и далее теперь пересылает не строчки с названиями хедеров, а индекс, вот там допустим индексу 42 соответствует хедер content type, сервер об этом знает, клиент об этом знает и соответственно если они оба договорились о правильных индексах, им не обязательно подправлять строки, они отправили там один байтик и уже всем все понятно какой хедер имеется в виду, вот такая немудреная оптимизация и сократила размер и увеличила перформанс и вообще позволила показать красивые графики нашим читателям. +1424.56 1434.24 "Анатолий Кулаков" В Signal Area уменьшили аллокацию с помощью кэширования, аллокацию строк тоже популярная способ оптимизации, это кэширование, главное не забывайте когда его чистить. +1434.24 1466.52 "Анатолий Кулаков" И в аутентификации также закэшировали policy_authorize_result, интересная оптимизация была сделана в http_results, http_results это такие специальные классики, которые возвращаются серверам в зависимости от того, что там произошло, самый частый случай это 200 окей, наверное все вам известны, когда возвращаете какой-то результат серверу, сообщаете ему, что все хорошо, в этот момент создается http_result, который умеет рендерить 200-ый респонс и он возвращается клиенту. +1466.52 1485.36 "Анатолий Кулаков" Зоркий глаз заметил, что очень часто, особенно для каких-то общеизвестных статус кодов, вот эти http_results они по сути иммьютабельные, то есть в них практически никогда нет какого-нибудь стейта, и поэтому решили http_results просто закэшировать и переиспользовать. +1485.36 1503.72 "Анатолий Кулаков" Но не просто закэшировали, а взяли и сгенерировали уже http_results по всем известным http кодам, потому что это очень частая ситуация, обычно наши клиенты не выдумывают каких-то хитроумных, наши серверы обычно не выдумывают каких-то хитроумных кодов, а возвращают то, что уже все знают и все давно есть. +1503.72 1511.36 "Анатолий Кулаков" В общем вот эти всем известные коды взяли и закэшировали, то есть закэшировали, да, а для того, чтобы закэшировать их для начала сгенерили. +1511.36 1515.04 "Анатолий Кулаков" И интересное в этой схеме в том, что сгенерили их с помощью t4-темплейтов. +1515.04 1533.68 "Анатолий Кулаков" Вот мы как раз недавно обсуждали жив t4-темплейт или мертв, или его заменил рослин генераторой или что-то в этом духе, оказывается нет, жив, живее всех живых, и вот в последних релизах Dota 7 команда ISP активно использует t4-темплейты, отличная технология, хорошо, что живет. +1533.68 1551.72 "Анатолий Кулаков" Еще один интересный момент в том, что для t4-темплейтинга они использовали не микрософтовскую реализацию, которая имеет свои минусы, а взяли монотекст-темплейтинг, то есть реализацию t4, ту, которая была сделана под моно, и вот ISP теперь юзает ее. +1551.72 1559.24 "Анатолий Кулаков" Это кроссплатформенная реализация, соответственно, и дает все те плюсы t4, которые вы, скорее всего, сталкивались когда-нибудь под виндой. +1559.24 1578.72 "Анатолий Кулаков" В общем, тоже прекрасная оптимизация, если вы можете что-нибудь сгенерить в дизайн тайме, то есть еще до того времени, когда вы начали компилировать, это всегда прекрасная идея, и самый лучший инструмент, который вам помогает это сделать, это t4, без него вообще никуда. +1578.72 1594.92 "Анатолий Кулаков" У нас, кстати, недавно в сообществе SPB.net был докладик по t4, если кто-то вдруг не сталкивался, обязательно на доклад посмотрите, я думаю, многим может помочь, там как раз доклад очень практичный, упоминается очень много кейсов, в которых в том числе есть performance оптимизации. +1594.92 1596.60 "Анатолий Кулаков" Так, погнали дальше. +1596.60 1610.24 "Анатолий Кулаков" В фильтрах наконец-то додумались светлой умой заменить new object, то есть создание нового пустого массива на специальное редональное свойство, которое называется array.empty от object. +1610.24 1616.96 "Анатолий Кулаков" Если вдруг в ваших проектах еще осталась аллокация нового пустого массива, то обязательно меняйте на array.empty. +1616.96 1620.32 "Анатолий Кулаков" По-моему, сейчас уже все анализаторы это советуют, но вдруг вы почему-то упустили. +1620.32 1629.32 "Анатолий Кулаков" И последняя оптимизация, о которой хотелось бы рассказать, это когда делают нескончаемый набор аргументов. +1629.32 1635.80 "Анатолий Кулаков" Редко такая штука встречается, но иногда бывает, когда вам нужно передать количество аргументов, которые вы заранее не знаете. +1635.80 1638.44 "Анатолий Кулаков" Вы обычно пишите по RAM и задаете это на массив объектов. +1638.44 1643.84 "Анатолий Кулаков" Это стандартный подход, например, в логгерах он используется практически всегда. +1643.84 1647.40 "Анатолий Кулаков" То есть, когда вы пишете log, вы не знаете, сколько параметров передастся. +1647.40 1650.84 "Анатолий Кулаков" Там будет message template и плюс еще куча всяких параметров. +1650.84 1654.64 "Анатолий Кулаков" В этом случае пишут обычно по RAM и массиву объектов. +1654.64 1656.52 "Анатолий Кулаков" И все, и корренно все в огнем. +1656.52 1658.64 "Анатолий Кулаков" Но хороший логгер, естественно, так не делает. +1658.64 1662.36 "Анатолий Кулаков" И хорошие микрософтовские пайплайны в ASP тоже так не делают. +1662.36 1663.36 "Анатолий Кулаков" Как делать правильно? +1663.36 1669.80 "Анатолий Кулаков" Правильно все-таки взять, напрячься и скопипастить, сгенерить, добавить 10 отдельных методов. +1669.80 1675.52 "Анатолий Кулаков" У первого метода будет один аргумент, у второго метода второй аргумент, у третьего три аргумента и так далее. +1675.52 1680.08 "Анатолий Кулаков" То есть, поддержать самое адекватное, то есть, самое часто распространенное количество аргументов. +1680.08 1683.56 "Анатолий Кулаков" И последнее можно сделать там уже с массивом объектов. +1683.56 1685.08 "Анатолий Кулаков" Что это вам даст? +1685.08 1688.92 "Анатолий Кулаков" Прежде всего, это позволит вам не аллокировать массив объектов. +1688.92 1695.72 "Анатолий Кулаков" Потому что аллокация в частых случаях, ну, например, если мы возьмем логгер, логгер на самом деле пользуется очень часто. +1695.72 1702.08 "Анатолий Кулаков" И там аллокация массива объектов – это уже какой-то performance penalty. +1702.08 1707.56 "Анатолий Кулаков" То есть, уже могут с этим вылезти проблемы, и вы их на профилере точно увидите при интенсивном использовании. +1707.56 1708.56 "Анатолий Кулаков" Вот. +1708.56 1714.08 "Анатолий Кулаков" И вторая проблема – это в том, что обычно такой массив параметров, он задается как массив объектов. +1714.08 1716.48 "Анатолий Кулаков" Потому что, по сути, вы не знаете, что туда положить. +1716.48 1718.24 "Анатолий Кулаков" И это провоцирует боксинг. +1718.24 1723.44 "Анатолий Кулаков" Боксинг – это еще одна такая невидимая штука, которая хорошо сажает performance. +1723.44 1730.68 "Анатолий Кулаков" Если же вы делаете отдельные параметры, то вы можете использовать в этот момент дженерики. +1730.68 1739.72 "Анатолий Кулаков" Никакого боксинга не будет, вы просто пишете t1, t2, t3, t4, и компилятор сам их раскладывает в правильные нужные вам типы, и эти типы подставляет во время компиляции. +1739.72 1743.00 "Анатолий Кулаков" То есть, никакого боксинга не будет, никакого создания массива не будет. +1743.00 1751.56 "Анатолий Кулаков" И в тех моментах, когда данные методы используются очень часто интенсивно, это очень сильно помогает вам улучшить performance. +1751.56 1756.24 "Анатолий Кулаков" Вот такие основные новинки по performance в WSP.net Core. +1756.24 1760.96 "Анатолий Кулаков" Думаю, что мы получим еще одни интересные тесты сразу после релиза. +1760.96 1769.96 "Анатолий Кулаков" Пока ребята обновят какие-нибудь общие употребимые теком power, и посмотрим, что там у нас изменится с местами. +1769.96 1775.24 "Анатолий Кулаков" Ну что ж, у нас осталась последняя статья по перформансу, давай перейдем уже к ней. +1775.24 1783.12 "Игорь Лабутин" Да, с перформансом у нас в этот раз все хорошо, и в этот раз мы посмотрим на перформанс MAUI, новую UI. +1783.12 1795.40 "Игорь Лабутин" Ну, не сказать, чтоб фреймворка, но по крайней мере, не сказать, чтоб нового, как наследника Xamarin.Forms, но тем не менее в нем тоже есть некоторые performance improvement по сравнению с .NET 6. +1795.40 1813.20 "Игорь Лабутин" MAUI в основном, ну он вообще предполагается то, что он должен быть полностью кроссплатформенным, но основной фокус сейчас, конечно же, на Android и на iOS, потому что там особые требования и к времени старта, и к размеру приложения, и там нужно более тщательно к этому всему подходить. +1813.20 1822.40 "Игорь Лабутин" Поэтому в этом релизе, в 7.NET, был фокус на Android и на iOS, и он был немножко разный. +1822.40 1834.88 "Игорь Лабутин" Согласно статье, для Android фокус был на производительности стартапа, то есть насколько быстро приложение запускается, потому что размер приложения был уже неплох, как у них написано. +1834.88 1835.88 "Игорь Лабутин" Was in good place. +1835.88 1845.60 "Игорь Лабутин" А для iOS наоборот, они фокусировались на размере приложения, потому что стартап тайм был in good shape, как опять же у них сказано. +1845.60 1851.36 "Игорь Лабутин" На одной платформе хорошо с размером, на другой платформе хорошо с временем старта. +1851.36 1858.64 "Игорь Лабутин" Но при этом у них был еще и кастомер фидбэк после шестерки, что в целом UI performance, то есть layout, scrolling и прочее надо улучшать. +1858.64 1861.60 "Игорь Лабутин" Ну в общем, примерно над этим и работали. +1861.60 1863.76 "Игорь Лабутин" И надо сказать улучшили. +1863.76 1877.96 "Игорь Лабутин" С одной стороны улучшили хорошо, с другой стороны чиселки ну прям такие как бы… когда я начал читать статью, они какие-то такие, ну не сказать смешные, но не очень убедительные что ли. +1877.96 1897.96 "Игорь Лабутин" То есть у них для примера, и мы может быть помните, обсуждали давным-давно, что у них появилось новое приложение, когда они начали разрабатывать Мауи, появилось новое, так скажем, модельное приложение, называется dotnet podcast app, то есть это некоторый каталог подкастов, который компилируется как Мауи приложение, и он кроссплатформенный. +1897.96 1914.24 "Игорь Лабутин" Соответственно для стартап тайма на андроиде это тестировалось на пятом пикселе, они улучшили по сравнению с шестеркой, было 814 мс, стало 759 мс, то есть улучшение где-то на 54 мс из 800. +1914.24 1922.60 "Игорь Лабутин" Ну как бы не знаю, лучше, но не сильно впечатляюще, было бы там 800-400, вот было бы да. +1922.60 1929.00 "Игорь Лабутин" А тут как-то улучшили, ну процентов на 7 получается, если так оценить. +1929.00 1940.12 "Игорь Лабутин" Немного, с размером на iOS примерно та же история, этот самый подкаст приложения занимал 25 мегабайт в варианте dotnet 6 и стал занимать 23.9 в варианте dotnet 7. +1940.12 1942.96 "Игорь Лабутин" Ну сэкономили 4% примерно. +1942.96 1948.64 "Игорь Лабутин" Не знаю, насколько это круто и хорошо, но наработали над этим много. +1948.64 1957.36 "Игорь Лабутин" И на самом деле вся статья это про то как раз-таки чем, какие подходы они использовали для того, чтобы этого всего добиться. +1957.36 1976.80 "Игорь Лабутин" И действительно можно посмотреть, что в некоторых местах startup time или с размером они прям выигрывали какие-то сотые доли секунды, не знаю там 16 мс сократили до 2 мс кусочки, то есть там они буквально профайлили вот такие вот места, то есть типа ооо вот здесь код занимает 16 мс, давайте его улучшим. +1976.80 1982.84 "Игорь Лабутин" Чего в обычной жизни конечно, ну вряд ли вы будете обращать свое внимание на код, который работает 16 мс. +1982.84 1987.64 "Игорь Лабутин" Здесь важна каждая мелочь, потому что даже она позволяет хоть что-то выиграть. +1987.64 1993.00 "Игорь Лабутин" И произвести свой вклад в общее дело. +1993.00 1999.24 "Анатолий Кулаков" Ну знаешь, там 16 мс, здесь 16 мс, там уже 100 бабок это руб. +1999.24 2017.64 "Игорь Лабутин" Ну видимо на этом они и основывались, то есть понятно, что есть какие-то очень большие куски, которые возможно сейчас сделать сложно, ну просто потому что дотлен сам по себе, там требует поднять довольно много вещей, там и DC, и JIT, там где он доступен на андроиде, но все остальное они пытаются оптимизировать. +2017.64 2020.36 "Игорь Лабутин" И с деталями там примерно следующее. +2020.36 2029.36 "Игорь Лабутин" Во-первых, они сначала сделали приложеньку, на которой они пытались это все моделировать и измерять, насколько вообще хорошо-плохо. +2029.36 2035.48 "Игорь Лабутин" Приложенька есть вообще на самом деле стандартная, как они говорят, некоторые тесты такой модель на приложение, но они написали свое. +2035.48 2038.20 "Игорь Лабутин" Они написали свое в 5 вариантах. +2038.20 2051.04 "Игорь Лабутин" Приложенька, смысл этой приложеньки, он простой, он берет рандомный текст, ну на самом деле берет фиксированную строчку текста, и выводит его с рандомным поворотом и рандомным цветом на экран просто, в разных местах, опять же рандомно. +2051.04 2054.44 "Игорь Лабутин" И по сути просто мерить, сколько раз вы смогли это сделать за секунду. +2054.44 2076.96 "Игорь Лабутин" Текст они выбрали очень прикольный, текст они выводят лолы, поэтому у них метрика называется lols_per_seconds, и на Xamarin.Forms, если это написать прям стареньком, то это будет 179 штук в секунду, на .NET 6 Maui 327 штук в секунду, на .NET 7 493, то есть это в полтора раза больше. +2076.96 2098.08 "Игорь Лабутин" На .NET Android, то есть это .NET приложение, использующее нативные байнинги к Android, всяким контроллам и всему остальному, 594, то есть .NET Maui где-то на 20% отстает от полноценного .NET Android, и на Java он еще процентов на 20% отстает, на Java 682. +2098.08 2103.60 "Игорь Лабутин" Короче нужно .NET 7 Maui ускорить где-то раза в полтора, чтобы добраться до скорости Java. +2103.60 2108.60 "Игорь Лабутин" Ну Java, понятно, нативный язык для Android, поэтому там все быстрее максимально. +2108.60 2119.12 "Игорь Лабутин" И это на самом деле, вот это вот Interop с Java, это практически основной источник улучшения стартап тайма и вообще работы для .NET приложения. +2119.12 2124.68 "Игорь Лабутин" То есть и в стартапе требуется много Interop, и дальше при дальнейшей работе много Interop. +2124.68 2140.04 "Игорь Лабутин" И там написано в статье довольно много интересных и на самом деле довольно очевидных техник, ну типа если у вас есть пропертия, которые под капотом ходят в javaski Interop, ну наверное можно внутри одной функции эту пропертию запихнуть в локальную переменную и дальше пользоваться локальной переменной. +2140.04 2145.80 "Игорь Лабутин" Ну в C# мы привыкли, что пропертия обычно это дешевая штука, ну если правильно написано. +2145.80 2149.56 "Игорь Лабутин" То естественно код написан был исходя из того, что пропертия это дешевая штука. +2149.56 2160.28 "Игорь Лабутин" Но оказалось она в мире такого Interop и Maui не очень дешевая местами, и потому что идет в Java на каждую чтение пропертии, это не здорово. +2160.28 2169.24 "Игорь Лабутин" Во-вторых, есть например методы, которые вам нужно получить, например, дефолтную ширину-высоту экрана, для этого нужно дернуть javaski метод. +2169.24 2172.56 "Игорь Лабутин" Точнее вы дергаете два метода, получить ширину, получить высоту. +2172.56 2178.36 "Игорь Лабутин" Можно дернуть метод, который вернет структурку, но там накладные расходы на передачку этой структуры. +2178.36 2189.32 "Игорь Лабутин" Инфективнее всего передавать интеджеры или лонги, и поэтому они написали хелперный Java метод, который пакует ширину и длину в общий лонг, ну битовой магии, да, и потом это все возвращает в C#. +2189.32 2194.88 "Игорь Лабутин" В общем, такими методами 100 миллисекунд, 10 миллисекунд, вот таким образом это все и экономится. +2194.88 2198.24 "Игорь Лабутин" Дальше там пошли уже совсем какие-то извращенные техники с моей точки зрения. +2198.24 2206.40 "Игорь Лабутин" Например, они выяснили, что очень много времени уходит на вызов метода datetime_offset.now, но не метод на пропертии. +2206.40 2208.00 "Игорь Лабутин" Ну, по понятным причинам. +2208.00 2217.28 "Игорь Лабутин" UTC_NOW добыть легко, а NOW требует сходить в информацию о таймзоне, узнать, собственно, что за таймзона, зааджастить текущее время к текущей таймзоне. +2217.28 2221.48 "Игорь Лабутин" И вот эта вот загружка информации про таймзоны, она занимает время. +2221.48 2224.32 "Игорь Лабутин" Поэтому они сделали хитрый ход, я так и не понял, зачем. +2224.32 2235.12 "Игорь Лабутин" На старте они сначала читают информацию о таймзоне в джава-коде, передают ее из джава-кода в C# и используют эту информацию об оффсете во время стартапа. +2235.12 2246.88 "Игорь Лабутин" Одновременно они стартуют бэкграундный трет для загрузки этой же информации в C#-овый код, и как только эта информация загрузится, то все вычисления оффсетов переходят на C#-овые данные. +2246.88 2247.88 "Игорь Лабутин" Сложно. +2247.88 2248.88 "Игорь Лабутин" Сложно. +2248.88 2249.88 "Игорь Лабутин" Я не понял, в чем смысл. +2249.88 2256.84 "Игорь Лабутин" Возможно, потому что там что-то может поменяться, ну, по пути или еще как-то, или чтобы поведение точно соответствовало поведению C# везде и было одинаковым. +2256.84 2258.76 "Игорь Лабутин" Ну, а на стартапе будет немножко отличаться. +2258.76 2262.16 "Игорь Лабутин" Выглядит забавно, я не очень понимаю эту технику, но вот так сделано. +2262.16 2275.36 "Игорь Лабутин" Вот, в куче мест они постарались убрать передачу массивов, то есть часть AP-шек была сделана так, что она возвращает, например, не знаю, массив из трех элементов, ну, там RGB-компонент, например, или еще что-нибудь в таком духе. +2275.36 2276.36 "Игорь Лабутин" Вот. +2276.36 2284.12 "Игорь Лабутин" Интерроб массивов он сложный и медленный, как выяснилось, потому что для того, чтобы интерробить массивы между Java и C#, они их копируют всегда. +2284.12 2287.68 "Игорь Лабутин" То есть передача массива и туда и обратно - это обязательная копия. +2287.68 2295.84 "Игорь Лабутин" А поэтому, опять же, пришлось битовой магией схлопывать это все по возможности в одно число и передавать. +2295.84 2299.36 "Игорь Лабутин" Дальше к SAML они компилируют в IL-код сразу. +2299.36 2304.84 "Игорь Лабутин" То есть не хранят там в виде ресурсов, в виде еще чего-то, а стараются сразу компилировать в IL-код. +2304.84 2319.12 "Игорь Лабутин" Ну и для винды используют RadioTuran во все, значит, это самое, потому что RadioTuran - это хорошо, он там прикомпилирует все как надо, и тем самым улучшает стартап-тайм на десктопе на винде. +2319.12 2335.40 "Игорь Лабутин" Помимо этого пришлось делать кучу изменений в Mono, ну потому что под компотом там Mono крутится, интерпретатор, потому что, например, на iOS у вас нету JIT, а хочется поддерживать System Reflection Emit. +2335.40 2343.72 "Игорь Лабутин" Чтобы это сделать, на самом деле на iOS, как выяснилось, для меня это было новостью, вполне поддерживается System Reflection Emit. +2343.72 2347.84 "Игорь Лабутин" Но мы же не можем на iOS исполнять код, который мы только что сгенерили, там JIT нет. +2347.84 2353.20 "Игорь Лабутин" Поэтому для исполнения такого кода используется Mono Interpreter внутри, под компотом семерки. +2353.20 2372.04 "Игорь Лабутин" И туда завезли некоторый аналог Tyrate компиляции, то есть это, конечно, не компиляция, это интерпретация, но если Mono Interpreter понимает, что какой-то кусочек кода, который вы сгенерили, используется очень часто, он его как-то оптимизирует пооптимальнее и начинает выполнять быстрее. +2372.04 2385.36 "Игорь Лабутин" Ну и куча всяких разных, повыкидывали лишних вещей из джавовского кода, плюс вот это может быть практически интересная штука, написали тул, который позволяет мерить стартап тайм. +2385.36 2400.44 "Игорь Лабутин" Все измерения стартап тайма, которые я выше приводил, они сделаны не просто так секундомером, для этого написан специальный тул, который, если вам интересно, если вы вдруг зачем-то мерите стартап тайм вашего продукта, можете у Microsoft позаимствовать и использовать тот же самый тул. +2400.44 2406.08 "Игорь Лабутин" Может быть, они его даже оформят в виде полноценного dotnet тула, рассматривать такую возможность пока еще не сделали. +2406.08 2407.08 "Игорь Лабутин" Примерно так. +2407.08 2429.68 "Игорь Лабутин" Короче, MAUI — это такая забавная конструкция, то есть с одной стороны там довольно противоречивые требования, потому что и Android, и iOS, и десктопы, они все очень разные, везде свои особенности, везде свои проблемы, везде свои оптимизации, которые нужно делать, и они как-то пытаются это все балансировать так, чтобы в результате получилось удовлетворительный перформанс везде. +2429.68 2431.92 "Игорь Лабутин" Ну вот, как-то получается. +2431.92 2434.96 "Игорь Лабутин" Не знаю, я пока не видел, не знаю, слышал ты каких-нибудь, +2434.96 2443.44 "Анатолий Кулаков" ну хоть каких-то приложений к этому MAUI? Наверное, еще нет, скорее всего все боятся, все ждут какую-то стабильную версию, и вот это, наверное, она и есть. +2443.44 2458.56 "Игорь Лабутин" Но с другой стороны, dotnet 7 — это не LTS, поэтому возможно сейчас на семерке начнут появляться какие-то экспериментальные приложения, и только к восьмерке, которая будет LTS, там вот уже, может быть, кто-то начнет что-то менять, переписывать или писать что-то новое. +2458.56 2480.92 "Анатолий Кулаков" Так как UI-компоненты, то есть UI-продукты, вот эти, в общем, UI-ки — это довольно-таки сложные обычно вещи, и там очень много, очень плотная интеграция с самим фреймворком, то мне кажется, что те люди, которые, например, уже давно сидят на старых UI-ках и хотят куда-то переехать, то для них сейчас самое время уже начинать переписывать, чтобы к моменту стабильного выхода нового релиза через год у них уже было все готово. +2480.92 2486.24 "Игорь Лабутин" Да, согласен, но с другой стороны, как человек, который +2486.24 2501.68 "Игорь Лабутин" когда-то переписывал, ну не переписывал, а начинался писать на нестабильной версии WPF, ну как бы количество workaround-ов и bug-ов, которые были, не то чтобы это плохо, но эти workaround-ы жили потом долго даже после выхода стабильной версии. +2501.68 2504.96 "Игорь Лабутин" Поэтому… Да, такое тоже бывает, к сожалению. +2504.96 2507.36 "Игорь Лабутин" Тут надо будет тщательно балансировать. +2507.36 2518.44 "Игорь Лабутин" Ну ладно, в общем с performance у нас вроде как все, вернее как, ну у нас на этот выпуск все, мы скорее всего затронем, конечно, какой-то performance в следующем выпуске, когда будем говорить в целом про тот всем релиз. +2518.44 2522.72 "Игорь Лабутин" Еще раз напомню, что все стало лучше, выше, сильнее и быстрее. +2522.72 2525.44 "Игорь Лабутин" Ну а пока давай перейдем к другим вещам. +2525.44 2539.04 "Анатолий Кулаков" Давай, я тут как раз наткнулся на одну такую фановую статьечку, которая нам расскажет и про новые методы, и про интеграцию с .NET, и вообще должна нас развлечь от всех вот этих performance низковыровневых вещей. +2539.04 2546.08 "Анатолий Кулаков" А нашел я статью, которая рассказывает нам о том, а как добавить в WPF .NET экспериментальный новый метод. +2546.08 2560.76 "Анатолий Кулаков" И я напомню, а для тех, кто не знал, расскажу, что сейчас в HTTP стандарте рассматривается новое ключевое слово, новый verb, новый глагол, который называется query. +2560.76 2564.76 "Анатолий Кулаков" И вот его, в принципе, вы уже можете добавить в свои приложения. +2564.76 2568.40 "Анатолий Кулаков" Давайте обсудим и посмотрим, как это можно сделать. +2568.40 2571.44 "Анатолий Кулаков" Во-первых, что такое query и зачем он был нужен? +2571.44 2574.40 "Анатолий Кулаков" Тут лучше всего начать с истории. +2574.40 2588.04 "Анатолий Кулаков" Наверное, как многие из вас знают, что для того, чтобы запросить какую-то информацию с сервера, например, там список юзеров, список групп, еще какую-то подробную информацию об одном юзере, обычно люди используют метод get. +2588.04 2594.56 "Анатолий Кулаков" Вы делаете get, потом передаете туда адрес ресурса, и вам возвращается то, что вы хотели. +2594.56 2603.00 "Анатолий Кулаков" Если вы хотите добавить какие-то дополнительные параметры, например, вам нужен список не всех юзеров, а как-то вы хотите отфильтровать, это тоже делается элементарно. +2603.00 2611.52 "Анатолий Кулаков" Вы просто в query строку записываете какой-нибудь фильтр с каким-нибудь экспрессионом, и тоже у вас, в принципе, все работает. +2611.52 2615.84 "Анатолий Кулаков" Фильтр отработает на сервере, вам вернутся к значению, и в принципе все счастливы. +2615.84 2619.00 "Анатолий Кулаков" Но у этого подхода есть большие ограничения. +2619.00 2624.40 "Анатолий Кулаков" Во-первых, вся эта query строка, она должна быть заискепиана, заинкожена. +2624.40 2637.32 "Анатолий Кулаков" После того, как она заинкожена, на нее накладываются всякие ограничения HTTP спецификации, что у нее там есть определенные ограничения по размеру, которые зависят тоже от браузера, от версии, от погоды на Марсе. +2637.32 2651.28 "Анатолий Кулаков" Но суть в том, что если вам вдруг нужно эту query строку сделать большую, то вы упретесь в тот факт, что сделать это практически нереально, потому что HTTP протокол не поддерживает большие query строки. +2651.28 2655.64 "Анатолий Кулаков" А строку сделать большую, на самом деле, это не такая редкая ситуация, как вам кажется. +2655.64 2673.60 "Анатолий Кулаков" Если взять тот же самый произвольный фильтр, который вы туда накладываете, и прибавить туда какое-нибудь более сложное условие, например, если пользователь находится в таком-то списке имен и передавать туда список имен, то вы очень быстро уткнетесь в тот лимит, буквально передать там несколько десятков имен и все. +2673.60 2681.08 "Анатолий Кулаков" И лимит достигнут, и ваше приложение уже не работает, уже агент делать не сможет. +2681.08 2686.52 "Анатолий Кулаков" Человечество столкнулось с этой проблемой довольно давно, и, соответственно, есть несколько способов ее решения. +2686.52 2692.52 "Анатолий Кулаков" Одним из самых простых и порицаемых – это использование вместо GET-а поста. +2692.52 2700.00 "Анатолий Кулаков" POST в данном случае от GET-а отличается тем, что у GET-а не имеет права иметь BODY. +2700.00 2703.64 "Анатолий Кулаков" То есть у GET-а BODY не бывает, у него только query-параметры. +2703.64 2707.44 "Анатолий Кулаков" А вот в POST можно засунуть любой BODY. +2707.44 2716.68 "Анатолий Кулаков" Соответственно, весь тот огромный запрос, который у вас не влез в предыдущем пункте в GET, вы очень легко можете селезнуть и засунуть его в BODY-поста. +2716.68 2722.44 "Анатолий Кулаков" На BODY практически нет никаких ограничений, в общем, вам его хватит с головой всегда и везде. +2722.44 2738.20 "Анатолий Кулаков" Соответственно, у нас уже будет метод, который называется POST к ресурсу, который называется USER, или может быть даже в этом случае уже GET-USER, и в качестве экспрессиона, в качестве фильтра мы в BODY передадим все, что нам нужно. +2738.78 2746.94 "Анатолий Кулаков" Данный подход не зря полицаем народом, потому что POST имеет кучу проблем. +2746.94 2752.10 "Анатолий Кулаков" Самая главная проблема, на которую все обращают внимание в первую очередь, это в том, что он не кашируется. +2752.10 2762.02 "Анатолий Кулаков" Действительно, у нас HTTP в мир, у нас HTTP протокол, и вот этот весь World Wide Web, он существует на куче спецификаций и договоренностей. +2762.02 2767.62 "Анатолий Кулаков" И одна из самых главных договоренностей существует в том, что метод GET можно кашировать. +2767.62 2774.42 "Анатолий Кулаков" Если у него одинаковые параметры в query-строке, то значит можно безболезненно отдавать какой-то результат. +2774.42 2779.98 "Анатолий Кулаков" Естественно, на какое-то время, не навсегда, но это очень сильно увеличивает перформанс. +2779.98 2793.06 "Анатолий Кулаков" Я думаю, когда мы разбирали методы оптимизации и методы улучшения перформанса команды ISP.NET Core и прочих команд в Дот-нете, вы увидели, что очень много вещей решается там с помощью кэша. +2793.06 2798.90 "Анатолий Кулаков" И кэш вам дает обалденный буст производительности, если вы знаете, когда его правильно чистить. +2798.90 2802.18 "Анатолий Кулаков" И вообще это один из самых первых методов оптимизации. +2802.18 2805.94 "Анатолий Кулаков" Поэтому кэширование на самом деле это очень важно. +2805.94 2816.44 "Анатолий Кулаков" Особенно если мы смотрим на сеть интернет, в которой там идут сексилиарды запросов в миллисекунду, то там кэширование становится просто ключевым фактором и просто так терять его не хотелось. +2816.44 2831.22 "Анатолий Кулаков" Но если вы используете метод POST и передаете аргументы в BODY, то кэширование вы теряете на вот таких промежуточных узлах, которые вполне могли бы обеспечить более быстрый доступ к вашим методам. +2831.22 2835.50 "Анатолий Кулаков" В большинстве случаев на это все забивали, потому что это было меньше изол. +2835.50 2840.22 "Анатолий Кулаков" Если там мы просто в GIT не могли ничего сделать, то в POST мы всего лишь на все теряем кэширование. +2840.22 2850.74 "Анатолий Кулаков" Ну, наверное, для большинства запросов это нормальная ситуация, но все же остаточек оставался. +2850.74 2862.14 "Анатолий Кулаков" И как раз таки, чтобы убрать эту проблему, весь консорсум World Wide Web собрался и наконец-то в 21 веке придумал новое ключевое слово, которое называется QUERY. +2862.14 2881.06 "Анатолий Кулаков" Это ключевое слово имеет полностью семантику GET, его же плюсы, то есть оно подразумевает, что все прокси будут кэшировать ответ, также подразумевается, что QUERY, так же как и GET, он иденпатентный, и ему прибавляется плюс POST. +2881.06 2883.42 "Анатолий Кулаков" QUERY теперь может иметь BODY. +2883.42 2891.10 "Анатолий Кулаков" В общем, в этот BODY можно засунуть опять же все, что вам угодно, даже тот expression, который вам нужно было бы передать, и он большой, страшный и все такое. +2891.10 2894.50 "Анатолий Кулаков" Но теперь вы можете его засунуть в BODY, и это все будет кэшироваться. +2894.50 2897.14 "Анатолий Кулаков" Вот ради этого изобрели новое слово. +2897.14 2900.06 "Анатолий Кулаков" Слово, которое объединяет и GET, и POST. +2900.06 2902.94 "Анатолий Кулаков" Теперь в BODY вы можете положить все, что угодно. +2902.94 2912.70 "Анатолий Кулаков" Например, вы туда можете засунуть GRAPHQL, вы туда можете засунуть полноценный SQL SCRIPT, вы туда можете даже LINK положить, потому что теперь это можно. +2912.70 2916.14 "Анатолий Кулаков" Теперь фильтр может быть вообще произвольной и произвольной длины. +2916.14 2921.82 "Анатолий Кулаков" Теперь там можно и запросы вкладывать, и батчинги вкладывать, и скрипты вкладывать, вообще все, что вам только придет в голову. +2921.82 2925.38 "Анатолий Кулаков" Вот консорциум такую штуку придумал. +2925.38 2928.46 "Анатолий Кулаков" Отлично, но в официальном кестре она еще не появилась. +2928.46 2935.38 "Анатолий Кулаков" Давайте же посмотрим, а как можно ее уже сейчас добавить в ваше приложение, и что для этого нужно сделать. +2935.38 2937.90 "Анатолий Кулаков" Для начала рассмотрим MINIMAL API. +2937.90 2943.14 "Анатолий Кулаков" На самом деле не нужно очень много кода для того, чтобы держать вот такую ключевую концепцию, как новое слово. +2943.14 2951.54 "Анатолий Кулаков" А все потому, что на самом деле в HTTP протоколе не задекларирован какой-то строгий список этих глаголов. +2951.54 2954.62 "Анатолий Кулаков" На самом деле вы туда можете передать абсолютно любой глагол. +2954.62 2958.58 "Анатолий Кулаков" Другой вопрос, кто его будет поддерживать и как он будет обрабатываться, это дело десятое. +2958.58 2963.06 "Анатолий Кулаков" Но вы можете, судя по самой спецификации протокола. +2963.06 2967.14 "Анатолий Кулаков" Вот и здесь в принципе протокол никак нам не запрещает использовать новое слово. +2967.14 2973.30 "Анатолий Кулаков" Нам осталось лишь научить наш MINIMAL API, наши хендлеры, наш ASP.NET обрабатывать эту штуку. +2973.30 2975.46 "Анатолий Кулаков" И обработка тоже делается достаточно просто. +2975.46 2989.10 "Анатолий Кулаков" Все, что вам нужно сделать, это сделать специальный метод, который называется MapQuery, по аналогии с другими экстеншн методами, который MapGet, MapPost, которые мапят соответствующий URL на его обработчик. +2989.10 3004.38 "Анатолий Кулаков" В этом методе MapQuery у вас будет Endpoint Convention Builder, у которого достаточно вызвать метод MapMethod и передать ему этот глагол, то есть передать ему просто Query. +3004.38 3013.78 "Анатолий Кулаков" В общем, этого достаточно для того, чтобы кестер сообразил, что как только вам приходит вот этот неизвестный глагол, должен вызываться ваш делегат. +3013.78 3017.62 "Анатолий Кулаков" А в делегате уже непосредственно происходит обработка события. +3017.62 3026.78 "Анатолий Кулаков" Этот делегат в MINIMAL API может принимать специальный класс, который описывает тот запрос к нему, как только к нему пришел. +3026.78 3029.14 "Анатолий Кулаков" Это, допустим, класс Query. +3029.14 3040.74 "Анатолий Кулаков" Теперь все, что вам нужно сделать, это создать вот этот класс Query и переопределить у него метод BindAsync, который при качестве параметра принимает HTTP контекст и параметр List. +3040.74 3055.78 "Анатолий Кулаков" Как вы уже догадались, из HTTP контекста и из параметров вам нужно каким-то образом, известным только вашему обработчику, достать параметры, в нашем случае просто-напросто считать Body и положить его уже в какую-то заранее переменную для децерализованных данных. +3055.78 3058.14 "Анатолий Кулаков" И дальше эта переменная будет доступна в делегате. +3058.14 3071.26 "Анатолий Кулаков" Таким образом, вы можете теперь регистрировать ваши новые делегаты с помощью метода MapQuery, указывать route и принимать в качестве параметра тот децерализованный классик Query, который мы разобрали секунду назад. +3071.26 3073.62 "Анатолий Кулаков" Обращаться, соответственно, к его свойствам. +3073.62 3075.10 "Анатолий Кулаков" Все легко и просто. +3075.10 3078.54 "Анатолий Кулаков" Как же сделать подобную штуку в ASP.NET Core MVC? +3078.54 3080.86 "Анатолий Кулаков" На самом деле, еще проще. +3080.86 3088.78 "Анатолий Кулаков" Вы просто-напросто добавляете еще один атрибут, например, HTTP Query атрибут, который наследуется от специального HTTP метод атрибута. +3088.78 3097.62 "Анатолий Кулаков" И HTTP метод атрибут в конструкторе принимает список методов, которые поддерживает ваш вот этот вот атрибут. +3097.62 3100.30 "Анатолий Кулаков" Естественно, вы туда передаете строку Query. +3100.30 3115.78 "Анатолий Кулаков" Как только вы это сделали, со этого самого момента, вы можете навешивать ваш HTTP Query атрибут над вашими экшенами, над вашими методами контроллера, точно так же, как вы раньше навешивали HTTP GET, HTTP POST. +3115.78 3118.82 "Анатолий Кулаков" Теперь у вас будет просто-напросто HTTP Query атрибут. +3118.82 3124.62 "Анатолий Кулаков" И ваш метод уже будет дергаться непосредственно, как только придет Query глагол к кестрелу. +3124.62 3126.86 "Анатолий Кулаков" Кестрел уже знает, что с ним делать. +3126.86 3127.94 "Анатолий Кулаков" Вот в принципе вот так. +3127.94 3129.98 "Анатолий Кулаков" Все намного проще, чем казалось. +3129.98 3133.26 "Анатолий Кулаков" И поддерживается и в старых версиях, и в новых версиях, и где угодно. +3133.26 3137.98 "Анатолий Кулаков" Лишний раз доказывается, что ASP.NET расширяется просто великолепно. +3137.98 3144.26 "Анатолий Кулаков" В общем, если вы вдруг захотите использовать этот Query атрибут по-настоящему в вашем продакшн коде, то вот здесь вот сильно не торопитесь. +3144.26 3148.30 "Анатолий Кулаков" Ну, во-первых, это все-таки еще экспериментальный метод. +3148.30 3151.86 "Анатолий Кулаков" Все еще идут обсуждения, все еще идут какие-то договоренности. +3151.86 3157.26 "Анатолий Кулаков" И в частности, он не поддерживается во многих сторонних инструментах. +3157.26 3160.58 "Анатолий Кулаков" Во многих инструментах, которые окружают вас ежедневно. +3160.58 3168.18 "Анатолий Кулаков" Ну, например, тот же самый Swashbuckle, который также известен как Swagger, который также известен как Open API Library. +3168.18 3171.14 "Анатолий Кулаков" В общем, он еще не понимает этот новый кейворд. +3171.14 3177.34 "Анатолий Кулаков" Соответственно, вы не сможете с помощью него отлаживать, запускать методы, которые вызываются с помощью Query. +3177.34 3182.78 "Анатолий Кулаков" Также точно практически никто из инфраструктуры не поддерживает Query. +3182.78 3189.34 "Анатолий Кулаков" То есть, вы можете потерять кэширование, load balancing и прочие вещи на сторонних каких-то инструментах. +3189.34 3194.02 "Анатолий Кулаков" На Jinx, на Lastic Load Balancer и на прочей инфраструктуре. +3194.02 3196.74 "Анатолий Кулаков" Они тоже пока еще не очень знают, что с ним делать. +3196.74 3205.86 "Анатолий Кулаков" Эта поддержка добавляется, безусловно, я думаю, через некоторое время все главные библиотеки, все главные инструменты, которые развиваются, такую штуку к себе добавить. +3205.86 3208.62 "Анатолий Кулаков" Но пока ситуация именно такая. +3208.62 3210.66 "Анатолий Кулаков" Используется все на ваш страх и риск. +3210.66 3217.90 "Анатолий Кулаков" Если вы вдруг захотите это использовать в продакшене, то обязательно смотрите, какими инструментами вы используетесь и проверяйте проверку у них. +3217.90 3225.18 "Игорь Лабутин" Ну, я что-то думаю, что пока это не будет поддержано в максимально большом количестве тулов, использовать это, ну не знаю зачем. +3225.18 3234.70 "Игорь Лабутин" Если это между вашими двумя приложениями, так можно и просто постом, а если куда-то наружу, так там в интернете мало кто это поддерживает, нормально пока еще, мне кажется. +3234.70 3240.02 "Анатолий Кулаков" Да, к сожалению, мы не знаем через какие роутеры пройдет эта штука и какая версия, какого ПО там стоит. +3240.02 3241.58 "Анатолий Кулаков" Поэтому мы можем только надеяться. +3241.58 3248.88 "Игорь Лабутин" Но пока у нас твой страх и риск, можно поэкспериментировать, не знаю, добавлять поддержку этой штуки в разные другие тулы. +3248.88 3250.86 "Игорь Лабутин" Вам, может, спасибо скажут за это. +3250.86 3253.22 "Игорь Лабутин" И потом все начнем использовать резко. +3253.22 3258.86 "Игорь Лабутин" Давай пойдем дальше, в другую часть нашего замечательного фреймворка. +3258.86 3261.22 "Игорь Лабутин" Ты знаешь ли ты, что такое memory model? +3261.22 3262.22 "Игорь Лабутин" Да, конечно. +3262.22 3264.50 "Анатолий Кулаков" Знаешь ли ты, какая она у .NET? +3264.50 3267.62 "Анатолий Кулаков" Я знаю в том, что она у .NET неформализованная. +3267.62 3268.62 "Игорь Лабутин" Ну, как? +3268.62 3270.90 "Игорь Лабутин" Значит, на самом деле у нас есть спека. +3270.90 3276.22 "Игорь Лабутин" Спека называется ECMO-335, насколько я помню, на рантайм, да? +3276.22 3279.00 "Игорь Лабутин" И технически там что-то описано. +3279.00 3289.96 "Игорь Лабутин" Но то, что там описано, оно очень, то, что называется weak, то есть оно слабое, то есть оно подходит под много чего и дает очень мало. +3289.96 3295.72 "Анатолий Кулаков" Она мега абстрактная и какие-то конкретные вещи, которые вам нужно ответить на вопрос, а здесь что будет? +3295.72 3297.92 "Анатолий Кулаков" Вот обычно на такие конкретные вещи она не отвечает. +3297.92 3301.20 "Игорь Лабутин" Ну, она не отвечает в том смысле, что она разрешает довольно много всего. +3301.20 3307.86 "Игорь Лабутин" То есть рантайм, который удовлетворяет ECMO-335, может делать, ну не то чтобы все что угодно, но там довольно мало ограничений. +3307.86 3332.06 "Игорь Лабутин" В реальной жизни рантайм, он гораздо более ограничен, потому что исторически .NET Runtime развивался на железе, которое чуть более ограничено, и даже сейчас, когда мы переехали, ну не переехали, а позволили поддерживать и армы и всякие странные процессоры, реалии таковы, что реальные железные ограничения все равно сильнее, чем ECMO, насколько я понимаю. +3332.06 3346.16 "Игорь Лабутин" Поэтому в репе .NET Runtime появилась наконец-таки идея сделать нормальное описание .NET Memory Model, а что же собственно текущий современный .NET Runtime в принципе сейчас предоставляет. +3346.16 3359.16 "Игорь Лабутин" Он предоставляет некоторый компромисс, чтобы быть разумно работающим на всех платформах и при этом все еще удовлетворять ECMO-335, и при этом чтобы это было как-то нормально, понятно, используемо. +3359.16 3373.16 "Игорь Лабутин" И появился pull request, он появился где-то в сентябре, если я правильно помню, в котором появилась некоторая, просто видите, страничка в том самом ботере буквы Runtime, где написано .NET Memory Model. +3373.16 3377.00 "Игорь Лабутин" Если вы хотели узнать, что же такое .NET Runtime Memory Model, вам туда. +3377.00 3399.64 "Игорь Лабутин" Это пока еще не финальный вариант, там активнейшее обсуждение, там пришли все самые умные люди из Runtime и все это дело активно обсуждают, то есть я там не то чтобы половину комментов не понял, но чтобы их понять надо реально хорошо вчитываться, кто там куда, кого заимствует, кто как читает, какие reordering разрешены и все такое прочее. +3399.64 3408.68 "Игорь Лабутин" Но если вам это интересно, если вы всегда хотели узнать, как же по-настоящему работает volatile, что он гарантирует, что он не гарантирует, то идите туда и посмотрите. +3408.68 3421.60 "Игорь Лабутин" Также там есть интересная секция, последняя в этом документе, это практически примеры того, как же нужно реализовывать правильно паттерны, то есть типа условный double check log для singleton, вот этого всего. +3421.60 3436.04 "Игорь Лабутин" Там это все написано правильно, ну даже не то чтобы правильно, а минимально необходимо, то есть понятно, что можно все обвесить логами и все будет работать, но на самом деле местами достаточно делать volatile read и volatile write и все тоже будет работать. +3436.04 3440.28 "Игорь Лабутин" Вот там написано как бы минимально правильные примеры, как это нужно все делать. +3440.28 3448.52 "Анатолий Кулаков" Вот это интересный вопрос, знаешь, обычно на собеседование задают, типа реализуйте мне самый примитивный какой-нибудь double checking log. +3448.52 3472.12 "Анатолий Кулаков" На самом деле, если придерживаться официальной спецификации memory module, то однозначно реализовать его невозможно, потому что, ну однозначно примитивный, самый минимальный реализовать невозможно, потому что мы не знаем, как ведет себя memory module и мы не знаем, где эта штука будет запускаться, это зависит от рантайма, от версии и от железа и от много всего еще. +3472.12 3478.04 "Анатолий Кулаков" Поэтому такой простейский вопрос, на который, наверное, уже каждый джун отвечает, на самом деле не имеет ответа. +3478.04 3482.00 "Игорь Лабутин" Ну, как бы да, каждый джун отвечает, делаем log, да. +3482.00 3483.92 "Игорь Лабутин" Да, делаем два лока и все хорошо. +3483.92 3487.24 "Игорь Лабутин" Нет, подожди, один log, два if, if log, if. +3487.24 3488.24 "Игорь Лабутин" Да, два if. +3488.24 3497.76 "Игорь Лабутин" Вот, и как бы везде, где работает dotnet, работать будет, потому что dotnet runtime, он вот некоторые гарантии дает. +3497.76 3501.88 "Игорь Лабутин" Но на самом деле можно написать его чуть более оптимально, вот это все. +3501.88 3515.76 "Игорь Лабутин" Поэтому если вам интересна тема вот этих всех memory modules, да, acquired read, write, reordering, вот это все, идите, читайте, участвуйте в обсуждении, задавайте вопросы, там довольно все активно живет. +3515.76 3526.24 "Игорь Лабутин" PR, не знаю, когда будет реально закоммичено, я думаю, что они будут долго обсуждать, пока не придут к какому-то общему пониманию и правильным примерам и терминологии. +3526.24 3532.52 "Игорь Лабутин" Там не только обсуждается непосредственно, что же мы реализовали и как оно на самом деле работает, но и какими примерами это лучше иллюстрировать. +3532.52 3540.20 "Игорь Лабутин" То есть там часть, по крайней мере, комментов, которые я читал к этому pull request, они про то, что вот этот пример не совсем характерен, давайте лучше вот такой возьмем. +3540.20 3552.36 "Игорь Лабутин" А если вы новичок и вам, в принципе, интересно, что такое memory module, то у нас в шоу-ноутах будет еще ссылочка на очень старый доклад Саши Гальштейна на dotnext про C++ и CLR memory modules. +3552.36 3573.84 "Игорь Лабутин" Тогда не было ничего еще стандартизированного и формализованного, но некоторое понимание того все-таки, как работает CLR memory module в то время, это 6 лет назад, уже было, некоторое понимание было, и он как раз-таки рассказывает вообще, что это такое, как к этому подходить и какие основные термины, концепции есть и чем они на самом деле отличаются от плюсов, если вам это интересно. +3573.84 3585.04 "Анатолий Кулаков" Кажется, именно там у него есть такие смешные демки, которые казалось бы абсолютно правильный код, и который все пишут и все такое, работает немножко не так, как на самом деле. +3585.04 3598.64 "Игорь Лабутин" Да, я помню, что доклад был хороший, давно его не пересматривал, надо будет действительно как-нибудь посмотреть, как раз и memory module почитать современную, чтобы уяснить себе-таки, как оно работает, и как же правильно надо отвечать на вопросы на собеседованиях. +3598.64 3609.20 "Анатолий Кулаков" Я думаю, когда этот доклад выйдет, мы там не один доклад на эту тему еще должны увидеть, услышать и не одну статейку прочитать, потому что труд действительно нужный, монументальный. +3609.20 3615.96 "Анатолий Кулаков" Конечно, интересно, что его делают постфактум, когда уже все состоялось, и обычно memory module делают в самом начале, когда пишут runtime. +3615.96 3617.96 "Анатолий Кулаков" Но что имеем, то имеем. +3617.96 3627.00 "Игорь Лабутин" Не, ну как бы, может быть она в каком-то виде и есть в головах у тех, кто пишет этот самый runtime, просто это некоторая попытка его формально записать в понятном виде. +3627.00 3634.76 "Анатолий Кулаков" Я думаю, она есть в коде, то есть runtime как-то работает по какой-то модели, и сейчас пытаются именно ее описать и как-то подогнать под теорию. +3634.76 3644.56 "Игорь Лабутин" Ну и хорошо, пошли в еще одну интересную тему, как я сказал, дотунайт работает много где, и в том числе на Raspberry. +3644.56 3648.00 "Анатолий Кулаков" Да, продолжаем рубрику, расширяем горизонты. +3648.00 3656.48 "Анатолий Кулаков" Хочется еще об некоторых технологиях вам рассказать, может быть, которые почему-то вы еще не слышали, и это мы устраним с помощью нашего образовательно-новостного подкаста. +3656.48 3665.36 "Анатолий Кулаков" Хочется рассказать о том, каким же образом все-таки запустить дотнет через WASM на Raspberry Pi. +3665.36 3669.24 "Анатолий Кулаков" Вот такая сложная цепочка, давайте посмотрим по каждому пункту в отдельности. +3669.24 3672.24 "Анатолий Кулаков" Во-первых, для тех, кто в танке, что такое WASM. +3672.24 3677.84 "Анатолий Кулаков" Вы с WASM знакомы, наверное, давно, когда еще в дотнете появились первые версии Blazor, Blazor WebAssembly. +3677.84 3685.68 "Анатолий Кулаков" Это такая специальная технология, которая позволяет вам дотнет компилировать прямо под браузер, грубо говоря, под движок джаваскрипта. +3685.68 3693.60 "Анатолий Кулаков" И, соответственно, браузер может выполнять вашу программу, не обращаясь к серверу, даже вообще не имея никакого коннекта к серверу, вообще даже офлайн. +3693.60 3696.36 "Анатолий Кулаков" Он один раз загружает сборочку и выполняет ее. +3696.36 3699.08 "Анатолий Кулаков" И это достигается с помощью технологии WASM. +3699.08 3703.60 "Анатолий Кулаков" WASM прекрасен тем, что он не только для дотнета. +3703.60 3713.92 "Анатолий Кулаков" Поэтому, когда сравнивают почему-то Blazor с Silverlight, вот здесь, безусловно, нужно учитывать, что это не какая-то плагина от Microsoft, которая нужна только для дотнета. +3713.92 3715.48 "Анатолий Кулаков" Нет, WASM пошел другим путем. +3715.48 3720.48 "Анатолий Кулаков" Теперь это встроенная фишка во все современные браузеры, в том числе в мобильные. +3720.48 3730.12 "Анатолий Кулаков" Поддерживается она очень многими производителями и достойными всеми нормальными языками. +3730.12 3735.48 "Анатолий Кулаков" На самом деле это набор бинарных инструкций для специальной stack-based virtual машины. +3735.48 3744.48 "Анатолий Кулаков" Это, как я уже сказал, язык программирования, который не зависит от архитектуры. +3744.48 3751.68 "Анатолий Кулаков" То есть он очень портабельный, он выполняется абсолютно везде, где может выполняться в данном случае браузер и JavaScript. +3751.68 3754.92 "Анатолий Кулаков" А это, как мы понимаем, практически любая платформа. +3754.92 3759.48 "Анатолий Кулаков" Он очень низкоуровневый, он больше похож на Assembler. +3759.48 3770.68 "Анатолий Кулаков" Если вы когда-нибудь интересовались, заглядывали или гуглили, как выглядят Assembler инструкции, или если вы заглядывали в .NET.IL, то WASM напоминает именно его. +3770.68 3774.56 "Анатолий Кулаков" То есть это минимальные Assembly инструкции для виртуальной машины. +3774.56 3783.12 "Анатолий Кулаков" Он бинарный и он очень компактный, потому что сразу рассчитывалось на то, что будут передавать по сети, поэтому он должен быть очень сжатым, красивым, быстрым. +3783.12 3786.28 "Анатолий Кулаков" В общем, и этого удалось достигнуть. +3786.28 3795.02 "Анатолий Кулаков" И самое интересное, что его перформанс довольно высокий, потому что многие браузеры его поддерживают нативно. +3795.02 3806.32 "Анатолий Кулаков" И там были выбраны специально, подобраны инструкции таким образом, чтобы они хорошо ложились на векторизацию, на нативные команды процессора, на нативные команды видеокарт и прочее, прочее. +3806.32 3821.60 "Анатолий Кулаков" То есть язык разрабатывался специально для трехмерной реальности, для виртуальных игр, для еще вот таких вот очень ресурсов, таких активностей, которые требуют очень много производительности. +3821.60 3825.80 "Анатолий Кулаков" Поэтому он получился довольно компактный, довольно хорошо производительный. +3825.80 3834.72 "Анатолий Кулаков" И как я уже упомянул, нормальные языки, такие как C#, C, C++, Rust, все недавно умеют и хорошо компилироваться именно в WASM. +3834.72 3841.56 "Анатолий Кулаков" Таким образом у нас получается, что WASM — это такой интересный кроссплатформенный формат. +3841.56 3850.88 "Анатолий Кулаков" Наверное, многие большевики рассчитывали и надеялись на то, что у нас появится какой-нибудь формат, куда можно один раз скомпилировать и запускать абсолютно на всех платформах, на везде. +3850.88 3856.24 "Анатолий Кулаков" Но вряд ли кто-то мог представить, что это будет какой-то там отросток от JavaScript. +3856.24 3858.28 "Анатолий Кулаков" Но по сути получилось именно так. +3858.28 3870.12 "Анатолий Кулаков" Намного легче было написать кроссбраузерный JavaScript, захватить мир и потом на JavaScript сделать оптимизированный общесистемный низкоуровневый язык. +3870.12 3871.12 "Анатолий Кулаков" Получилось смешно. +3871.12 3874.12 "Анатолий Кулаков" Но, как ни странно, получилось очень хорошо. +3874.12 3879.88 "Анатолий Кулаков" И народ подхватил эту идею и подумал, а зачем нам обязательно запускать это все в браузере. +3879.88 3883.32 "Анатолий Кулаков" В принципе, получился отличный формат, поддерживается многими языками. +3883.32 3890.16 "Анатолий Кулаков" Он быстрый, он компактный, он интересный, он довольно легко читается и понимается. +3890.16 3896.12 "Анатолий Кулаков" А давайте мы будем его использовать как обычный формат для любого языка программирования. +3896.12 3902.68 "Анатолий Кулаков" То есть, по сути, запускать все эти приложения не в браузере, а запускать все эти приложения вообще на любом хосте. +3902.68 3905.48 "Анатолий Кулаков" И таким образом появился Wasi. +3905.48 3908.64 "Анатолий Кулаков" Wasi – это WebAssembly System Interface. +3908.64 3918.96 "Анатолий Кулаков" Это как раз-таки отдельный стандарт для Wasmo, который рассказывает о том, каким образом Wasmo взаимодействовать с любым окружением на хосте. +3918.96 3921.68 "Анатолий Кулаков" Хостом может быть любая операционная система. +3921.68 3927.56 "Анатолий Кулаков" Его можно запускать на чистом Linux, на Android, на Windows и вообще где угодно. +3927.56 3929.08 "Анатолий Кулаков" Везде, где что-то запускается. +3929.08 3938.20 "Анатолий Кулаков" Вот каким образом из песочницы JavaScript перетащить его на полноценную операционную систему, этим и занимается как раз вот этот System Interface. +3938.20 3944.56 "Анатолий Кулаков" То есть, это набор API, с помощью которого WebAssembly может вызывать нативные хостовые методы. +3944.56 3951.40 "Анатолий Кулаков" Таким образом, Wasi помогает вам запустить вашу Wasm-сборку без браузера на чистом хосте. +3951.40 3956.76 "Анатолий Кулаков" И для того, чтобы это сделать, нам нужны соответствующие рантаймы, которые реализуют данный подход. +3956.76 3962.32 "Анатолий Кулаков" Из известных есть WasmTime, Wasmir или WasmEdge. +3962.32 3964.52 "Анатолий Кулаков" Давайте же теперь посмотрим, как это все связано с .NET. +3964.52 3966.76 "Анатолий Кулаков" На .NET очень легко получить Wasi Project. +3966.76 3973.04 "Анатолий Кулаков" Для этого вам достаточно всего лишь на все немножко поменять стандартный WebAPI проект. +3973.04 3979.88 "Анатолий Кулаков" После этого вы можете создать обычный WebAPI проект, допустим, даже с дефолтным вот этим приложением, который там погодку нам показывает. +3979.88 3983.92 "Анатолий Кулаков" Оставим его таким же точно пустым, сделаем .NET Publish -c release. +3983.92 3993.64 "Анатолий Кулаков" И в результате, на выходе в Output мы уже получим не какую-то сборочку или .exe, а получим файл с расширением Wasm. +3993.64 3997.88 "Анатолий Кулаков" Этот файл можно запустить, допустим, прямо на Windows. +3997.88 3999.68 "Анатолий Кулаков" Для этого нам понадобится WasmTime. +3999.68 4004.72 "Анатолий Кулаков" WasmTime – это очень быстрая и security runtime для WebAssembly. +4004.72 4014.04 "Анатолий Кулаков" Это как раз таки и есть та запускалка, которая способна интерпретировать код Wasm на многих операционных системах. +4014.04 4018.56 "Анатолий Кулаков" Мы можем скачать WasmTime с GitHub. +4018.56 4020.08 "Анатолий Кулаков" Вызывается все довольно просто. +4020.08 4026.84 "Анатолий Кулаков" WasmTime, пробел и указываем имя того Output приложения, которое у нас появилось с расширением .wasm. +4026.84 4029.56 "Анатолий Кулаков" Как только мы его указали, у нас запустится это приложение. +4029.56 4035.68 "Анатолий Кулаков" Можно сделать проще, можно просто даже запустить .NET Run, если мы находимся в каталоге с нашим Wasi Solution. +4035.68 4039.68 "Анатолий Кулаков" И .NET Run вам, соответственно, запустит приложение. +4039.68 4048.32 "Анатолий Кулаков" Вы после этого можете открыть браузер, зайти на Localhost и убедиться, что весь WPPI отвечает вам стандартными отчетами про коду. +4048.32 4054.30 "Анатолий Кулаков" Вот так просто получить из .NET Wasm. +4054.30 4055.60 "Анатолий Кулаков" Мы на этом не останавливаемся. +4055.60 4059.16 "Анатолий Кулаков" Мы хотим запульнуть наш Wasm на Raspberry Pi. +4059.16 4066.44 "Анатолий Кулаков" Если кто не знал, то в последних Windows давно SSH и SCP входят в коробочную версию. +4066.44 4069.16 "Анатолий Кулаков" То есть, поставляются out of box эти утилиты. +4069.16 4078.80 "Анатолий Кулаков" С помощью SSH мы можем коннектиться к удаленному хосту по протоколу SSH, а с помощью SCP мы можем просто-напросто скопировать какой-то файлик на удаленный хост. +4078.80 4080.16 "Анатолий Кулаков" Чем мы, собственно, и займемся. +4080.16 4085.64 "Анатолий Кулаков" Возьмем этот файлик с Wasm и скопируем его с нашего PC на Raspberry Pi. +4085.64 4090.36 "Анатолий Кулаков" После этого мы с помощью SSH можем подконнектиться к Raspberry Pi. +4090.36 4094.40 "Анатолий Кулаков" Там нам нужно снова установить WasmTime для Raspberry Pi. +4094.40 4100.84 "Анатолий Кулаков" Это делается с помощью скачивания с GitHub, разархивирования и у нас уже есть готовый запускальщик в WebAssembly. +4100.84 4108.24 "Анатолий Кулаков" Точно так же WasmTime, пробел, наш файлик .wasm и на Raspberry Pi все точно так же запускается. +4108.24 4116.24 "Анатолий Кулаков" Вот таким образом выглядит эра кроссплатформенности, межязыковости и так далее. +4116.24 4122.28 "Анатолий Кулаков" Тут уже опять еще раз стоит напомнить, что эти Wasm файлы их может генерить абсолютно любой язык программирования. +4122.28 4124.48 "Анатолий Кулаков" Любой нормальный современный язык программирования. +4124.48 4129.12 "Анатолий Кулаков" То есть вы можете собрать какие-то утилиты с помощью разных языков. +4129.12 4131.96 "Анатолий Кулаков" Вы можете писать плагины с помощью разных языков. +4131.96 4138.76 "Анатолий Кулаков" Уже мы никак не опираемся на совместимость с архитектурой, с операционной системой, еще с чем-то. +4138.76 4142.76 "Анатолий Кулаков" Wasm предоставляет нам такой хороший абстрактный слой. +4142.76 4146.60 "Анатолий Кулаков" Соответственно мы с вами посмотрели каким образом создаются Wasm модули в дот-нете. +4146.60 4155.64 "Анатолий Кулаков" Каким образом можно сделать Web API прямо на чистом Wasm и как его запустить под виндой, как его запустить под Raspberry Pi. +4155.64 4159.12 "Анатолий Кулаков" И познакомились с утилитой WasmTime. +4159.12 4162.72 "Анатолий Кулаков" Таких утилит, которые способны запускать их несколько, WasmTime это одна из них. +4162.72 4166.60 "Анатолий Кулаков" Вот такое интересное будущее рисует нам WebAssembly. +4166.60 4176.56 "Игорь Лабутин" Ну да, кажется, что если мы туда можем купить вообще все что угодно и запускать это везде, где может быть запущен Wasm, то это такой почти докер. +4176.56 4177.56 "Анатолий Кулаков" Именно так. +4177.56 4188.96 "Анатолий Кулаков" Когда мы разговаривали про чистый Wasm, то при его разработке учитывалась та специфика, что он как раз таки будет запускаться всегда в браузере. +4188.96 4192.36 "Анатолий Кулаков" А браузер это должна быть очень секурная песочница. +4192.36 4199.64 "Анатолий Кулаков" Потому что из браузера никогда ваш ни JavaScript, ни какие-то другие скрипты, которые вы скачали из сторонних сервисов выбраться не должны. +4199.64 4206.12 "Анатолий Кулаков" Потому что как только в этой песочнице найдется дыра, то сразу в мире можно заразить миллиарды компьютеров, миллиарды пользователей. +4206.12 4208.00 "Анатолий Кулаков" Это очень-очень-очень страшно. +4208.00 4210.96 "Анатолий Кулаков" Поэтому в браузерах обычно железобетонные песочницы. +4210.96 4217.36 "Анатолий Кулаков" В самом Wasm есть специальные механизмы, которые позволяют железобетонные песочницы поддерживать. +4217.36 4225.04 "Анатолий Кулаков" То есть это штука, которая изначально проектировалась именно для того, чтобы секурно запускаться в песочницах. +4225.04 4229.48 "Игорь Лабутин" Ну и это как раз то, что нужно для докера по большому счету. +4229.48 4230.88 "Игорь Лабутин" Ну или для чего-то, что может заменить докер. +4230.88 4234.12 "Игорь Лабутин" Только более, не знаю, легковесное что ли. +4234.12 4251.76 "Анатолий Кулаков" Вот эта возможность запускаться в неком контейнере, который может быть ограничен по ресурсам, который обязательно ограничен по секьюрности и который распространяется в виде какого-то межплатформенного формата, которым вы тоже не должны задумываться, под какую архитектуру его скомпилить. +4251.76 4254.44 "Анатолий Кулаков" Кажется, что это прекрасная замена контейнером. +4254.44 4263.40 "Анатолий Кулаков" Более того, если вы используете Kubernetes, то под Kubernetes уже есть специальное расширение, которое позволяет вам запускать не контейнеры, а именно вот эти Wasm файлы. +4263.40 4269.40 "Анатолий Кулаков" Именно как обычный докер-контейнер, как в обычных ваших приложениях. +4269.40 4270.40 "Игорь Лабутин" Прекрасно. +4270.40 4273.08 "Игорь Лабутин" Ну в общем, посмотрим, куда это все сдвинется. +4273.08 4285.24 "Игорь Лабутин" Кажется, что в ближайшее время, ну я пока не слышал о таком широком распространении этой техники, назовем это так, но действительно потихонечку появляются всякие плагины и поддержка этого дела. +4285.24 4290.96 "Игорь Лабутин" Так что может быть мы и увидим переход с докер-контейнеров на Wasm-контейнеры или как их там назовут. +4290.96 4298.48 "Анатолий Кулаков" А также смотри, можно дойти до операционной системы, которая ничего не умеет, кроме как интерпретировать Wasm, которую запускать Wasm. +4298.48 4313.04 "Анатолий Кулаков" Теперь можно на Wasm записать операционную систему, все модули расширения, все плагины, все программы писать под ней, у тебя автоматически получится, все программы будут изолированными, будут мега-секьюрными, и очень сложно будет под такую штуку писать вирусы, например. +4313.04 4315.36 "Анатолий Кулаков" В общем, эта дорожка может привести нас очень далеко. +4315.36 4319.16 "Игорь Лабутин" Ну посмотрим, как далеко и как быстро она нас туда приведет. +4319.16 4333.64 "Игорь Лабутин" Ну а потом еще в одну тему у нас давно достаточно лежит в бэклоге статья от Маони, главного архитектора Garbage Collector в Дотнете, и наконец-таки мы до нее добрались. +4333.64 4348.92 "Игорь Лабутин" И статья продолжает цикл довольно редких статей от Маони про Garbage Collector и раскрывает, куда же немножко они двигаются, точнее немножко раскрывают, куда они двигаются или планируют двигаться. +4348.92 4375.76 "Игорь Лабутин" Напомню, что в шестом Дотнете появились и в седьмом уже были официально включены так называемые регионы вместо сегментов, то есть Garbage Collector у нас работал раньше на сегментах, это большие куски памяти, там от сотни мегабайт и больше, где внутри них уже каким-то образом распределялись там нулевое первое поколение в эфемерный сегмент или сегменты, а второе поколение в прочий сегмент, но тоже большой. +4375.76 4408.92 "Игорь Лабутин" В какой-то момент было принято решение, что мы переходим на регионы, это уже более маленькие, ну скажем так, блоки памяти по 4 мегабайта или около того, которые можно свободно переиспользовать между разными сегментами, и одна из целей это была возможность декомитить какое-то количество памяти, но также это открывает некоторые возможности более правильной оптимизации, более интересных, так скажем, оптимизаций с точки зрения того, как мы работаем вообще с памятью не только с точки зрения garbage collection, а вообще работаем с памятью. +4408.92 4414.56 "Игорь Лабутин" И одна из оптимизаций как раз таки описана в этой статье, называется она более точные write barriers. +4414.56 4423.32 "Игорь Лабутин" Вы можете подумать, что если мы говорим про барьеры, это про memory model, который мы обсуждали чуть выше, потому что там тоже есть понятие memory barrier, но это не про то. +4423.32 4428.68 "Игорь Лабутин" Это про другую штуку, которая именно в контексте garbage collection. +4428.68 4439.80 "Игорь Лабутин" Представьте себе, что у вас есть некоторое поле в каком-то объекте, назовем его field, и новый объект, object, который вы присваиваете в это поле. +4439.80 4445.72 "Игорь Лабутин" Ну, операция, которую вы делаете очень часто, да, сохраняете ссылку на объект в каком-то поле. +4445.72 4456.04 "Игорь Лабутин" Каждый раз, когда вы выполняете такой код, у вас на самом деле выполняется метод внутри JIT, точнее JIT вызывает метод, называется JIT write barrier. +4456.04 4465.28 "Игорь Лабутин" И исходная цель заключается в том, чтобы, собственно, на основе этого у нас и получается сделать поколенческий garbage collector. +4465.28 4473.28 "Игорь Лабутин" То есть нам нужно знать, какие поколения смотреть, когда мы будем собирать, точнее, какие объекты смотреть, когда мы будем собирать то или иное поколение. +4473.28 4493.84 "Игорь Лабутин" Для этого нужно знать, какие объекты в каком поколении вообще потенциально могли измениться или могли получить, не то чтобы измениться, а получить новых родителей, точнее новых, как это сказать, не родителей, тех, кто их удерживает в памяти, вот удаление новых там, рутов, назовем это так. +4493.84 4513.28 "Игорь Лабутин" Если вы читали книжку "Кондрат Кокос" или слушали какой-то из наших подкастов из древних, где мы хоть что-то описывали про garbage collector, вы, может быть, знаете такой термин как cartable, это, грубо говоря, некоторая такая масочка по всему адресному пространству памяти, где одному битику соответствует некоторое количество килобайт в памяти. +4513.28 4528.84 "Игорь Лабутин" И если вот такое присвоение меняет хоть какой-то объект в этом регионе памяти, то в cartable этот битик проставляется в единичку, это значит, что когда сработает следующий garbage collector, он знает, в какие регионы памяти нужно посмотреть на предмет появившихся новых ссылок на объекты. +4528.84 4533.00 "Игорь Лабутин" Возможно, там ничего не появилось, но может быть, появилось. +4533.00 4541.40 "Игорь Лабутин" Когда .NET был спортирован на Linux, работа в RightBarrier заключалась ровно в том, что там нужно просто проставить этот самый битик. +4541.40 4548.64 "Игорь Лабутин" На самом деле проставлялся байтик, потому что атомарно поставить битик сложно, а байтик, ну как бы, архитектуру поддерживает. +4548.64 4555.84 "Игорь Лабутин" Когда это все спортировали на Linux, в эту функцию gRightBarrier добавили еще одну функциональность. +4555.84 4560.84 "Игорь Лабутин" На Linux дело в том, что нет такой штуки, как PageRightWatch, которая поддерживает винда. +4560.84 4569.24 "Игорь Лабутин" То есть винда умеет идентифицировать процесс о том, что в какую-то страничку памяти что-то записали в этом процессе. +4569.24 4572.84 "Игорь Лабутин" Linux такого не умеет, поэтому теперь RightBarrier занимается примерно тем же самым. +4572.84 4582.34 "Игорь Лабутин" И в случае с сегментами у этой функции RightBarrier была следующая задача. +4582.34 4605.64 "Игорь Лабутин" Во-первых, нужно было понять, пишем ли мы куда-то в heap или может быть мы присваиваем, не знаю, в поле структуры, которое лежит на стейке, и тогда нам не надо ничего добавлять ни в какой CardTable, потому что стейк у нас по дефолту будет, да, крутый, мы его в любом случае будем просматривать при сборке мусора, и тогда ничего писать никуда не надо. +4605.64 4616.40 "Игорь Лабутин" Для того, чтобы понять, есть ли это ссылка в heap, ну ссылка, куда мы пишем, она в heap или не в heap, для сегментов было просто, сегменты они большие, у каждого есть начало и конец. +4616.40 4625.36 "Игорь Лабутин" Особенно для эфемерного сегмента все просто, в Workstation GT он вообще один, и поэтому у вас здесь по сути два адреса, начало сегмента и конец сегмента. +4625.36 4632.28 "Игорь Лабутин" Сравнили адрес, куда мы пишем, с этим двумя и точно поняли, мы попадаем в эфемерный сегмент или не попадаем. +4632.28 4643.48 "Игорь Лабутин" С серверным GC все сложнее, потому что там есть несколько эфемерных сегментов, поэтому там была другая логика, там CardTable он обновлялся вообще безусловно. +4643.48 4648.44 "Игорь Лабутин" Если мы дернули какой-то кусочек памяти и он не на стейке, то мы считаем, что он в heapе и обновляем. +4648.44 4649.44 "Игорь Лабутин" Вот. +4649.44 4674.12 "Игорь Лабутин" В седьмом дотнете вот эти write barriers стали гораздо более точными, потому что у нас есть регионы, региончики они маленькие, они могут быть раскиданы где угодно, между ними могут быть какие-то дырки, и поэтому мы не можем себе позволить просто так считать, что вообще все это heap, потому что регионов много, и, ну, они не такие последовательные, может быть их будет слишком много и они будут раскиданы слишком далеко по виртуальной памяти. +4674.12 4679.28 "Игорь Лабутин" И самое главное, что каждый регион может быть вообще говоря в любом поколении, у нас теперь нету такой строгой последовательности. +4679.28 4690.00 "Игорь Лабутин" Для регионов у нас хранится так называемая generation info map, это некоторая, ну, словарик карта того, в каком поколении соответствует какой регион. +4690.00 4713.84 "Игорь Лабутин" Она хранится достаточно компактно, потому что в отличие от cart table, где по-моему на один бит требовалось около, в смысле один бит описывал по-моему странички то ли по 4, то ли по 16 килобайт, ну не странички, а регионы памяти, здесь у нас один регион это 4 мегабайта как минимум, поэтому количество битов для описания того, в каком поколении этот регион находится, ну, нужно говорить, гораздо меньше. +4713.84 4720.92 "Игорь Лабутин" Майкрософт утверждает, что настолько мало, что в принципе эта информация частенько попадает нормально в кэшброса и там хранится. +4720.92 4735.12 "Игорь Лабутин" Поэтому сейчас, вот, собственно, после этой оптимизации, алгоритм теперь выглядит следующим образом, того, что делает, того, что emitted JIT, по сути, вызов вот этой функции JIT write barrier, и она делает теперь следующую штуку. +4735.12 4745.16 "Игорь Лабутин" Сначала мы берем номер поколения того, куда мы пишем, то есть того адреса, куда мы пишем по вот этому generationInfoMap, это быстрая и простая операция. +4745.16 4750.44 "Игорь Лабутин" Если это нулевое поколение, вообще ничего делать не надо, то есть мы сохранили ссылку на объект в объект нулевого поколения. +4750.44 4758.04 "Игорь Лабутин" И объекты нулевого поколения мы в любом случае будем просматривать при следующей фазе сборки мусора, поэтому ничего дополнительно отмечать не надо. +4758.04 4772.72 "Игорь Лабутин" Если мы, если же это все-таки не объект нулевого поколения, а там первого или второго, то может быть мы сделали следующее, может быть мы свежесозданный объект, который сейчас живет в нулевом поколении, ссылку на него положили в какой-нибудь долго живущий объект. +4772.72 4787.56 "Игорь Лабутин" И это значит, что когда мы будем собирать нулевое поколение, нужно не забыть проверить в качестве рутов еще и те объекты, которые мы затронули в более старших поколениях, потому что иначе, если мы их не посмотрим, то мы не найдем ссылок на этот новый объект в нулевом поколении и его соберем. +4787.56 4788.56 "Игорь Лабутин" Вот плохо. +4788.56 4794.84 "Игорь Лабутин" Поэтому мы берем и выясняем, собственно, поколение того объекта, который мы присваиваем. +4794.84 4799.40 "Игорь Лабутин" Возможно оно нулевое, возможно первое, возможно второе. +4799.40 4807.68 "Игорь Лабутин" Если поколение объекта, который мы присваиваем, больше либо такой же, чем поколение филда, в который мы его присваиваем, то делать ничего не надо. +4807.68 4812.64 "Игорь Лабутин" То есть мы положили ссылку на более старший объект, ссылку в более новый объект. +4812.64 4814.32 "Игорь Лабутин" Ничего страшного, все нормально. +4814.32 4827.12 "Игорь Лабутин" А вот если наоборот, то есть мы сохранили ссылку на объект нулевого поколения в второе поколение, например, и перешли в первое, то тогда нам нужно таки update карт table. +4827.12 4835.96 "Игорь Лабутин" В результате получается из этого алгоритма, что мы гораздо реже обновляем карт тейбл, особенно в случае с сервером ГЦ, потому что раньше мы это делали безусловно. +4835.96 4850.64 "Игорь Лабутин" И в результате, когда у нас наступает фаза сборки мусора, Mark phase, когда мы пробегаемся по всем объектам и размечаем, кого удалить, кого не удалять, эта фаза протекает гораздо быстрее, потому что нам нужно просмотреть гораздо меньше объектов. +4850.64 4853.88 "Игорь Лабутин" Карт тейбл, собственно, используется как источник того, сколько нам посмотреть. +4853.88 4867.24 "Игорь Лабутин" Более того, после некоторых экспериментов Microsoft пришли к выводу, что на самом деле, несмотря на то, что вроде как архитектура у нас атомарно, по сути, мы можем поставить только байт, мы не можем атомарно поставить бит. +4867.24 4876.88 "Игорь Лабутин" Но фактически Microsoft теперь ставит бит, то есть она атомарно ставит байт, изменяя в нем один бит. +4876.88 4889.56 "Игорь Лабутин" То есть технически, если два конкурирующих потока будут проставлять один и тот же байт в карт тейбле, пытаясь поставить разные биты, то кто-то из них победит, а второму придется делать лишние захотные на простановку. +4889.56 4892.04 "Игорь Лабутин" То есть технически может быть больше контеншн. +4892.04 4895.56 "Игорь Лабутин" Но фактически эксперименты показали, что не так все 4895.56 4913.24 None плохо и можно ставить биты. Эксперименты, собственно, показали, что если мы ставим вот этот, с новым right barrier, но который все еще делает байты, ставит байты в карт тейбле, мы получаем ускорение в МГЦ примерно на 18%. -4913.24 4917.44 SPEAKER_01 За счет многих вещей, но вот в том числе за счет этого. -4917.44 4923.40 SPEAKER_01 За счет того, что у нас теперь новый right barrier и он пишет меньше данных, меньше карт тейблов обновляет. -4923.40 4929.36 SPEAKER_01 Если же мы проставляем биты right barrier, то мы улучшаем не на 18%, а аж на 25. -4929.36 4932.84 SPEAKER_01 То есть еще 7% дополнительно добавляем. -4932.84 4940.80 SPEAKER_01 Ну это, конечно, не бесплатно, то есть JIT right barrier, соответственно, тратит чуть больше времени потенциально на это. -4940.80 4946.12 SPEAKER_01 Но рекомендация Microsoft говорит следующее. -4946.12 4957.28 SPEAKER_01 Поскольку мы изменили, ну в общем-то, ключевую, одну из ключевых функций, одну из функций внутрянки, понятное дело, которая используется очень часто, на каждое присвоение вызывается JIT right barrier. -4957.28 4965.08 SPEAKER_01 И вам нужно понять вообще в новом .NET 7, когда вы запустите ваше приложение, посмотреть, нет ли у вас регрессии из-за этого. -4965.08 4966.44 SPEAKER_01 Технически она может быть. -4966.44 4968.04 SPEAKER_01 И рекомендация Microsoft простая. -4968.04 4976.76 SPEAKER_01 Если вы видите, что JIT right barrier в вашем профайлинге вылез больше чем на 1%, это как бы плохо и скорее всего это регрессия. -4976.76 4980.56 SPEAKER_01 Обычно она должна быть меньше чем 1% времени, а по факту еще ниже. -4980.56 4987.84 SPEAKER_01 Если вдруг что-то произошло и это действительно для вас регресс для вашего приложения, ну понятно, сообщите Microsoft. -4987.84 4993.68 SPEAKER_01 Плюс можно откатиться на старое поведение, как обычно с помощью переменной окружения .NET GC right barrier. -4993.68 5001.96 SPEAKER_01 У нее есть 4 значения, но фактически дефолт совпадает с не совсем дефолтом. -5001.96 5007.64 SPEAKER_01 Короче там можно сказать дефолт, можно сказать используйте новую right barrier с битами, это одно и то же. -5007.64 5010.52 SPEAKER_01 Можно выбрать новый right barrier, но все-таки с байтами. -5010.52 5017.24 SPEAKER_01 В этом случае прирост скорости GC будет чуть меньше, потому что карта ABLE будет обновляться побольше. -5017.24 5020.96 SPEAKER_01 Но зато и времени будет тратиться в JIT right barrier поменьше. -5020.96 5030.60 SPEAKER_01 Можно включить вообще старое поведение и использовать вот по старинке все обновлять и вернуться к старому поведению GC с точки зрения right barrier. -5030.60 5039.44 SPEAKER_01 При этом нельзя включить вот тот самый Workstation GC поведение, ну потому что эксперименты показали, что сервер GC тоже нечего работает даже в Workstation сценариях. -5039.44 5045.40 SPEAKER_01 Это пока только начало, у Маони есть еще некоторые планы про то, что делать в будущих релизах. -5045.40 5060.80 SPEAKER_01 Так что скорее всего мы увидим еще больше изменений вокруг Garbage Collector и они возможно будут настолько тонкими, что мы с одной стороны, ну 25% прироста скорости в GC это в принципе неплохо, четверть, это прям круто. -5060.80 5065.08 SPEAKER_01 Сравните с изменениями там Android Startup Time, где было там 6-7%. -5065.08 5070.92 SPEAKER_01 25% это круто, причем в той вещи, которая работает прям всегда в вашем приложении. -5070.92 5079.56 SPEAKER_01 Но с другой стороны, они уже настолько low-level, что иногда довольно сложно разобраться и понять, что же там такое сделали и насколько это зааффектит ваше приложение. -5079.56 5092.72 SPEAKER_01 Так что смотрите внимательно, смотрите внимательно за статьями Маони, потому что, как правило, когда большие изменения выходят, она пишет какую-нибудь полезную статью на эту тему. -5092.72 5101.48 SPEAKER_01 Ну и каждый раз, меняя рантайм, проверяйте, что случилось, что изменилось в вашем приложении и как оно теперь себя ведет. -5101.48 5107.20 SPEAKER_00 Да, наверное, могут быть ситуации, когда это еще будет и хуже себя вести ваше приложение. -5107.20 5141.56 SPEAKER_01 Ну Microsoft старается тестировать, у них огромное количество так называемых и внутренних, и first-tier клиентов, и много кого другого, и рантаймы, они, ну количество превьюшек вкладываемое достаточно великое, поэтому много кто успевает что попробовать, какие-то косяки собрать, но практика показывает, что вот ошибки такого рода, ну в смысле что, изменения в таких компонентах типа GCE или GTA, они иногда стреляют на каких-то ну совсем экстремальных корнер-кейсов, которые может не быть в большинстве проектов, а именно в вашем он попадется. -5141.56 5153.36 SPEAKER_00 Интересный эффект получается, я вот заметил, что почему-то мне кажется, что в последнее время очень много меняется джит и очень часто меняется джит, или это, наверное, только потому, что Маони начал об этом писать, а до этого мы просто не знали, как он меняется. -5153.36 5167.84 SPEAKER_01 Ну Маони про джит, кстати, не пишет, про джит мы максимум узнаем из, ну не знаю, из профильных чатиков, назовем это так, или если действительно появляются какие-то там твиты от Егора Бакатова и так далее, то есть… -5167.84 5176.60 SPEAKER_00 Да, я перепутал, конечно же, про ГЦ. То есть мне почему-то раз уж казалось, что ГЦ вот где-то до дот-нета 3.1 он вообще не двигался никуда и никак. -5176.60 5185.84 SPEAKER_02 Ну возможно как раз там, как говорила Маони, когда мы с ней общались на самом деле, она говорила, что там проводилась некоторая работа по, ну назовем это -5185.84 5195.32 SPEAKER_01 внутреннему рефакторингу, чтобы это не было монолитным ГЦ-ЦПП, да, это было хоть как-то поддерживаемым, потому что там все-таки команда работает, там не она одна работает над этим. -5195.32 5211.04 SPEAKER_01 И во-вторых, я так понимаю, что вся эта затея с регионами и прочее, она требовала некоторой, ну скажем так, серьезной подготовки и обкатки, поэтому, видимо, в релизных вещах мы этого ничего не видели, потому что это все было под капотом пока там в экспериментальных ветках. -5211.04 5218.28 SPEAKER_00 Ну хорошо, как ты думаешь, после такой хардкорного ГЦ перейти к философскому рефакторингу, это нормальная -5218.28 5226.44 SPEAKER_01 тема будет? Да, нормально, мы всегда переходим как-то непонятно куда чего, просто берем следующую тему в списке и про нее рассказываем, поэтому валяй. -5226.44 5230.68 SPEAKER_00 То есть ты думаешь, никакой логики повествования от нас уже слушатели не ждут? -5230.68 5235.56 SPEAKER_01 У нас новостной подкаст, мы это, а теперь новости философии, давай. -5235.56 5249.52 SPEAKER_00 Отлично, ну главный философ в нашей области, это безусловно Марк Симон, хочется посмотреть на еще одну интересную его статью, и в этой статье он рассуждает, а нужно ли просить менеджеров разрешение или времени на рефакторинг. -5249.52 5253.24 SPEAKER_00 Игорь, ты вот как думаешь, на рефакторинг надо время отдельно выпрашивать? -5253.24 5271.56 SPEAKER_01 Выпрашивать, наверное, ну вопрос такой формулировки меня немножко ставит в тупик, если вы видите, что нужно рефакторить, то да, наверное, надо выпрашивать, просто мне непонятна терминология выпрашивать, то есть типа, -5271.56 5286.68 SPEAKER_00 а если не дадут? Обычно у тебя стоит как бы выбор, или сделать фичу супер нужную бизнесу, или все-таки потратить какое-то время от фичи, что-то двинуть, но сделать рефакторинг и это гипотетически улучшит в будущем жизнь неким абстрактным разработчикам. -5286.68 5290.16 SPEAKER_00 А фича, она уже здесь, она как бы полезная, она бабло может принести и все такое. -5290.16 5301.00 SPEAKER_00 И для того, чтобы понять, куда тебе тратить время на фичу или на рефакторинг, ты должен договориться, наверное, с твоим менеджером, чтобы как-то предсказуемо результаты ощущать. -5301.00 5337.36 SPEAKER_01 Мне, видимо, везло с, ну давай назовем это продукт-аунерами, те, кто ответственен за там приоритизацию, у нас всегда была некоторая договоренность, ну условно, где-то формальная, где-то неформальная, про то, что какое-то время, то есть все хотелки по рефакторингу, те или иные, которые возникают у команды, либо просто возникают, либо из-за того, что мы там нашли какую-то проблему в ронтайме, либо просто кто-то прочитал стазию какую-нибудь, или послушал подкаст, они все тоже скидывались в общий баклог и приоритизировались, ну условно говоря, наравне. -5337.36 5348.36 SPEAKER_01 То есть понятно, что приоритет все-таки за бизнес-фичами, но какое-то время у нас всегда находилось практически на всех проектах, где я работал, на то, чтобы хоть какой-то рефакторинг делать в общем порядке. -5348.36 5353.80 SPEAKER_00 Ну вот смотри, с Марком произошла примерно такая же история, рассказываю вкратце. -5353.80 5366.96 SPEAKER_00 В общем, работал он над одним проектом, и там понадобился срочный рефакторинг, там был какой-то технический долг, этот долг был такой большой, концептуальный, и нужно было засесть и отрефакторить. -5366.96 5374.48 SPEAKER_00 Он точно так же обратился к менеджеру, говорит, чувак, надо, а менеджер сказал, да, хорошо, без проблем, раз уж надо, давайте делать. -5374.48 5376.68 SPEAKER_00 И он засел за рефакторинг. -5376.68 5396.00 SPEAKER_00 После того, как через неделю проект все еще не компилировался, менеджер позвал его в сторонку и ласково намекнул, что как бы я немножко неудовлетворен, сложився с текущей ситуацией, потому что как бы бизнес-фичи пилить надо, у нас все стоит, потому что проект развален, ничего не компилируется, и когда это будет работать, непонятно. -5396.00 5397.92 SPEAKER_01 А развален, ясное дело, в мастер-ветке. -5397.92 5410.60 SPEAKER_00 Он не в мастер-ветке развален, но так как эта фича была мега-фундаментальная, она затрагивала практически абсолютно все, поэтому если бы мастер-ветка ушла далеко, то МЕЖ был бы очень-очень сложно. -5410.60 5413.60 SPEAKER_00 И надо разваливать заново мастер. -5413.60 5414.60 SPEAKER_00 Практически. -5414.60 5415.60 SPEAKER_00 Окей. -5415.60 5418.88 SPEAKER_00 Вот, и как раз ситуация очень неприятная. -5418.88 5428.24 SPEAKER_00 Марк сел, подумал, как поступать в будущем и как выйти из подобных ситуаций, и придумал нам вот такую прекрасную статейку, которую мы с вами предлагаем рассмотреть. -5428.24 5439.28 SPEAKER_00 Итак, прежде всего он сделал вывод, что никогда не нужно менеджеров спрашивать разрешения о том, проводить рефакторинг или не проводить рефакторинг. -5439.28 5443.80 SPEAKER_00 Более того, он никогда больше так не делал, то есть не спрашивал менеджеров. -5443.80 5458.88 SPEAKER_00 А самая главная причина, почему он менеджеров не спрашивал, потому что он никогда не вписывался в такие задачи, где нужно было делать рефакторинг очень-очень долго, и в момент этого рефакторинга, возможно, разваливался код. -5458.88 5470.44 SPEAKER_00 В общем, и вот каким образом он пришел к такой позиции, что он избежал таких больших рефакторингов с развалением кода, он пытается нам в статье объяснить. -5470.44 5473.52 SPEAKER_00 Прежде всего, здесь он напоминает о нескольких стратегиях. -5473.52 5478.16 SPEAKER_00 Во-первых, это известный стратегий-душитель, который называется "стрэнглер". -5478.16 5480.96 SPEAKER_00 Это тоже известная такая штука. -5480.96 5489.00 SPEAKER_00 Она помогает вам мигрировать ваш код на новый API, и в то же самое время старый API оставлять на месте. -5489.00 5492.00 SPEAKER_00 То есть параллельно должны работать оба API. -5492.00 5497.76 SPEAKER_00 И постепенно нового кода появляется больше, а старого кода должно появляться меньше. -5497.76 5500.26 SPEAKER_00 И старый код должен постепенно исчезать. -5500.26 5504.00 SPEAKER_00 Таким образом, новый код постепенно душит старый код. -5504.00 5508.44 SPEAKER_00 Также очень полезна в этом случае такая штука, как фичи-флаги. -5508.44 5524.28 SPEAKER_00 Когда вы закрываете какой-то блок исполнения с помощью специального флага, и все ваши нововведения, все ваши изменения, они относятся только к тем блокам, которые закрыты с помощью этого фичи-флага, и старое поведение остается за фичи-флагом. -5524.28 5533.88 SPEAKER_00 Это позволяет вам, вот эти два подхода, позволяет вам беспрепятственно, например, межить в мастер, как уже было предложено выше, и при этом не ломать текущую совместимость. -5533.88 5541.28 SPEAKER_00 То есть, чтобы текущий код, который уже выполнялся, и на который рассчитывает бизнес-фичи, он продолжал исполняться. -5541.28 5544.88 SPEAKER_00 И вы при этом можете постепенно добавлять какие-то новые кусочки. -5544.88 5549.72 SPEAKER_00 То есть, основная идея этого подхода, это в том, что двигаться нужно маленькими шагами. -5549.72 5557.12 SPEAKER_00 И в коем случае не нужно допускать, что вы на неделю уходили в рефакторинг, разваливали там все, и может быть, к какому-то моменту оно как-нибудь заработает. -5557.12 5562.00 SPEAKER_00 Нет, такой подход не работает, работает только подход, когда вы делаете все маленькими шагами. -5562.00 5570.48 SPEAKER_00 Более того, вот этот определенный скил рефакторинга и рефакторинга маленькими шагами – это специальная наука. -5570.48 5572.20 SPEAKER_00 Про нее написано множество книг. -5572.20 5576.00 SPEAKER_00 Нельзя не упомянуть здесь книгу Мартина Фаулера про рефакторинг. -5576.00 5583.92 SPEAKER_00 В общем, это большая наука, у которой есть свои подходы, свои шаблоны проектирования, свои тесты и много-много всего интересного. -5583.92 5589.68 SPEAKER_00 Поэтому если вы чувствуете, что не владеете этой техникой, ее нужно целенаправленно осваивать. -5589.68 5592.80 SPEAKER_00 Не надейтесь на то, что у вас оно может получиться само собой. -5592.80 5598.00 SPEAKER_00 Такие, конечно, самородки тоже есть, но мы за правильный учебный подход. -5598.00 5606.12 SPEAKER_00 Давайте теперь разберем немножко конкретных примерчиков, как это может работать на практике. -5606.12 5610.16 SPEAKER_00 Во-первых, часто задаются вопросом, а когда рефакторить? -5610.16 5623.28 SPEAKER_00 То есть нужно ли откладывать это на конец итерации, нужно ли откладывать это в отдельные таски, чтобы их опять же предлагать на рассмотрение управляющему менеджеру, раундеру или еще каким-то образом. -5623.28 5625.48 SPEAKER_00 То есть когда выделять время для рефакторинга? -5625.48 5626.48 SPEAKER_00 Правильный ответ всегда. -5626.48 5634.36 SPEAKER_00 Рефакторить нужно безотлагательно, ежесекундно, как тогда же, когда вы пишете код. -5634.36 5637.80 SPEAKER_00 Даже существует такое правило, которое звучит следующим образом. -5637.80 5641.16 SPEAKER_00 Сначала сделай, чтобы оно работало, а потом сделай это правильным. -5641.16 5642.96 SPEAKER_00 Что это означает? -5642.96 5651.28 SPEAKER_00 Что сначала вы, когда делаете любую фичу, первым этапом добитесь для того, чтобы она выполняла свои прямые обязанности, на которые вы рассчитываете. -5651.28 5655.92 SPEAKER_00 После того, как вы это сделали, уже нужно переходить ко второй фазе, фазе рефакторинга. -5655.92 5664.44 SPEAKER_00 То есть тогда вы уже причесываете эту штучку, делаете там некрасивый API, может быть пишете документацию, может еще как-нибудь ее облагораживаете. -5664.44 5666.52 SPEAKER_00 В общем четко делите две этих фазы. -5666.52 5675.84 SPEAKER_00 Как только вы начнете делить, вы попробуйте в себя в голове представить, сколько времени будет занимать та или иная фаза. -5675.84 5679.52 SPEAKER_00 Например 50% на разработку, 50% на рефакторинг. -5679.52 5683.96 SPEAKER_00 Ну или вдруг 30% на разработку и 70% на рефакторинг. -5683.96 5685.28 SPEAKER_00 Скорее всего это не так. -5685.28 5694.20 SPEAKER_00 Скорее всего основное время у вас потратится именно на разработку фичи, на проработку идеи, на интеграцию с существующим кодом, на тесты, еще на что-то. -5694.20 5702.72 SPEAKER_00 И обычно на рефакторинг, то есть на конечное причесывание, у вас будет уходить не более 10% всего этого времени. -5702.72 5705.40 SPEAKER_00 Как показала практика Марка, это именно так. -5705.40 5711.36 SPEAKER_00 А если уходит меньше 10%, то здесь нет никакого смысла спрашивать менеджера разрешения. -5711.36 5716.68 SPEAKER_00 Это как раз та штука, которую легче просто сделать в рамках текущей таски. -5716.68 5730.44 SPEAKER_00 Для того, чтобы держать эту планку, чтобы все-таки на рефакторинг уходило немного времени, достаточно первой фазы, которую сделать, чтобы она работала, не пытаться сделать идеальной. -5730.44 5732.48 SPEAKER_00 Ее нужно сделать достаточно хорошей. -5732.48 5737.84 SPEAKER_00 Достаточно хорошей для вашей задачи, для вашего текущего контекста и для вашей текущей интеграции. -5737.84 5745.16 SPEAKER_00 Не пытайтесь применить там сверхновые техники, засунуть сверхновые библиотеки или сделать максимальный перформанс, который только можно. -5745.16 5748.28 SPEAKER_00 Всегда есть какой-то понятный достаточный критерий. -5748.28 5753.08 SPEAKER_00 Вот эти достаточные критерии, их обычно хватает для того, чтобы сделать просто, понятно и хорошо. -5753.08 5764.76 SPEAKER_00 Также для того, чтобы не тратить много времени на рефакторинг, придерживайтесь вполне каких-то банальных вещей, которые можно внедрять уже непосредственно на этапе разработки. -5764.76 5766.56 SPEAKER_00 Например, используйте нормальные имена. -5766.56 5768.84 SPEAKER_00 Не надо откладывать это на какой-то долгий ящик. -5768.84 5770.76 SPEAKER_00 Вам и разрабатывать легче будет. -5770.76 5773.16 SPEAKER_00 Старайтесь удалять дубликаты. -5773.16 5779.52 SPEAKER_00 Обязательно следите за кодсмейлами, за вот этими запахами, которые мы много обсуждали в наших подкастах. -5779.52 5783.64 SPEAKER_00 Держите методы маленькими, чтобы их легко можно было тестировать, управлять ими и так далее. -5783.64 5786.32 SPEAKER_00 И держите маленькой сложность. -5786.32 5791.56 SPEAKER_00 Чем больше сложность, тем у вас будет больше недопониманий и тем больше вам придется рефакторить и разбивать эти методы. -5791.56 5804.04 SPEAKER_00 В общем, придерживаясь таких простых правил, у вас всегда будет часть, которая отвечает за разработку, она всегда будет закончена и более-менее приближена к тому идеалу, к которому вы приступите во второй фазе и на который соответственно вы не потратите много времени. -5804.04 5808.24 SPEAKER_00 Это что касается фичи, которые вы делаете новенькую. -5808.24 5812.24 SPEAKER_00 То есть у вас понятная фича, вы ее сделали, вы ее отрефакторили и все хорошо. -5812.24 5818.04 SPEAKER_00 Но обычно тех долг и, соответственно, большой рефакторинг встречается в фичах, которые уже есть. -5818.04 5824.12 SPEAKER_00 В каких-то старых, больших фичах вам, допустим, нужно туда что-нибудь добавить, что-нибудь изменить. -5824.12 5826.44 SPEAKER_00 Вот как подойти к этому большому куску. -5826.44 5828.56 SPEAKER_00 Здесь есть другое правило. -5828.56 5834.20 SPEAKER_00 Сначала сделайте так, чтобы изменение было легким, а потом легко сделайте это изменение. -5834.20 5836.68 SPEAKER_00 Что это значит? -5836.68 5849.16 SPEAKER_00 Это значит, когда вы приходите в какой-то большой Legacy Code, видите, что вам нужно добавить всего лишь какой-то маленький флажочек, но чтобы это сделать, вам нужно перелопатить огромные какие-то куски интеграции, огромные какие-то непонятные зависимости. -5849.16 5851.64 SPEAKER_00 Разделите, опять же, эту фазу на две части. -5851.64 5860.76 SPEAKER_00 В первой части вы занимаетесь подготовкой вашего кода, существующего, к тому, чтобы он новую фичу воспринял очень легко и просто. -5860.76 5863.80 SPEAKER_00 То есть вы, по сути, рефакторите существующий код. -5863.80 5869.80 SPEAKER_00 И вторая фаза, как только ваш код уже готов к тому, чтобы воспринять эту новую фичу, вы ее очень легко и просто добавляете. -5869.80 5873.32 SPEAKER_00 Что у нас из этого получается? -5873.32 5877.16 SPEAKER_00 Получается, соответственно, что вы не тратите время на рефакторинг. -5877.16 5880.56 SPEAKER_00 Вы, грубо говоря, тратите время на имплементацию этой фичи. -5880.56 5888.44 SPEAKER_00 Но, если бы вы попытались вкорячить эту фичу в старый, страшный, заросший код, вы бы, скорее всего, потратили столько же времени. -5888.44 5891.20 SPEAKER_00 Может быть, это время вылилось бы у вас потом в баги. -5891.20 5894.32 SPEAKER_00 Может быть, это время вылилось бы в сложность написания тестов. -5894.32 5897.44 SPEAKER_00 Но в общем, временем вас заняло бы это столько же. -5897.44 5910.32 SPEAKER_00 Но при этом ваш код остался бы еще более кривым, потому что как только вы в кусок грязи добавляете еще одно ведро грязи, то есть еще одну какую-то новую фичу, у вас появится просто большая куча грязи. -5910.32 5917.64 SPEAKER_00 Вместо того, чтобы сделать тот код, с которым вам пришлось работать, сначала прекрасным и элегантно добавить туда новую фичу. -5917.64 5920.32 SPEAKER_00 Соответственно, после вас код останется прекрасным. -5920.32 5925.12 SPEAKER_00 И следующий человек, который придет добавлять новую фичу, он сделает это уже быстро, красиво. -5925.12 5933.48 SPEAKER_00 Может быть, потратив небольшое, маленькое время на то, чтобы доработать, отрефакторить, улучшить тот код, который оставили после себя вы. -5933.48 5942.28 SPEAKER_00 Основная идея вот этих посылов в том, что когда вы приходите в код и смотрите, что его можно улучшить, то обязательно улучшайте его. -5942.28 5947.04 SPEAKER_00 И тогда после этого все фичи, которые вы будете добавлять, они будут добавляться легко и просто. -5947.04 5950.00 SPEAKER_00 Соответственно, нужно ли здесь спрашивать разрешение в этой ситуации? -5950.00 5957.00 SPEAKER_00 Наверное, не нужно, потому что вы тратите на реализацию фичи столько же времени, сколько вы бы тратили, скорее всего, и без рефакторинга. -5957.00 5961.48 SPEAKER_00 Но при этом еще оставляете за собой чистым и красивым код. -5961.48 5969.48 SPEAKER_00 И больше времени вам для этого не нужно, потому что вы, соответственно, создаете предусловия для реализации фичи. -5969.48 5978.36 SPEAKER_00 Вот таким образом можно разбить весь код на какие-то подходы и весь рефакторинг включать в эти подходы. -5978.36 5981.04 SPEAKER_00 Что мы получаем в итоге? -5981.04 5986.16 SPEAKER_00 Во-первых, правило, что если вдруг вы видите, что код может быть улучшен, то не дожидайтесь ничего. -5986.16 5989.28 SPEAKER_00 Если это маленькое, легенькое изменение, обязательно улучшайте его. -5989.28 5995.28 SPEAKER_00 Никакого смысла ждать, откладывать, или смотреть, или выделять, или просить. -5995.28 5996.28 SPEAKER_00 Смысла никакого нет. -5996.28 6001.60 SPEAKER_00 Как только вы пришли делать какую-то фичу, то у вас уже выделено время на эту фичу. -6001.60 6006.16 SPEAKER_00 И если вы смотрите на этот код, значит, этот код находится где-то рядом с вашей фичей. -6006.16 6012.96 SPEAKER_00 Если займет это вас не больше 5-10 минут, то потратите это время и вокруг этой фичи приведите код в порядок. -6012.96 6017.56 SPEAKER_00 То есть потратите минимальное усилие для того, чтобы улучшить ваш существующий код. -6017.56 6028.56 SPEAKER_00 Если же этот код занимает часы, дни, недели и прочие такие страшные размерности, то применяйте технику, когда мы рефакторим с помощью маленьких шагов. -6028.56 6037.48 SPEAKER_00 И не обязательно спрашивать при этом менеджера, потому что маленькие шаги, они тем и прекрасны, что мы возвращаемся к предыдущему варианту. -6037.48 6042.24 SPEAKER_00 То есть вы выделяете какую-то область и вы можете маленькими шагами ее улучшать. -6042.24 6049.92 SPEAKER_00 Чем больше фич вы делаете вокруг этой грязной области, тем больше шансов, тем больше вероятности у вас эту грязную область почистить, улучшить. -6049.92 6051.92 SPEAKER_00 Точно так же маленькими небольшими шагами. -6051.92 6069.20 SPEAKER_00 Все это будет заливаться в мастер, все это будет интегрироваться, все это будет пропускаться через тесты и все это будет жить, а не накапливаться в отдельной большой ветке на целый месяц непонятных каких-то изменений, которые еще не понятно, как мы будем выливать и к чему не приведут наш релиз. -6069.20 6086.76 SPEAKER_00 Вот такие простые, кажется, на первый момент шаги, но если их попытаться применить в настоящем коде, то мне кажется, что они как раз таки дадут хороший boost, хорошее понимание того, как когда улучшать код и что сделать, чтобы код стал лучше и понятнее, красивее, при этом не развалился. -6086.76 6090.32 SPEAKER_01 И кажется, что здесь нужно уметь вовремя останавливаться. -6090.32 6098.96 SPEAKER_01 То есть понятно, что нам всем очень нравится рефакторить, понятно, что очень хочется сразу весь проект сделать лучше, отформатировать нафиг все файлы под современные кодинг гайдлайны. -6098.96 6125.32 SPEAKER_01 Вот это все, короче, прям, чтобы все было хорошо, но в итоге получаются огромные пул реквесты с кучей изменений, где-то форматирование, где-то рефакторинг, где-то фича, все это одновременно, и поэтому лучше все-таки уметь себя останавливать, то есть улучшить кусочек, закоммитить и продолжить дальше, а не пытаться сделать все и сразу, хотя и очень хочется. -6125.32 6130.88 SPEAKER_00 Да, каждый сам для себя определяет, что такое маленькие шаги, но опять же, чем меньше эти шаги, тем лучше. -6130.88 6132.72 SPEAKER_00 Максимально маленькие, которые вы сможете. -6132.72 6139.72 SPEAKER_01 Мне кажется, если шаги будут выбраны слишком крупные, команда, которая будет ревьюить такие пул реквесты, тоже намекнет о том, что шаги крупноваты. -6139.72 6147.32 SPEAKER_00 Да, ваши коллеги вам обязательно помогут, особенно когда нужно показать, ткнуть носом в ваши ошибки, будьте уверены. -6147.32 6148.76 SPEAKER_01 Да, ну что, пойдем дальше. -6148.76 6158.64 SPEAKER_01 Дальше у нас, как обычно, мы переходим к новостям, которые мы не знали, куда отнести, или они просто очень небольшие, поэтому по чуть-чуть, но о разном. -6158.64 6161.00 SPEAKER_01 То есть продать нельзя, а выбросить жалко, да? -6161.00 6163.60 SPEAKER_01 Ну, типо того, обязательно когда-нибудь пригодится. -6163.60 6164.96 SPEAKER_01 И может быть действительно пригодится. -6164.96 6181.92 SPEAKER_01 Для начала Дэвид Фаулер, он очень редко пишет в блоге, у него есть блог, но он туда пишет крайне редко, зато он мастер всяких полезных твитов и иногда выкладывает интересные гисты на гитхаб. -6181.92 6192.36 SPEAKER_01 В этот раз он выложил интересный, ну он не очень большой, но тем не менее мне показался полезный титр-рет-рет про минимал-АПИ, про телеметрию, про Метеус и вот это вот все. -6192.36 6200.72 SPEAKER_01 Он там показал, как обычно, что, а он фанат, как я понимаю, минимал-АПИ, прям вот, по-моему, самый главный фанат в Майкрософте. -6200.72 6228.32 SPEAKER_01 И как это все легко сконфигурить, как можно просоздавать свои собственные метрики, какие ресурсы, ну в смысле ссылочки почитать в интернете, если вам это интересно, какие-то типсы, как это сделать поудобнее, поправильнее, то есть в общем, если вы смотрите на минимал-АПИ, OpenTelemetry и вот это все, то гляньте твит, он прям, ну серию твитов, они прям действительно, 2-3 скриншота объясняют практически все, как легко это дело подключить. -6228.32 6230.80 SPEAKER_01 Дальше немножко про тулинг. -6230.80 6259.16 SPEAKER_01 Я давно хотел упомянуть, это произошло еще примерно в июле или в августе, зарелизился Illspy 8.0, но это все еще Preview 2, я все ждал, когда же будет релиз, по релизу, к сожалению, пока так и нет, он все еще в состоянии Preview 2, на момент 30 июля, видимо, не хватает сил, не знаю, ресурсов в команде, чтобы довести это до полноценного релиза, либо они ждут, собственно, финального релиза 7.0.net, чтобы окончательно поддержать все фичи C# 11. -6259.16 6274.52 SPEAKER_01 Но тем не менее, какие-то фичи уже поддержаны, поэтому если вам нужен декомпилятор, DotPick, наверное, поддерживает получше, потому что, ну, JetBrains все-таки старается бежать достаточно в ногу с тем, как Microsoft релизит фичи C#. -6274.52 6297.28 SPEAKER_01 Ну а Illspy полегковеснее, Dnspy тоже вариант, я уже рассказывал, что есть, сам Dnspy не развивается, но есть DnspyX, который является форком Dnspy и который развивается, зарелизлен последний раз тоже примерно в июне-июле, так что из таких легковесных декомпилеров пока только эти два более-менее живы. -6297.28 6312.08 SPEAKER_01 И третья новость, она такая больше, я бы ее назвал корпоративной, Microsoft OpenSource Tool, который позволяет генерить то, что называется Software Bill of Materials. -6312.08 6339.28 SPEAKER_01 Мы уже в какой-то момент рассказывали про такую штуку, что сейчас участились, ну скажем так, атаки всякие разные через NuGet и через вот эти всякие вещи, плюс если вы работаете в каком-нибудь большом, не знаю, enterprise, довольно часто становится важным вообще из чего собран ваш продукт, не затащили ли вы туда какую-нибудь странную библиотеку, странной лицензии, ну и так далее. -6339.28 6358.12 SPEAKER_01 А вот как раз-таки Microsoft Tool зарелизился, лежит на GitHub, который позволяет сгенерить по вашему продукту в некотором стандартном SPDX формате описание того, что же затащено в ваш продукт, то есть из чего он состоит. -6358.12 6394.20 SPEAKER_01 Причем поддержан не только .NET, там поддержано огромное количество разных всяких языков и фреймворков, поэтому если вы увлекаетесь, наверное, неправильным глаголом, но вам приходится заниматься какой-то такой работой, посмотрите на этот тул, возможно, это то, что поможет вам более-менее автоматически, например, во время какого-нибудь CI проверять, что старые и детектить изменения в заиспользованных библиотеках и как-то триггерить какие-то дополнительные проверки, либо просто, не знаю, валить билд, пока они не запробят новую библиотеку, если вы почему-то живете в таком окружении. -6394.20 6411.56 SPEAKER_00 Я наткнулся на очень интересный код стили, наверное, код стилей бывает много разных, и все мы с вами сталкивались с ними, в общем, я наткнулся на такие, я бы назвал их более глубокие рекомендации по стилям кодирования, что я имею в виду. -6411.56 6427.20 SPEAKER_00 Очень часто анализаторы Рослиновский и Житбреновский, они заложники той ситуации, что они обязаны поддерживать максимально широкое число клиентов, то есть они, конечно, подсказывают отличные какие-то рекомендации, но они не заходят слишком далеко. -6427.20 6435.12 SPEAKER_00 А мне бы хотелось рекомендаций более высокоуровневых, то есть все-таки забить на какие-то возможности языка, на возможности рантайма, это все. -6435.12 6438.40 SPEAKER_00 Мне бы хотелось рекомендаций, которые ближе именно к самому домену. -6438.40 6447.48 SPEAKER_00 И вот кажется, что я нашел прекрасный сайтик, который такие рекомендации в виде как раз-таки анализаторов и предлагает. -6447.48 6448.96 SPEAKER_00 Ну сейчас я вам для примера расскажу. -6448.96 6455.76 SPEAKER_00 Например, что из методов, обычно, если возвращаете коллекцию, то вам обычно нужно возвращать иммьютабл коллекцию. -6455.76 6462.88 SPEAKER_00 Никакой решайпер вам это не подскажет, потому что, в принципе, никто не запретит вам возвращать хоть массив оттуда, хоть обычный лист. -6462.88 6470.36 SPEAKER_00 Но, насколько я сталкивался, никогда практически не нужно на практике возвращать вам какой-нибудь массив. -6470.36 6474.76 SPEAKER_00 Потому что всегда нужно возвращать ридон для листы, ридон для коллекции, еще что-нибудь такое. -6474.76 6479.80 SPEAKER_00 И вот прекрасно было бы, если бы анализатор вот эти штуки все проверял. -6479.80 6486.60 SPEAKER_00 То есть, естественно, это будет, правда, не в 100% случаев, но опять же, мы покроем 99% случаев, и это прекрасно. -6486.60 6488.08 SPEAKER_00 И вот их хотелось бы иметь. -6488.08 6495.36 SPEAKER_00 Например, этот анализатор может нам проверить, что элементы коллекции и также таски не могут быть нулями. -6495.36 6505.20 SPEAKER_00 То есть, это тоже штука, которая язык не запрещает, так можно делать, но в любой нормальной команде всегда есть договоренность, что так делать нельзя, так делать не надо. -6505.20 6507.60 SPEAKER_00 Это приводит к огромному числу неприятностей. -6507.60 6511.48 SPEAKER_00 И вот есть анализатор, который как раз таки работает на уровне вот этих доменов. -6511.48 6522.36 SPEAKER_00 Также он может проверять домен-специфик value, когда вы используете primitive obsession, то есть, когда вы возвращаете строку, а вам нужен был ISBN, например, уникальный номер книги. -6522.36 6528.96 SPEAKER_00 Он точно так же может вам порекомендовать, типа, оберните это в нормальный домен-специфик primitive и пользуйтесь им. -6528.96 6542.16 SPEAKER_00 Он может проверять, что когда у вас используются магические номеры, то есть, магические числа, которые непонятно, что значат, встречаются где-то посредине кода, и никто никогда не догадается, что это за смещение с левой стороны луны. -6542.16 6550.00 SPEAKER_00 В общем, вот подобные проверки, которые такие уже более домен-специфик, какие-то более на уровне договоренности между командами, вот там есть. -6550.00 6551.24 SPEAKER_00 И их там достаточно много. -6551.24 6556.92 SPEAKER_00 И этот анализатор, он работает именно не на уровне языка, а на уровне принципов. -6556.92 6576.20 SPEAKER_00 Такие как принцип наименьшего удивления, принцип kitted simple stupid, это kiss, всем известный yagna, это you ain't gonna need it, don't repeat yourself, те же самые принципы OOP с правильным наследованием, с раскрытием каких-нибудь protected members. -6576.20 6579.56 SPEAKER_00 Очень много у него есть про DDD, безусловно. -6579.56 6581.96 SPEAKER_00 В общем, вот на таких уровнях, на уровнях принципа. -6581.96 6583.40 SPEAKER_00 И вот это как раз то, чего не хватало. -6583.40 6591.72 SPEAKER_00 Идеи автор сцеплял из Стивена Макконнелла, Джимми Нильсона, Джерми Миллера, Дэвида Фаулера, Роберта Мартина. -6591.72 6600.64 SPEAKER_00 В основном это авторы больших таких монументальных трудов, это книги, книги по архитектуре, по дизайну, и там как раз вот эти все принципы очень тщательно и хорошо разобраны. -6600.64 6603.56 SPEAKER_00 И как раз автор пытался отразить это все в анализаторах. -6603.56 6607.68 SPEAKER_00 Есть, естественно, несколько уровней предупреждений. -6607.68 6612.16 SPEAKER_00 Все они настраиваются с помощью Editor-Config, атрибутов, директив, все как положено. -6612.16 6620.00 SPEAKER_00 Интересно то, что этот сайт, то есть вот эти описания всех вот этих проверок, они переведены на русский. -6620.00 6630.92 SPEAKER_00 Если вдруг как раз эти описания могут быть очень полезны и для джунов, которые только учатся программировать и которые не знают, что, например, плохого в том, что вернули мьютабельную коллекцию из вашего метода. -6630.92 6635.32 SPEAKER_00 Вот, часто джуны не знают хорошо английский и стесняются как бы читать английские сайты. -6635.32 6641.80 SPEAKER_00 Здесь есть отличная переведенная версия, можно прямо на русском давать им ссылочки и там подробно будет написано, что все-таки случилось. -6641.80 6643.84 SPEAKER_00 Ну и, собственно, конечно же есть анализатор. -6643.84 6653.64 SPEAKER_00 То есть вам не нужно сверяться с этими принципами вручную, есть анализатор, который вы можете подключить к вашему CI или к вашей IDE и он будет это все дело проверять. -6653.64 6659.12 SPEAKER_00 В общем, я планирую в ближайшее время попробовать и, может быть, на постояночку такой анализатор к себе подключу. -6659.12 6663.84 SPEAKER_00 Еще я наткнулся на библиотечку. -6663.84 6673.80 SPEAKER_00 Мне нужна была какой-нибудь embedded движок, который может хранить данные и, соответственно, загружать данные прямо в процессе. -6673.80 6677.76 SPEAKER_00 То есть без какой-то отдельной базы данных, а прямо база данных, встроенная в процесс. -6677.76 6683.16 SPEAKER_00 И мне не очень нужен был SQL syntax, иначе я бы, скорее всего, остановился на SQLite. -6683.16 6689.76 SPEAKER_00 Ну и даже когда берешь SQLite, сразу вспоминаешь, что там все работает через interop и как-то не по себе становится. -6689.76 6691.64 SPEAKER_00 Ну, вроде в 21 веке работаем, а тут опять interop. -6691.64 6696.92 SPEAKER_00 В общем, и нагуглил внезапно какую-то интересную библиотечку, которая называется LightDB. -6696.92 6706.24 SPEAKER_00 LightDB – это serverless, соответственно, вам не нужен какой-то выделенный сервак, embedded driver для базы данных, то есть он встраивается непосредственно в ваш процесс. -6706.24 6712.16 SPEAKER_00 Он встраивается в виде одной-единственной DLL, вы ее просто подключаете через зависимость и все, и больше ни о чем не заботитесь. -6712.16 6717.56 SPEAKER_00 Это NoSQL, документ Store, очень похожий по смыслу на MongoDB. -6717.56 6723.44 SPEAKER_00 У него точно такой же примитивный API, ну, примитивный в хорошем смысле этого слова, простой API. -6723.44 6746.76 SPEAKER_00 Он 100% в этой базе данных написан на C#, у него поддерживается полностью ACID транзакции, у него есть хорошие data recovery, допустим, если вдруг случилась ошибка в момент записи данных, там ваше приложение почему-то кильнулось, его убили, есть VOL, все в VOL пишется, потом восстанавливается и соответственно, данные ваши потеряться не должны. -6746.76 6751.60 SPEAKER_00 Встроенное шифрование DES, IS, криптография, все на месте. -6751.60 6757.36 SPEAKER_00 Результат записывается в единственный файл на диске, в базу данных, наподобие SQLite. -6757.36 6765.00 SPEAKER_00 Библиотека полностью open-source, лежит на GitHub, распространяется под MIT лицензией, то есть свободна для всех, даже для коммерческого использования. -6765.00 6772.40 SPEAKER_00 В общем, довольно прекрасно выглядит, много лайков, много коммитов, мне кажется, должна работать хорошо, тоже у меня в планах попробовать. -6772.40 6790.44 SPEAKER_01 Да, я ее как-то видел, мне кажется, но что-то мне no-seq не нужен был особо в таком вот формате, потому что если нужна реализационка, то есть SQLite, собственно, а ее как-то хватало до сих пор. -6790.44 6792.56 SPEAKER_01 Я и в корпусе SQLite, все работает. -6792.56 6795.20 SPEAKER_01 Ну надо будет на заметку себе взять, мало ли пригодится. -6795.20 6798.64 SPEAKER_01 Ну что, все, на сегодня, я думаю, хватит. -6798.64 6801.00 SPEAKER_00 Да, кажется, пора заканчивать. -6801.00 6822.76 SPEAKER_01 Посмотрели мы на очень разные темы сегодня, сначала обсудили три performance темы, про EF7, про ISP.NET Core 7 и про MAUI, тоже о версии 7, потом посмотрели, как вы можете добавить свой собственный HTTP-глагол или HTTP-метод в ISP.NET Core, поддержку либо в minimal API, либо в MVC. -6822.76 6826.68 SPEAKER_01 Не очень понятно, зачем вам это сейчас надо, но если хочется, то почему нет. -6826.68 6835.04 SPEAKER_01 Обсудили DotNet Memory Module, который наконец-таки будет нормально документирован, надеемся, через скором времени. -6835.04 6840.36 SPEAKER_01 Посмотрели, как вы можете запустить DotNet 7 с помощью WASM на Raspberry Pi. -6840.36 6845.68 SPEAKER_01 Узнали, какие новые оптимизации нам принесли регионы в деле нормач-коллектора. -6845.68 6863.08 SPEAKER_01 Обсудили философию Quadrifactory, поговорили про всякие разные мелочи типа OpenTelemetry, ELSPY, LightDB, Coding Guidelines, в общем, тоже такая солянка из техники и философии немножечко, потому что Coding Guidelines, это иногда, мне кажется, больше философия в том числе. -6863.08 6865.88 SPEAKER_01 Хотя и практические моменты, конечно, тоже есть. -6865.88 6867.76 SPEAKER_01 Примерно так, на этом будем заканчивать. -6867.76 6876.08 SPEAKER_00 Да, всем счастливо, слушайте и подписывайтесь, советуйте нас друзьям, распространяйте как только можно, мы будем очень счастливы. -6876.08 6877.08 SPEAKER_00 Всем пока. -6877.08 6877.60 SPEAKER_00 Всем пока. -6877.68 6878.68 None Пока. -6878.76 6879.76 None Пока. -6879.84 6880.84 None Пока. -6880.84 6881.84 None Пока. -6881.84 6882.84 None Пока. -6882.84 6883.84 None Пока. -6883.84 6884.84 None Пока. -6884.84 6885.84 None Пока. +4913.24 4917.44 "Игорь Лабутин" За счет многих вещей, но вот в том числе за счет этого. +4917.44 4923.40 "Игорь Лабутин" За счет того, что у нас теперь новый right barrier и он пишет меньше данных, меньше карт тейблов обновляет. +4923.40 4929.36 "Игорь Лабутин" Если же мы проставляем биты right barrier, то мы улучшаем не на 18%, а аж на 25. +4929.36 4932.84 "Игорь Лабутин" То есть еще 7% дополнительно добавляем. +4932.84 4940.80 "Игорь Лабутин" Ну это, конечно, не бесплатно, то есть JIT right barrier, соответственно, тратит чуть больше времени потенциально на это. +4940.80 4946.12 "Игорь Лабутин" Но рекомендация Microsoft говорит следующее. +4946.12 4957.28 "Игорь Лабутин" Поскольку мы изменили, ну в общем-то, ключевую, одну из ключевых функций, одну из функций внутрянки, понятное дело, которая используется очень часто, на каждое присвоение вызывается JIT right barrier. +4957.28 4965.08 "Игорь Лабутин" И вам нужно понять вообще в новом .NET 7, когда вы запустите ваше приложение, посмотреть, нет ли у вас регрессии из-за этого. +4965.08 4966.44 "Игорь Лабутин" Технически она может быть. +4966.44 4968.04 "Игорь Лабутин" И рекомендация Microsoft простая. +4968.04 4976.76 "Игорь Лабутин" Если вы видите, что JIT right barrier в вашем профайлинге вылез больше чем на 1%, это как бы плохо и скорее всего это регрессия. +4976.76 4980.56 "Игорь Лабутин" Обычно она должна быть меньше чем 1% времени, а по факту еще ниже. +4980.56 4987.84 "Игорь Лабутин" Если вдруг что-то произошло и это действительно для вас регресс для вашего приложения, ну понятно, сообщите Microsoft. +4987.84 4993.68 "Игорь Лабутин" Плюс можно откатиться на старое поведение, как обычно с помощью переменной окружения .NET GC right barrier. +4993.68 5001.96 "Игорь Лабутин" У нее есть 4 значения, но фактически дефолт совпадает с не совсем дефолтом. +5001.96 5007.64 "Игорь Лабутин" Короче там можно сказать дефолт, можно сказать используйте новую right barrier с битами, это одно и то же. +5007.64 5010.52 "Игорь Лабутин" Можно выбрать новый right barrier, но все-таки с байтами. +5010.52 5017.24 "Игорь Лабутин" В этом случае прирост скорости GC будет чуть меньше, потому что карта ABLE будет обновляться побольше. +5017.24 5020.96 "Игорь Лабутин" Но зато и времени будет тратиться в JIT right barrier поменьше. +5020.96 5030.60 "Игорь Лабутин" Можно включить вообще старое поведение и использовать вот по старинке все обновлять и вернуться к старому поведению GC с точки зрения right barrier. +5030.60 5039.44 "Игорь Лабутин" При этом нельзя включить вот тот самый Workstation GC поведение, ну потому что эксперименты показали, что сервер GC тоже нечего работает даже в Workstation сценариях. +5039.44 5045.40 "Игорь Лабутин" Это пока только начало, у Маони есть еще некоторые планы про то, что делать в будущих релизах. +5045.40 5060.80 "Игорь Лабутин" Так что скорее всего мы увидим еще больше изменений вокруг Garbage Collector и они возможно будут настолько тонкими, что мы с одной стороны, ну 25% прироста скорости в GC это в принципе неплохо, четверть, это прям круто. +5060.80 5065.08 "Игорь Лабутин" Сравните с изменениями там Android Startup Time, где было там 6-7%. +5065.08 5070.92 "Игорь Лабутин" 25% это круто, причем в той вещи, которая работает прям всегда в вашем приложении. +5070.92 5079.56 "Игорь Лабутин" Но с другой стороны, они уже настолько low-level, что иногда довольно сложно разобраться и понять, что же там такое сделали и насколько это зааффектит ваше приложение. +5079.56 5092.72 "Игорь Лабутин" Так что смотрите внимательно, смотрите внимательно за статьями Маони, потому что, как правило, когда большие изменения выходят, она пишет какую-нибудь полезную статью на эту тему. +5092.72 5101.48 "Игорь Лабутин" Ну и каждый раз, меняя рантайм, проверяйте, что случилось, что изменилось в вашем приложении и как оно теперь себя ведет. +5101.48 5107.20 "Анатолий Кулаков" Да, наверное, могут быть ситуации, когда это еще будет и хуже себя вести ваше приложение. +5107.20 5141.56 "Игорь Лабутин" Ну Microsoft старается тестировать, у них огромное количество так называемых и внутренних, и first-tier клиентов, и много кого другого, и рантаймы, они, ну количество превьюшек вкладываемое достаточно великое, поэтому много кто успевает что попробовать, какие-то косяки собрать, но практика показывает, что вот ошибки такого рода, ну в смысле что, изменения в таких компонентах типа GCE или GTA, они иногда стреляют на каких-то ну совсем экстремальных корнер-кейсов, которые может не быть в большинстве проектов, а именно в вашем он попадется. +5141.56 5153.36 "Анатолий Кулаков" Интересный эффект получается, я вот заметил, что почему-то мне кажется, что в последнее время очень много меняется джит и очень часто меняется джит, или это, наверное, только потому, что Маони начал об этом писать, а до этого мы просто не знали, как он меняется. +5153.36 5167.84 "Игорь Лабутин" Ну Маони про джит, кстати, не пишет, про джит мы максимум узнаем из, ну не знаю, из профильных чатиков, назовем это так, или если действительно появляются какие-то там твиты от Егора Бакатова и так далее, то есть… +5167.84 5176.60 "Анатолий Кулаков" Да, я перепутал, конечно же, про ГЦ. То есть мне почему-то раз уж казалось, что ГЦ вот где-то до дот-нета 3.1 он вообще не двигался никуда и никак. +5176.60 5185.84 "Игорь Лабутин" Ну возможно как раз там, как говорила Маони, когда мы с ней общались на самом деле, она говорила, что там проводилась некоторая работа по, ну назовем это +5185.84 5195.32 "Игорь Лабутин" внутреннему рефакторингу, чтобы это не было монолитным ГЦ-ЦПП, да, это было хоть как-то поддерживаемым, потому что там все-таки команда работает, там не она одна работает над этим. +5195.32 5211.04 "Игорь Лабутин" И во-вторых, я так понимаю, что вся эта затея с регионами и прочее, она требовала некоторой, ну скажем так, серьезной подготовки и обкатки, поэтому, видимо, в релизных вещах мы этого ничего не видели, потому что это все было под капотом пока там в экспериментальных ветках. +5211.04 5218.28 "Анатолий Кулаков" Ну хорошо, как ты думаешь, после такой хардкорного ГЦ перейти к философскому рефакторингу, это нормальная +5218.28 5226.44 "Игорь Лабутин" тема будет? Да, нормально, мы всегда переходим как-то непонятно куда чего, просто берем следующую тему в списке и про нее рассказываем, поэтому валяй. +5226.44 5230.68 "Анатолий Кулаков" То есть ты думаешь, никакой логики повествования от нас уже слушатели не ждут? +5230.68 5235.56 "Игорь Лабутин" У нас новостной подкаст, мы это, а теперь новости философии, давай. +5235.56 5249.52 "Анатолий Кулаков" Отлично, ну главный философ в нашей области, это безусловно Марк Симон, хочется посмотреть на еще одну интересную его статью, и в этой статье он рассуждает, а нужно ли просить менеджеров разрешение или времени на рефакторинг. +5249.52 5253.24 "Анатолий Кулаков" Игорь, ты вот как думаешь, на рефакторинг надо время отдельно выпрашивать? +5253.24 5271.56 "Игорь Лабутин" Выпрашивать, наверное, ну вопрос такой формулировки меня немножко ставит в тупик, если вы видите, что нужно рефакторить, то да, наверное, надо выпрашивать, просто мне непонятна терминология выпрашивать, то есть типа, +5271.56 5286.68 "Анатолий Кулаков" а если не дадут? Обычно у тебя стоит как бы выбор, или сделать фичу супер нужную бизнесу, или все-таки потратить какое-то время от фичи, что-то двинуть, но сделать рефакторинг и это гипотетически улучшит в будущем жизнь неким абстрактным разработчикам. +5286.68 5290.16 "Анатолий Кулаков" А фича, она уже здесь, она как бы полезная, она бабло может принести и все такое. +5290.16 5301.00 "Анатолий Кулаков" И для того, чтобы понять, куда тебе тратить время на фичу или на рефакторинг, ты должен договориться, наверное, с твоим менеджером, чтобы как-то предсказуемо результаты ощущать. +5301.00 5337.36 "Игорь Лабутин" Мне, видимо, везло с, ну давай назовем это продукт-аунерами, те, кто ответственен за там приоритизацию, у нас всегда была некоторая договоренность, ну условно, где-то формальная, где-то неформальная, про то, что какое-то время, то есть все хотелки по рефакторингу, те или иные, которые возникают у команды, либо просто возникают, либо из-за того, что мы там нашли какую-то проблему в ронтайме, либо просто кто-то прочитал стазию какую-нибудь, или послушал подкаст, они все тоже скидывались в общий баклог и приоритизировались, ну условно говоря, наравне. +5337.36 5348.36 "Игорь Лабутин" То есть понятно, что приоритет все-таки за бизнес-фичами, но какое-то время у нас всегда находилось практически на всех проектах, где я работал, на то, чтобы хоть какой-то рефакторинг делать в общем порядке. +5348.36 5353.80 "Анатолий Кулаков" Ну вот смотри, с Марком произошла примерно такая же история, рассказываю вкратце. +5353.80 5366.96 "Анатолий Кулаков" В общем, работал он над одним проектом, и там понадобился срочный рефакторинг, там был какой-то технический долг, этот долг был такой большой, концептуальный, и нужно было засесть и отрефакторить. +5366.96 5374.48 "Анатолий Кулаков" Он точно так же обратился к менеджеру, говорит, чувак, надо, а менеджер сказал, да, хорошо, без проблем, раз уж надо, давайте делать. +5374.48 5376.68 "Анатолий Кулаков" И он засел за рефакторинг. +5376.68 5396.00 "Анатолий Кулаков" После того, как через неделю проект все еще не компилировался, менеджер позвал его в сторонку и ласково намекнул, что как бы я немножко неудовлетворен, сложився с текущей ситуацией, потому что как бы бизнес-фичи пилить надо, у нас все стоит, потому что проект развален, ничего не компилируется, и когда это будет работать, непонятно. +5396.00 5397.92 "Игорь Лабутин" А развален, ясное дело, в мастер-ветке. +5397.92 5410.60 "Анатолий Кулаков" Он не в мастер-ветке развален, но так как эта фича была мега-фундаментальная, она затрагивала практически абсолютно все, поэтому если бы мастер-ветка ушла далеко, то МЕЖ был бы очень-очень сложно. +5410.60 5413.60 "Анатолий Кулаков" И надо разваливать заново мастер. +5413.60 5414.60 "Анатолий Кулаков" Практически. +5414.60 5415.60 "Анатолий Кулаков" Окей. +5415.60 5418.88 "Анатолий Кулаков" Вот, и как раз ситуация очень неприятная. +5418.88 5428.24 "Анатолий Кулаков" Марк сел, подумал, как поступать в будущем и как выйти из подобных ситуаций, и придумал нам вот такую прекрасную статейку, которую мы с вами предлагаем рассмотреть. +5428.24 5439.28 "Анатолий Кулаков" Итак, прежде всего он сделал вывод, что никогда не нужно менеджеров спрашивать разрешения о том, проводить рефакторинг или не проводить рефакторинг. +5439.28 5443.80 "Анатолий Кулаков" Более того, он никогда больше так не делал, то есть не спрашивал менеджеров. +5443.80 5458.88 "Анатолий Кулаков" А самая главная причина, почему он менеджеров не спрашивал, потому что он никогда не вписывался в такие задачи, где нужно было делать рефакторинг очень-очень долго, и в момент этого рефакторинга, возможно, разваливался код. +5458.88 5470.44 "Анатолий Кулаков" В общем, и вот каким образом он пришел к такой позиции, что он избежал таких больших рефакторингов с развалением кода, он пытается нам в статье объяснить. +5470.44 5473.52 "Анатолий Кулаков" Прежде всего, здесь он напоминает о нескольких стратегиях. +5473.52 5478.16 "Анатолий Кулаков" Во-первых, это известный стратегий-душитель, который называется "стрэнглер". +5478.16 5480.96 "Анатолий Кулаков" Это тоже известная такая штука. +5480.96 5489.00 "Анатолий Кулаков" Она помогает вам мигрировать ваш код на новый API, и в то же самое время старый API оставлять на месте. +5489.00 5492.00 "Анатолий Кулаков" То есть параллельно должны работать оба API. +5492.00 5497.76 "Анатолий Кулаков" И постепенно нового кода появляется больше, а старого кода должно появляться меньше. +5497.76 5500.26 "Анатолий Кулаков" И старый код должен постепенно исчезать. +5500.26 5504.00 "Анатолий Кулаков" Таким образом, новый код постепенно душит старый код. +5504.00 5508.44 "Анатолий Кулаков" Также очень полезна в этом случае такая штука, как фичи-флаги. +5508.44 5524.28 "Анатолий Кулаков" Когда вы закрываете какой-то блок исполнения с помощью специального флага, и все ваши нововведения, все ваши изменения, они относятся только к тем блокам, которые закрыты с помощью этого фичи-флага, и старое поведение остается за фичи-флагом. +5524.28 5533.88 "Анатолий Кулаков" Это позволяет вам, вот эти два подхода, позволяет вам беспрепятственно, например, межить в мастер, как уже было предложено выше, и при этом не ломать текущую совместимость. +5533.88 5541.28 "Анатолий Кулаков" То есть, чтобы текущий код, который уже выполнялся, и на который рассчитывает бизнес-фичи, он продолжал исполняться. +5541.28 5544.88 "Анатолий Кулаков" И вы при этом можете постепенно добавлять какие-то новые кусочки. +5544.88 5549.72 "Анатолий Кулаков" То есть, основная идея этого подхода, это в том, что двигаться нужно маленькими шагами. +5549.72 5557.12 "Анатолий Кулаков" И в коем случае не нужно допускать, что вы на неделю уходили в рефакторинг, разваливали там все, и может быть, к какому-то моменту оно как-нибудь заработает. +5557.12 5562.00 "Анатолий Кулаков" Нет, такой подход не работает, работает только подход, когда вы делаете все маленькими шагами. +5562.00 5570.48 "Анатолий Кулаков" Более того, вот этот определенный скил рефакторинга и рефакторинга маленькими шагами – это специальная наука. +5570.48 5572.20 "Анатолий Кулаков" Про нее написано множество книг. +5572.20 5576.00 "Анатолий Кулаков" Нельзя не упомянуть здесь книгу Мартина Фаулера про рефакторинг. +5576.00 5583.92 "Анатолий Кулаков" В общем, это большая наука, у которой есть свои подходы, свои шаблоны проектирования, свои тесты и много-много всего интересного. +5583.92 5589.68 "Анатолий Кулаков" Поэтому если вы чувствуете, что не владеете этой техникой, ее нужно целенаправленно осваивать. +5589.68 5592.80 "Анатолий Кулаков" Не надейтесь на то, что у вас оно может получиться само собой. +5592.80 5598.00 "Анатолий Кулаков" Такие, конечно, самородки тоже есть, но мы за правильный учебный подход. +5598.00 5606.12 "Анатолий Кулаков" Давайте теперь разберем немножко конкретных примерчиков, как это может работать на практике. +5606.12 5610.16 "Анатолий Кулаков" Во-первых, часто задаются вопросом, а когда рефакторить? +5610.16 5623.28 "Анатолий Кулаков" То есть нужно ли откладывать это на конец итерации, нужно ли откладывать это в отдельные таски, чтобы их опять же предлагать на рассмотрение управляющему менеджеру, раундеру или еще каким-то образом. +5623.28 5625.48 "Анатолий Кулаков" То есть когда выделять время для рефакторинга? +5625.48 5626.48 "Анатолий Кулаков" Правильный ответ всегда. +5626.48 5634.36 "Анатолий Кулаков" Рефакторить нужно безотлагательно, ежесекундно, как тогда же, когда вы пишете код. +5634.36 5637.80 "Анатолий Кулаков" Даже существует такое правило, которое звучит следующим образом. +5637.80 5641.16 "Анатолий Кулаков" Сначала сделай, чтобы оно работало, а потом сделай это правильным. +5641.16 5642.96 "Анатолий Кулаков" Что это означает? +5642.96 5651.28 "Анатолий Кулаков" Что сначала вы, когда делаете любую фичу, первым этапом добитесь для того, чтобы она выполняла свои прямые обязанности, на которые вы рассчитываете. +5651.28 5655.92 "Анатолий Кулаков" После того, как вы это сделали, уже нужно переходить ко второй фазе, фазе рефакторинга. +5655.92 5664.44 "Анатолий Кулаков" То есть тогда вы уже причесываете эту штучку, делаете там некрасивый API, может быть пишете документацию, может еще как-нибудь ее облагораживаете. +5664.44 5666.52 "Анатолий Кулаков" В общем четко делите две этих фазы. +5666.52 5675.84 "Анатолий Кулаков" Как только вы начнете делить, вы попробуйте в себя в голове представить, сколько времени будет занимать та или иная фаза. +5675.84 5679.52 "Анатолий Кулаков" Например 50% на разработку, 50% на рефакторинг. +5679.52 5683.96 "Анатолий Кулаков" Ну или вдруг 30% на разработку и 70% на рефакторинг. +5683.96 5685.28 "Анатолий Кулаков" Скорее всего это не так. +5685.28 5694.20 "Анатолий Кулаков" Скорее всего основное время у вас потратится именно на разработку фичи, на проработку идеи, на интеграцию с существующим кодом, на тесты, еще на что-то. +5694.20 5702.72 "Анатолий Кулаков" И обычно на рефакторинг, то есть на конечное причесывание, у вас будет уходить не более 10% всего этого времени. +5702.72 5705.40 "Анатолий Кулаков" Как показала практика Марка, это именно так. +5705.40 5711.36 "Анатолий Кулаков" А если уходит меньше 10%, то здесь нет никакого смысла спрашивать менеджера разрешения. +5711.36 5716.68 "Анатолий Кулаков" Это как раз та штука, которую легче просто сделать в рамках текущей таски. +5716.68 5730.44 "Анатолий Кулаков" Для того, чтобы держать эту планку, чтобы все-таки на рефакторинг уходило немного времени, достаточно первой фазы, которую сделать, чтобы она работала, не пытаться сделать идеальной. +5730.44 5732.48 "Анатолий Кулаков" Ее нужно сделать достаточно хорошей. +5732.48 5737.84 "Анатолий Кулаков" Достаточно хорошей для вашей задачи, для вашего текущего контекста и для вашей текущей интеграции. +5737.84 5745.16 "Анатолий Кулаков" Не пытайтесь применить там сверхновые техники, засунуть сверхновые библиотеки или сделать максимальный перформанс, который только можно. +5745.16 5748.28 "Анатолий Кулаков" Всегда есть какой-то понятный достаточный критерий. +5748.28 5753.08 "Анатолий Кулаков" Вот эти достаточные критерии, их обычно хватает для того, чтобы сделать просто, понятно и хорошо. +5753.08 5764.76 "Анатолий Кулаков" Также для того, чтобы не тратить много времени на рефакторинг, придерживайтесь вполне каких-то банальных вещей, которые можно внедрять уже непосредственно на этапе разработки. +5764.76 5766.56 "Анатолий Кулаков" Например, используйте нормальные имена. +5766.56 5768.84 "Анатолий Кулаков" Не надо откладывать это на какой-то долгий ящик. +5768.84 5770.76 "Анатолий Кулаков" Вам и разрабатывать легче будет. +5770.76 5773.16 "Анатолий Кулаков" Старайтесь удалять дубликаты. +5773.16 5779.52 "Анатолий Кулаков" Обязательно следите за кодсмейлами, за вот этими запахами, которые мы много обсуждали в наших подкастах. +5779.52 5783.64 "Анатолий Кулаков" Держите методы маленькими, чтобы их легко можно было тестировать, управлять ими и так далее. +5783.64 5786.32 "Анатолий Кулаков" И держите маленькой сложность. +5786.32 5791.56 "Анатолий Кулаков" Чем больше сложность, тем у вас будет больше недопониманий и тем больше вам придется рефакторить и разбивать эти методы. +5791.56 5804.04 "Анатолий Кулаков" В общем, придерживаясь таких простых правил, у вас всегда будет часть, которая отвечает за разработку, она всегда будет закончена и более-менее приближена к тому идеалу, к которому вы приступите во второй фазе и на который соответственно вы не потратите много времени. +5804.04 5808.24 "Анатолий Кулаков" Это что касается фичи, которые вы делаете новенькую. +5808.24 5812.24 "Анатолий Кулаков" То есть у вас понятная фича, вы ее сделали, вы ее отрефакторили и все хорошо. +5812.24 5818.04 "Анатолий Кулаков" Но обычно тех долг и, соответственно, большой рефакторинг встречается в фичах, которые уже есть. +5818.04 5824.12 "Анатолий Кулаков" В каких-то старых, больших фичах вам, допустим, нужно туда что-нибудь добавить, что-нибудь изменить. +5824.12 5826.44 "Анатолий Кулаков" Вот как подойти к этому большому куску. +5826.44 5828.56 "Анатолий Кулаков" Здесь есть другое правило. +5828.56 5834.20 "Анатолий Кулаков" Сначала сделайте так, чтобы изменение было легким, а потом легко сделайте это изменение. +5834.20 5836.68 "Анатолий Кулаков" Что это значит? +5836.68 5849.16 "Анатолий Кулаков" Это значит, когда вы приходите в какой-то большой Legacy Code, видите, что вам нужно добавить всего лишь какой-то маленький флажочек, но чтобы это сделать, вам нужно перелопатить огромные какие-то куски интеграции, огромные какие-то непонятные зависимости. +5849.16 5851.64 "Анатолий Кулаков" Разделите, опять же, эту фазу на две части. +5851.64 5860.76 "Анатолий Кулаков" В первой части вы занимаетесь подготовкой вашего кода, существующего, к тому, чтобы он новую фичу воспринял очень легко и просто. +5860.76 5863.80 "Анатолий Кулаков" То есть вы, по сути, рефакторите существующий код. +5863.80 5869.80 "Анатолий Кулаков" И вторая фаза, как только ваш код уже готов к тому, чтобы воспринять эту новую фичу, вы ее очень легко и просто добавляете. +5869.80 5873.32 "Анатолий Кулаков" Что у нас из этого получается? +5873.32 5877.16 "Анатолий Кулаков" Получается, соответственно, что вы не тратите время на рефакторинг. +5877.16 5880.56 "Анатолий Кулаков" Вы, грубо говоря, тратите время на имплементацию этой фичи. +5880.56 5888.44 "Анатолий Кулаков" Но, если бы вы попытались вкорячить эту фичу в старый, страшный, заросший код, вы бы, скорее всего, потратили столько же времени. +5888.44 5891.20 "Анатолий Кулаков" Может быть, это время вылилось бы у вас потом в баги. +5891.20 5894.32 "Анатолий Кулаков" Может быть, это время вылилось бы в сложность написания тестов. +5894.32 5897.44 "Анатолий Кулаков" Но в общем, временем вас заняло бы это столько же. +5897.44 5910.32 "Анатолий Кулаков" Но при этом ваш код остался бы еще более кривым, потому что как только вы в кусок грязи добавляете еще одно ведро грязи, то есть еще одну какую-то новую фичу, у вас появится просто большая куча грязи. +5910.32 5917.64 "Анатолий Кулаков" Вместо того, чтобы сделать тот код, с которым вам пришлось работать, сначала прекрасным и элегантно добавить туда новую фичу. +5917.64 5920.32 "Анатолий Кулаков" Соответственно, после вас код останется прекрасным. +5920.32 5925.12 "Анатолий Кулаков" И следующий человек, который придет добавлять новую фичу, он сделает это уже быстро, красиво. +5925.12 5933.48 "Анатолий Кулаков" Может быть, потратив небольшое, маленькое время на то, чтобы доработать, отрефакторить, улучшить тот код, который оставили после себя вы. +5933.48 5942.28 "Анатолий Кулаков" Основная идея вот этих посылов в том, что когда вы приходите в код и смотрите, что его можно улучшить, то обязательно улучшайте его. +5942.28 5947.04 "Анатолий Кулаков" И тогда после этого все фичи, которые вы будете добавлять, они будут добавляться легко и просто. +5947.04 5950.00 "Анатолий Кулаков" Соответственно, нужно ли здесь спрашивать разрешение в этой ситуации? +5950.00 5957.00 "Анатолий Кулаков" Наверное, не нужно, потому что вы тратите на реализацию фичи столько же времени, сколько вы бы тратили, скорее всего, и без рефакторинга. +5957.00 5961.48 "Анатолий Кулаков" Но при этом еще оставляете за собой чистым и красивым код. +5961.48 5969.48 "Анатолий Кулаков" И больше времени вам для этого не нужно, потому что вы, соответственно, создаете предусловия для реализации фичи. +5969.48 5978.36 "Анатолий Кулаков" Вот таким образом можно разбить весь код на какие-то подходы и весь рефакторинг включать в эти подходы. +5978.36 5981.04 "Анатолий Кулаков" Что мы получаем в итоге? +5981.04 5986.16 "Анатолий Кулаков" Во-первых, правило, что если вдруг вы видите, что код может быть улучшен, то не дожидайтесь ничего. +5986.16 5989.28 "Анатолий Кулаков" Если это маленькое, легенькое изменение, обязательно улучшайте его. +5989.28 5995.28 "Анатолий Кулаков" Никакого смысла ждать, откладывать, или смотреть, или выделять, или просить. +5995.28 5996.28 "Анатолий Кулаков" Смысла никакого нет. +5996.28 6001.60 "Анатолий Кулаков" Как только вы пришли делать какую-то фичу, то у вас уже выделено время на эту фичу. +6001.60 6006.16 "Анатолий Кулаков" И если вы смотрите на этот код, значит, этот код находится где-то рядом с вашей фичей. +6006.16 6012.96 "Анатолий Кулаков" Если займет это вас не больше 5-10 минут, то потратите это время и вокруг этой фичи приведите код в порядок. +6012.96 6017.56 "Анатолий Кулаков" То есть потратите минимальное усилие для того, чтобы улучшить ваш существующий код. +6017.56 6028.56 "Анатолий Кулаков" Если же этот код занимает часы, дни, недели и прочие такие страшные размерности, то применяйте технику, когда мы рефакторим с помощью маленьких шагов. +6028.56 6037.48 "Анатолий Кулаков" И не обязательно спрашивать при этом менеджера, потому что маленькие шаги, они тем и прекрасны, что мы возвращаемся к предыдущему варианту. +6037.48 6042.24 "Анатолий Кулаков" То есть вы выделяете какую-то область и вы можете маленькими шагами ее улучшать. +6042.24 6049.92 "Анатолий Кулаков" Чем больше фич вы делаете вокруг этой грязной области, тем больше шансов, тем больше вероятности у вас эту грязную область почистить, улучшить. +6049.92 6051.92 "Анатолий Кулаков" Точно так же маленькими небольшими шагами. +6051.92 6069.20 "Анатолий Кулаков" Все это будет заливаться в мастер, все это будет интегрироваться, все это будет пропускаться через тесты и все это будет жить, а не накапливаться в отдельной большой ветке на целый месяц непонятных каких-то изменений, которые еще не понятно, как мы будем выливать и к чему не приведут наш релиз. +6069.20 6086.76 "Анатолий Кулаков" Вот такие простые, кажется, на первый момент шаги, но если их попытаться применить в настоящем коде, то мне кажется, что они как раз таки дадут хороший boost, хорошее понимание того, как когда улучшать код и что сделать, чтобы код стал лучше и понятнее, красивее, при этом не развалился. +6086.76 6090.32 "Игорь Лабутин" И кажется, что здесь нужно уметь вовремя останавливаться. +6090.32 6098.96 "Игорь Лабутин" То есть понятно, что нам всем очень нравится рефакторить, понятно, что очень хочется сразу весь проект сделать лучше, отформатировать нафиг все файлы под современные кодинг гайдлайны. +6098.96 6125.32 "Игорь Лабутин" Вот это все, короче, прям, чтобы все было хорошо, но в итоге получаются огромные пул реквесты с кучей изменений, где-то форматирование, где-то рефакторинг, где-то фича, все это одновременно, и поэтому лучше все-таки уметь себя останавливать, то есть улучшить кусочек, закоммитить и продолжить дальше, а не пытаться сделать все и сразу, хотя и очень хочется. +6125.32 6130.88 "Анатолий Кулаков" Да, каждый сам для себя определяет, что такое маленькие шаги, но опять же, чем меньше эти шаги, тем лучше. +6130.88 6132.72 "Анатолий Кулаков" Максимально маленькие, которые вы сможете. +6132.72 6139.72 "Игорь Лабутин" Мне кажется, если шаги будут выбраны слишком крупные, команда, которая будет ревьюить такие пул реквесты, тоже намекнет о том, что шаги крупноваты. +6139.72 6147.32 "Анатолий Кулаков" Да, ваши коллеги вам обязательно помогут, особенно когда нужно показать, ткнуть носом в ваши ошибки, будьте уверены. +6147.32 6148.76 "Игорь Лабутин" Да, ну что, пойдем дальше. +6148.76 6158.64 "Игорь Лабутин" Дальше у нас, как обычно, мы переходим к новостям, которые мы не знали, куда отнести, или они просто очень небольшие, поэтому по чуть-чуть, но о разном. +6158.64 6161.00 "Игорь Лабутин" То есть продать нельзя, а выбросить жалко, да? +6161.00 6163.60 "Игорь Лабутин" Ну, типо того, обязательно когда-нибудь пригодится. +6163.60 6164.96 "Игорь Лабутин" И может быть действительно пригодится. +6164.96 6181.92 "Игорь Лабутин" Для начала Дэвид Фаулер, он очень редко пишет в блоге, у него есть блог, но он туда пишет крайне редко, зато он мастер всяких полезных твитов и иногда выкладывает интересные гисты на гитхаб. +6181.92 6192.36 "Игорь Лабутин" В этот раз он выложил интересный, ну он не очень большой, но тем не менее мне показался полезный титр-рет-рет про минимал-АПИ, про телеметрию, про Метеус и вот это вот все. +6192.36 6200.72 "Игорь Лабутин" Он там показал, как обычно, что, а он фанат, как я понимаю, минимал-АПИ, прям вот, по-моему, самый главный фанат в Майкрософте. +6200.72 6228.32 "Игорь Лабутин" И как это все легко сконфигурить, как можно просоздавать свои собственные метрики, какие ресурсы, ну в смысле ссылочки почитать в интернете, если вам это интересно, какие-то типсы, как это сделать поудобнее, поправильнее, то есть в общем, если вы смотрите на минимал-АПИ, OpenTelemetry и вот это все, то гляньте твит, он прям, ну серию твитов, они прям действительно, 2-3 скриншота объясняют практически все, как легко это дело подключить. +6228.32 6230.80 "Игорь Лабутин" Дальше немножко про тулинг. +6230.80 6259.16 "Игорь Лабутин" Я давно хотел упомянуть, это произошло еще примерно в июле или в августе, зарелизился Illspy 8.0, но это все еще Preview 2, я все ждал, когда же будет релиз, по релизу, к сожалению, пока так и нет, он все еще в состоянии Preview 2, на момент 30 июля, видимо, не хватает сил, не знаю, ресурсов в команде, чтобы довести это до полноценного релиза, либо они ждут, собственно, финального релиза 7.0.net, чтобы окончательно поддержать все фичи C# 11. +6259.16 6274.52 "Игорь Лабутин" Но тем не менее, какие-то фичи уже поддержаны, поэтому если вам нужен декомпилятор, DotPick, наверное, поддерживает получше, потому что, ну, JetBrains все-таки старается бежать достаточно в ногу с тем, как Microsoft релизит фичи C#. +6274.52 6297.28 "Игорь Лабутин" Ну а Illspy полегковеснее, Dnspy тоже вариант, я уже рассказывал, что есть, сам Dnspy не развивается, но есть DnspyX, который является форком Dnspy и который развивается, зарелизлен последний раз тоже примерно в июне-июле, так что из таких легковесных декомпилеров пока только эти два более-менее живы. +6297.28 6312.08 "Игорь Лабутин" И третья новость, она такая больше, я бы ее назвал корпоративной, Microsoft OpenSource Tool, который позволяет генерить то, что называется Software Bill of Materials. +6312.08 6339.28 "Игорь Лабутин" Мы уже в какой-то момент рассказывали про такую штуку, что сейчас участились, ну скажем так, атаки всякие разные через NuGet и через вот эти всякие вещи, плюс если вы работаете в каком-нибудь большом, не знаю, enterprise, довольно часто становится важным вообще из чего собран ваш продукт, не затащили ли вы туда какую-нибудь странную библиотеку, странной лицензии, ну и так далее. +6339.28 6358.12 "Игорь Лабутин" А вот как раз-таки Microsoft Tool зарелизился, лежит на GitHub, который позволяет сгенерить по вашему продукту в некотором стандартном SPDX формате описание того, что же затащено в ваш продукт, то есть из чего он состоит. +6358.12 6394.20 "Игорь Лабутин" Причем поддержан не только .NET, там поддержано огромное количество разных всяких языков и фреймворков, поэтому если вы увлекаетесь, наверное, неправильным глаголом, но вам приходится заниматься какой-то такой работой, посмотрите на этот тул, возможно, это то, что поможет вам более-менее автоматически, например, во время какого-нибудь CI проверять, что старые и детектить изменения в заиспользованных библиотеках и как-то триггерить какие-то дополнительные проверки, либо просто, не знаю, валить билд, пока они не запробят новую библиотеку, если вы почему-то живете в таком окружении. +6394.20 6411.56 "Анатолий Кулаков" Я наткнулся на очень интересный код стили, наверное, код стилей бывает много разных, и все мы с вами сталкивались с ними, в общем, я наткнулся на такие, я бы назвал их более глубокие рекомендации по стилям кодирования, что я имею в виду. +6411.56 6427.20 "Анатолий Кулаков" Очень часто анализаторы Рослиновский и Житбреновский, они заложники той ситуации, что они обязаны поддерживать максимально широкое число клиентов, то есть они, конечно, подсказывают отличные какие-то рекомендации, но они не заходят слишком далеко. +6427.20 6435.12 "Анатолий Кулаков" А мне бы хотелось рекомендаций более высокоуровневых, то есть все-таки забить на какие-то возможности языка, на возможности рантайма, это все. +6435.12 6438.40 "Анатолий Кулаков" Мне бы хотелось рекомендаций, которые ближе именно к самому домену. +6438.40 6447.48 "Анатолий Кулаков" И вот кажется, что я нашел прекрасный сайтик, который такие рекомендации в виде как раз-таки анализаторов и предлагает. +6447.48 6448.96 "Анатолий Кулаков" Ну сейчас я вам для примера расскажу. +6448.96 6455.76 "Анатолий Кулаков" Например, что из методов, обычно, если возвращаете коллекцию, то вам обычно нужно возвращать иммьютабл коллекцию. +6455.76 6462.88 "Анатолий Кулаков" Никакой решайпер вам это не подскажет, потому что, в принципе, никто не запретит вам возвращать хоть массив оттуда, хоть обычный лист. +6462.88 6470.36 "Анатолий Кулаков" Но, насколько я сталкивался, никогда практически не нужно на практике возвращать вам какой-нибудь массив. +6470.36 6474.76 "Анатолий Кулаков" Потому что всегда нужно возвращать ридон для листы, ридон для коллекции, еще что-нибудь такое. +6474.76 6479.80 "Анатолий Кулаков" И вот прекрасно было бы, если бы анализатор вот эти штуки все проверял. +6479.80 6486.60 "Анатолий Кулаков" То есть, естественно, это будет, правда, не в 100% случаев, но опять же, мы покроем 99% случаев, и это прекрасно. +6486.60 6488.08 "Анатолий Кулаков" И вот их хотелось бы иметь. +6488.08 6495.36 "Анатолий Кулаков" Например, этот анализатор может нам проверить, что элементы коллекции и также таски не могут быть нулями. +6495.36 6505.20 "Анатолий Кулаков" То есть, это тоже штука, которая язык не запрещает, так можно делать, но в любой нормальной команде всегда есть договоренность, что так делать нельзя, так делать не надо. +6505.20 6507.60 "Анатолий Кулаков" Это приводит к огромному числу неприятностей. +6507.60 6511.48 "Анатолий Кулаков" И вот есть анализатор, который как раз таки работает на уровне вот этих доменов. +6511.48 6522.36 "Анатолий Кулаков" Также он может проверять домен-специфик value, когда вы используете primitive obsession, то есть, когда вы возвращаете строку, а вам нужен был ISBN, например, уникальный номер книги. +6522.36 6528.96 "Анатолий Кулаков" Он точно так же может вам порекомендовать, типа, оберните это в нормальный домен-специфик primitive и пользуйтесь им. +6528.96 6542.16 "Анатолий Кулаков" Он может проверять, что когда у вас используются магические номеры, то есть, магические числа, которые непонятно, что значат, встречаются где-то посредине кода, и никто никогда не догадается, что это за смещение с левой стороны луны. +6542.16 6550.00 "Анатолий Кулаков" В общем, вот подобные проверки, которые такие уже более домен-специфик, какие-то более на уровне договоренности между командами, вот там есть. +6550.00 6551.24 "Анатолий Кулаков" И их там достаточно много. +6551.24 6556.92 "Анатолий Кулаков" И этот анализатор, он работает именно не на уровне языка, а на уровне принципов. +6556.92 6576.20 "Анатолий Кулаков" Такие как принцип наименьшего удивления, принцип kitted simple stupid, это kiss, всем известный yagna, это you ain't gonna need it, don't repeat yourself, те же самые принципы OOP с правильным наследованием, с раскрытием каких-нибудь protected members. +6576.20 6579.56 "Анатолий Кулаков" Очень много у него есть про DDD, безусловно. +6579.56 6581.96 "Анатолий Кулаков" В общем, вот на таких уровнях, на уровнях принципа. +6581.96 6583.40 "Анатолий Кулаков" И вот это как раз то, чего не хватало. +6583.40 6591.72 "Анатолий Кулаков" Идеи автор сцеплял из Стивена Макконнелла, Джимми Нильсона, Джерми Миллера, Дэвида Фаулера, Роберта Мартина. +6591.72 6600.64 "Анатолий Кулаков" В основном это авторы больших таких монументальных трудов, это книги, книги по архитектуре, по дизайну, и там как раз вот эти все принципы очень тщательно и хорошо разобраны. +6600.64 6603.56 "Анатолий Кулаков" И как раз автор пытался отразить это все в анализаторах. +6603.56 6607.68 "Анатолий Кулаков" Есть, естественно, несколько уровней предупреждений. +6607.68 6612.16 "Анатолий Кулаков" Все они настраиваются с помощью Editor-Config, атрибутов, директив, все как положено. +6612.16 6620.00 "Анатолий Кулаков" Интересно то, что этот сайт, то есть вот эти описания всех вот этих проверок, они переведены на русский. +6620.00 6630.92 "Анатолий Кулаков" Если вдруг как раз эти описания могут быть очень полезны и для джунов, которые только учатся программировать и которые не знают, что, например, плохого в том, что вернули мьютабельную коллекцию из вашего метода. +6630.92 6635.32 "Анатолий Кулаков" Вот, часто джуны не знают хорошо английский и стесняются как бы читать английские сайты. +6635.32 6641.80 "Анатолий Кулаков" Здесь есть отличная переведенная версия, можно прямо на русском давать им ссылочки и там подробно будет написано, что все-таки случилось. +6641.80 6643.84 "Анатолий Кулаков" Ну и, собственно, конечно же есть анализатор. +6643.84 6653.64 "Анатолий Кулаков" То есть вам не нужно сверяться с этими принципами вручную, есть анализатор, который вы можете подключить к вашему CI или к вашей IDE и он будет это все дело проверять. +6653.64 6659.12 "Анатолий Кулаков" В общем, я планирую в ближайшее время попробовать и, может быть, на постояночку такой анализатор к себе подключу. +6659.12 6663.84 "Анатолий Кулаков" Еще я наткнулся на библиотечку. +6663.84 6673.80 "Анатолий Кулаков" Мне нужна была какой-нибудь embedded движок, который может хранить данные и, соответственно, загружать данные прямо в процессе. +6673.80 6677.76 "Анатолий Кулаков" То есть без какой-то отдельной базы данных, а прямо база данных, встроенная в процесс. +6677.76 6683.16 "Анатолий Кулаков" И мне не очень нужен был SQL syntax, иначе я бы, скорее всего, остановился на SQLite. +6683.16 6689.76 "Анатолий Кулаков" Ну и даже когда берешь SQLite, сразу вспоминаешь, что там все работает через interop и как-то не по себе становится. +6689.76 6691.64 "Анатолий Кулаков" Ну, вроде в 21 веке работаем, а тут опять interop. +6691.64 6696.92 "Анатолий Кулаков" В общем, и нагуглил внезапно какую-то интересную библиотечку, которая называется LightDB. +6696.92 6706.24 "Анатолий Кулаков" LightDB – это serverless, соответственно, вам не нужен какой-то выделенный сервак, embedded driver для базы данных, то есть он встраивается непосредственно в ваш процесс. +6706.24 6712.16 "Анатолий Кулаков" Он встраивается в виде одной-единственной DLL, вы ее просто подключаете через зависимость и все, и больше ни о чем не заботитесь. +6712.16 6717.56 "Анатолий Кулаков" Это NoSQL, документ Store, очень похожий по смыслу на MongoDB. +6717.56 6723.44 "Анатолий Кулаков" У него точно такой же примитивный API, ну, примитивный в хорошем смысле этого слова, простой API. +6723.44 6746.76 "Анатолий Кулаков" Он 100% в этой базе данных написан на C#, у него поддерживается полностью ACID транзакции, у него есть хорошие data recovery, допустим, если вдруг случилась ошибка в момент записи данных, там ваше приложение почему-то кильнулось, его убили, есть VOL, все в VOL пишется, потом восстанавливается и соответственно, данные ваши потеряться не должны. +6746.76 6751.60 "Анатолий Кулаков" Встроенное шифрование DES, IS, криптография, все на месте. +6751.60 6757.36 "Анатолий Кулаков" Результат записывается в единственный файл на диске, в базу данных, наподобие SQLite. +6757.36 6765.00 "Анатолий Кулаков" Библиотека полностью open-source, лежит на GitHub, распространяется под MIT лицензией, то есть свободна для всех, даже для коммерческого использования. +6765.00 6772.40 "Анатолий Кулаков" В общем, довольно прекрасно выглядит, много лайков, много коммитов, мне кажется, должна работать хорошо, тоже у меня в планах попробовать. +6772.40 6790.44 "Игорь Лабутин" Да, я ее как-то видел, мне кажется, но что-то мне no-seq не нужен был особо в таком вот формате, потому что если нужна реализационка, то есть SQLite, собственно, а ее как-то хватало до сих пор. +6790.44 6792.56 "Игорь Лабутин" Я и в корпусе SQLite, все работает. +6792.56 6795.20 "Игорь Лабутин" Ну надо будет на заметку себе взять, мало ли пригодится. +6795.20 6798.64 "Игорь Лабутин" Ну что, все, на сегодня, я думаю, хватит. +6798.64 6801.00 "Анатолий Кулаков" Да, кажется, пора заканчивать. +6801.00 6822.76 "Игорь Лабутин" Посмотрели мы на очень разные темы сегодня, сначала обсудили три performance темы, про EF7, про ISP.NET Core 7 и про MAUI, тоже о версии 7, потом посмотрели, как вы можете добавить свой собственный HTTP-глагол или HTTP-метод в ISP.NET Core, поддержку либо в minimal API, либо в MVC. +6822.76 6826.68 "Игорь Лабутин" Не очень понятно, зачем вам это сейчас надо, но если хочется, то почему нет. +6826.68 6835.04 "Игорь Лабутин" Обсудили DotNet Memory Module, который наконец-таки будет нормально документирован, надеемся, через скором времени. +6835.04 6840.36 "Игорь Лабутин" Посмотрели, как вы можете запустить DotNet 7 с помощью WASM на Raspberry Pi. +6840.36 6845.68 "Игорь Лабутин" Узнали, какие новые оптимизации нам принесли регионы в деле нормач-коллектора. +6845.68 6863.08 "Игорь Лабутин" Обсудили философию Quadrifactory, поговорили про всякие разные мелочи типа OpenTelemetry, ELSPY, LightDB, Coding Guidelines, в общем, тоже такая солянка из техники и философии немножечко, потому что Coding Guidelines, это иногда, мне кажется, больше философия в том числе. +6863.08 6865.88 "Игорь Лабутин" Хотя и практические моменты, конечно, тоже есть. +6865.88 6867.76 "Игорь Лабутин" Примерно так, на этом будем заканчивать. +6867.76 6876.08 "Анатолий Кулаков" Да, всем счастливо, слушайте и подписывайтесь, советуйте нас друзьям, распространяйте как только можно, мы будем очень счастливы. +6876.08 6877.08 "Анатолий Кулаков" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-62.txt b/input/Radio/Transcriptions/RadioDotNet-62.txt index 8874d8e..bcf7f53 100644 --- a/input/Radio/Transcriptions/RadioDotNet-62.txt +++ b/input/Radio/Transcriptions/RadioDotNet-62.txt @@ -1,839 +1,834 @@ -0.00 10.72 SPEAKER_01 Здравствуйте, дорогие друзья, в эфире Радио.нет выпуск номер 62. -10.72 13.20 SPEAKER_01 Сегодня в студии будет Анатолий Кулаков. -13.20 14.20 SPEAKER_01 И Игорь Лобутин. -14.20 15.20 SPEAKER_01 Всем привет. -15.20 25.36 SPEAKER_01 Сначала хотелось бы поблагодарить всех наших помогаторов – Александр, Сергей, Владислав, Алексей, Шевченко, Антон, Илья и Гурий Самарин, а также всех тех, кто пожелал остаться неизвестными. -25.36 30.64 SPEAKER_01 Друзья, большое спасибо за помощь и эти выпуски выходят в частности благодаря вам. -30.64 38.72 SPEAKER_01 Сегодня у нас немножко необычный будет выпуск, и в том же самом смысле обычный, потому что будем говорить мы про .NET и про C#. -38.72 43.16 SPEAKER_01 Ну, в принципе, как и всегда в нашем подкасте мы обсуждаем именно это. -43.16 66.16 SPEAKER_01 Но сегодня мы поговорим как раз-таки про конференцию .NET Conf 2022, на котором было представлено в частности .NET 7, C# 11 и множество вокруг этого всего от лзов, технологий, какие-то новые библиотеки, планов и прочего-прочего. -66.16 80.64 SPEAKER_01 Наверное, стоит сразу на берегу оговориться, что подробно мы обсуждать каждую тему не будем, потому что этим мы как раз-таки и занимались целый год с прошлого релиза .NET, поэтому кому интересно, можете смело переслушивать наши подкасты там за последний год. -80.64 90.92 SPEAKER_01 Информация там практически вся актуальная, не устарела, и где мы в детальностях разобрали в принципе все те новинки, которые сейчас уже предстали перед нами. -90.92 105.56 SPEAKER_01 Цель нашего сегодняшнего выпуска, наверное, быстро пробежаться и в общем обозреть, что в итоге получилось, что у нас за релиз, что он за собой потащил, какие инструменты подтянулись и что он нам вообще готовит, чем мы на ближайший год будем пользоваться. -105.56 106.56 SPEAKER_01 Правильно я говорю? -106.56 107.84 SPEAKER_01 Да, все так. -107.84 120.60 SPEAKER_00 Мы попробуем, так скажем, рассказать про инструменты, тулзы, новинки, библиотеки, фреймворки, которые каким либо образом обновились. -120.60 126.08 SPEAKER_00 Действительно, наверное, 90%, если не больше, мы уже каким-то образом в этом подкасте упоминали. -126.08 142.36 SPEAKER_00 Но составить цельную картину, составить полное понимание, что же у нас такое .NET 7, возможно, это как-то проще запомнить, когда теперь оно свелось все в единый релизный .NET 7, теперь этим можно начинать пользоваться, продакшене, все такое. -142.36 145.44 SPEAKER_00 Так что как раз на этом мы все это и будем смотреть. -145.44 155.48 SPEAKER_01 Ну, я напоминаю, что следующий .NET, который через годик будет, он уже будет LTS, и вот там будет, наверное, уже и больше фич, и больше клиентов, и больше переводов. -155.48 157.28 SPEAKER_01 Ну, то есть LTS, он в Африке LTS. -157.28 173.92 SPEAKER_01 Вот, и чтобы не пропустить этот момент, чтобы, опять же, ушами не хлопать, когда выйдет релиз, смело подписывайтесь на наш подкаст, не теряйте ни одного выпуска, а мы, соответственно, будем вас практически каждый выпуск посвящать в те новинки, которые ждут на вас в LTS. -173.92 180.56 SPEAKER_01 Поэтому рассказывайте о нас своим друзьям, нам шарри, репост, сабскрайб, колокольчики, всеми возможными способами. -180.56 187.36 SPEAKER_01 Подписывайтесь, нам будет приятно, и следите за нашими выпусками, мы будем держать вас в курсе. -187.36 192.28 SPEAKER_00 Начнем, давай на самом деле, действительно, вот мы тут говорим LTS, не LTS, LTS, не LTS. -192.28 197.40 SPEAKER_00 У нас текущий релиз, это не LTS, как он правильно называется, знаешь? -197.40 198.40 SPEAKER_00 - СТС. -198.40 219.08 SPEAKER_00 - СТС, да, ну то есть он раньше назывался Current, теперь он должен называться STS, это LTS, это у нас Long Term Support, то есть релиз, который поддерживается три года с момента выпуска, а Current, который не LTS, или теперь он называется STS, он поддерживается полтора года, то есть ближайший год до ближайшего LTS и еще полгодика после этого, чтобы дать вам время перейти. -219.08 231.96 SPEAKER_00 STS это не Short Term Support, это Standard Term Support, чтобы вы понимали, но я никогда не видел практически, чтобы использовали термин Current, так что, скорее всего, STS тоже вряд ли сильно будут использовать и просто говорить LTS или Non-LTS. -231.96 253.80 SPEAKER_00 Релиз этот, который семерка, он большой, в него довольно много контрибьюшенов и Microsoft отдельно подчеркивает, что очень много всяких open-source внешних контрибьюшенов, то есть в этом релизе поучаствовало по каким-то замерам порядка 8900 внешних контрибьюторов, которые принесли 28000 контрибьютов. -253.80 266.60 SPEAKER_00 Конечно, там, скорее всего, распределение не такое, что все поровну, но почти 9000 внешних человек поучаствовали в том или ином виде в развитии этого релиза, и это прикольно. -266.60 295.56 SPEAKER_00 Дальше, основная цель команды это сделать более-менее унифицированный SDK, то есть чтобы вам не нужно было ставить там SDK такой, SDK секой, SDK эдакий, чтобы вы просто ставите .NET SDK и в нем добавляете, возможно, какие-то нужные части, мы говорили про такую тему как ворклоуды, то есть части SDK идут отдельно, они не ставятся сразу, их нужно добавить потом отдельно, и потом вы полученный, собственно, комплект тулов можете использовать для разработки для тех или иных платформ. -295.56 300.36 SPEAKER_00 И в частности, одной из платформ, над которой велась довольно большая работа, был ARM64. -300.36 328.84 SPEAKER_00 Эта штука, она сейчас трендовая, во-первых, она трендовая в лэптопах в каком-то смысле, потому что там потихонечку армы становятся популярные там, ну и на серверах тоже, дело не отстает, там в Амазоне есть соответствующие, как они, гравитоны, да, в Ажуре, по-моему, тоже что-то появилось, не помню как называется, Ажур Ампер, по-моему так. -328.84 356.40 SPEAKER_00 И Microsoft работает над тем, чтобы .NET на ARM64 работал ну с той же скоростью, как на x64, потому что в рекламе всегда говорится, что ARM процы вам будут дешевле, потому что они потребляют меньше энергии и всё такое, но при этом в старых версиях .NET, которые уже начинали поддерживать ARM64, они, конечно, потребляют меньше электричества, работают эффективнее, но .NET на них работал существенно медленнее, и поэтому хорошо, если тон оттуда и выйдет, а то и медленнее будет. -356.40 361.40 SPEAKER_00 Цель была добиться того, чтобы перформанс был похож на x64. -361.40 380.84 SPEAKER_00 Там были проблемы с атомиками, ARM64 до некоторой версии не поддерживал атомарные записи чтения, ну в смысле типа compare and swap, или load and store, не помню точно, но ещё какую-то из них он не поддерживал, в какой-то версии начал поддерживать, и в .NET это добавили. -380.84 402.12 SPEAKER_00 В векторизацию добавили, поддержку векторных операций, и в результате получили, не только эти два изменения, конечно, было много ещё других, получили, что сейчас по результатам замеров на .NET 7, перформанс подбирался и подбирался, подбирался по мере превьюшек к перформансу на x64, и наконец-таки сравнялся, и даже чуть-чуть превзошёл. -402.12 411.48 SPEAKER_00 Так что в общем-то можно сказать, что более-менее цель достигнута с точки зрения поддержки ARM64. -411.48 431.88 SPEAKER_00 Дальше вторая причина, проблема, не знаю, цель с Unified SDK в том, что этот SDK должен быть унифицирован вообще для всех платформ, куда мы ставимся, то есть работаем ли мы на Windows, работаем ли мы на Linux, на Mac, SDK, ну в смысле инсталлятор, конечно, разный, но с точки зрения того, что вы получаете, должно быть всё более-менее одинаково. -431.88 437.68 SPEAKER_00 В этом смысле есть довольно большая работа, которая делается для Linux, для Ubuntu. -437.68 454.24 SPEAKER_00 Начиная с шестёрки, там .NET поддерживается уже в прям в нативном менеджере пакетов, то есть не нужно качать инсталлятор, можно просто сказать "Up to install .NET 6", и начиная с этого релиза у нас есть прикольные компактные образы про Ubuntu, мы про них поговорим ближе к концу. -454.24 473.28 SPEAKER_00 С точки зрения таргетинга или одной из тоже целей .NET 7, конечно, является большое хайповое движение под названием Cloud Native, то есть всё, что мы пишем, если мы пишем для Web или ещё для чего-то, должно быть, конечно же, Cloud Native. -473.28 485.32 SPEAKER_00 И тут возникает несколько моментов, которых .NET был, ну не то чтобы прям медленный или неудобный, но который всегда можно было что-то улучшить, вот поулучшали. -485.32 488.12 SPEAKER_00 Во-первых, поулучшали поддержку контейнеров, поговорим попозже. -488.12 499.60 SPEAKER_00 Во-вторых, почему-то в анонсе именно в этом месте Microsoft упоминает такой фреймворк как Carlins, мы про Carlins тоже чуть дальше поговорим, почему он в Cloud Native находится, я не очень понял, но тем не менее. -499.60 503.76 SPEAKER_00 Зато там точно находится штука, которая должна быть, это работа с JSON. -503.76 512.84 SPEAKER_00 Пишите ли вы веб-сервисы, или может быть даже если вы пишете какие-то command-line тулы, как ни странно, или что-нибудь ещё, вы довольно много всегда работаете с JSON. -512.84 519.72 SPEAKER_00 И в Dota 7 JSON, стандартный JSON-сериализатор, получил довольно много улучшений и изменений. -519.72 535.68 SPEAKER_00 Во-первых, там теперь стала возможна поддержка полиморфных типов, вы можете указать на родительском типе специальный атрибутик JSON Derived Types и указать список, соответственно, дочерних типов, которые вы хотите уметь реализовывать. -535.68 540.80 SPEAKER_00 Это будет такая статическая полиморфиза, можно сделать динамически, чуть более сложно. -540.80 552.04 SPEAKER_00 И есть ещё специальный атрибут JSON Polymorphic, который позволяет настроить на самом деле то, как всё это работает, что делать, если встретился неизвестный тип, как вообще определять, что за тип. -552.04 559.12 SPEAKER_00 Это делается всё с помощью специального полидискриминатора, как его назвать, ну и в общем, вся кастомизация делается через него. -559.12 563.24 SPEAKER_00 А кроме этого ещё можно делать кастомизацию непосредственно контракта. -563.24 599.40 SPEAKER_00 То есть если, например, у вас есть какой-нибудь класс, может быть ваш, может быть из вообще сторонней библиотеки, в котором у вас нет исходников, но вы хотите либо ваш класс как-то очень хитро сериализовывать в JSON, либо вы хотите этот сторонний класс как-то хитро сериализовывать или десериализовывать из JSON, то теперь стало возможно написать специальный TypeResolver, который сериализатор будет дёргать в моменты, когда он сериализует объекты этого класса, и в этом резолвере определять вообще, что делать с объектом, причём там доступно значение самого объекта, то есть там можно намутить логику типа там "если поле объекта true, то два соседних поля сериализовывать не надо" или наоборот. -599.40 608.12 SPEAKER_00 То есть всякую сложную логику я думаю, что на этой штуке можно там практически полное поведение Newtonsoft'а воспроизвести, хотя на 100% понятно не уверен. -608.12 628.96 SPEAKER_00 А при апдейте .NET естественно обновляется core библиотека, BaseClass library, там довольно много, понятное дело, всяких довольно мелких улучшений, несколько штук были признаны достаточно значимыми, чтобы попасть в главный анонс про релиз .NET 7. -628.96 637.08 SPEAKER_00 Это nullable аннотации на весь namespace Microsoft Extensions, если вы что-то оттуда используете, знайте, теперь это что-то поддерживает nullable. -637.08 654.00 SPEAKER_00 В типы работы с датой и временем, то есть date/time и timeonly/timespan завезли поддержку micro и nanosecond, то есть раньше всё, что меньше, чем миллисекунды, нужно было оперировать тиками, теперь можно работать с микро и наносекундами, есть соответствующие API, ну и оверлоды конструкторов и так далее. -654.00 672.32 SPEAKER_00 В iMemoryCache завезли метрики, я вот на самом деле в своих проектах всё чаще и чаще замечаю, что мы кэшируем через iMemoryCache, и соответственно было бы здорово выставить метрики наружу, в какой-нибудь Prometheus или ещё куда-нибудь, чтобы следить вообще, в каком состоянии эти кэши, теперь это можно сделать. -672.32 683.28 SPEAKER_00 Класс, соответственно, ну интерфейсы класса имеют соответствующие методы, которые вы можете использовать, чтобы всё это выставить наружу в нормальный ваш коллектор-метрик. -683.28 695.68 SPEAKER_00 Ну и поддержка tar-архивов, понятно, что поддержка Linux должна быть, поэтому tar-архивы на Linux довольно популярны, вот оно там есть, плюс оно ещё потребовалось для докера, как оказалось. -695.68 701.92 SPEAKER_00 В SDK в целом изменений не так много, именно с точки зрения тулинга, вот .NET тулинга. -701.92 707.88 SPEAKER_00 Понятно, что там есть всякие разные изменения, типа .NET watch, там всякие смайлики завезли, это в одном из первых превьюшек, мне кажется, было. -707.88 710.64 SPEAKER_00 Hot reload, там вот теперь всякие иконочки рисуют. -710.64 723.32 SPEAKER_00 Появилась возможность нормального автодополнения в команде .NET new, там теперь какой-то более клёвый парсер и тап комплешн. -723.32 743.44 SPEAKER_00 Ну и темплетики, то есть шаблоны проектов, которые вы можете создавать в .NET new и которые вы можете, честно говоря, создавать сами, теперь можно создавать, появилось возможность ограничений, то есть можно сказать, что если вы там создаете в таком-то ворклоуде, то вот этот шаблон теперь неприменим, ну и так далее. -743.44 748.84 SPEAKER_00 Есть возможность какую-то условную, грубо говоря, доступность шаблонов организовать. -748.84 753.60 SPEAKER_00 Последняя секция в большой статье анонса — это про перформанс. -753.60 762.36 SPEAKER_00 Куда же без перформанса, мы весь год говорили про перформанс, по-моему, ни один превью у нас не был без новостей о перформансе, то ли иные штуки. -762.36 766.68 SPEAKER_00 Ну в перформансе три главных вещи, которые произошли. -766.68 768.56 SPEAKER_00 Во-первых, это онстайк реплейсмент. -768.56 796.60 SPEAKER_00 У нас был уже то, что называется tired compilation, ну и здесь, это было уже в шестом .NET, но проблема с ним была в том, что он не мог подменять функции, то есть смысл в чём, что если какая-то функция или какой-то кусок кода используется чаще, чем обычно, то есть количество вызовов этого кода превышает некоторый порог, то он перекомпилировался более оптимально и ссылка на него подменялась. -796.60 800.60 SPEAKER_00 Проблема в том, что если вы это сделали для функции, которая сейчас исполняется, ну как бы подменить её сложно. -800.60 801.60 SPEAKER_00 Вот теперь можно. -801.60 813.44 SPEAKER_00 .NET 7 умеет это делать, если у вас есть большой цикл в функции, то как раз .NET 7 умеет теперь перекомпилировать и подменять такие функции, даже пока они выполняются. -813.44 816.84 SPEAKER_00 File Guided Optimization туда же и Native OUT. -816.84 837.20 SPEAKER_00 Native OUT в семёрке получил прям очень хороший boost, он работает, ну как я понял, довольно неплохо для всяких разных таких классических ворклоудов типа консольных приложений, ASP.NET Core, а не, если ASP.NET Core как раз не работает, там Reflection сейчас много пока ещё, и про это ведутся активные разговоры, как бы так сделать, чтобы заработало. -837.20 840.80 SPEAKER_00 Но есть эксперименты по всяким WinForm и прочим. -840.80 856.76 SPEAKER_00 При этом Native OUT там работали довольно хорошо над всяким триммингом и прочим, пустая консольная приложенка, которая скомпилирована в Native OUT на винде, сейчас занимает 3,6 мегабайта, то есть в общем-то уже, ну, более-менее разумный размер. -856.76 871.00 SPEAKER_00 Но понятно, что как только вы начнёте тащить внутрь всякие зависимости, в зависимости от того, насколько хорошо для них определены настройки тримминга, размер может резко поползти наверх, потому что все эти зависимости будут упакованы в этот single file. -871.00 875.08 SPEAKER_00 Ну и говоря про performance, нельзя не сказать, конечно, про бенчмарки. -875.08 885.32 SPEAKER_00 Если вы посмотрите открывающий видосик с .NET Conf, там будет сказано, что .NET 7, он, короче, круче, крут-крут-крут, он круче Go, он круче Node.js, он круче кого? -885.32 886.32 SPEAKER_00 Java. -886.32 888.24 SPEAKER_00 Понятно, ну короче, мы круче всех. -888.24 902.16 SPEAKER_00 Это всё основано на техэмпауэре, верить ему надо с большими-большими оговорками, и там на самом деле несколько тестов на ASP.NET Core, смотреть надо только на некоторые, и смотря что вы хотите добиться, какую информацию вы хотите узнать. -902.16 918.16 SPEAKER_00 Про это есть отдельная большая статья, мы про неё, наверное, поговорим, постараемся в следующем выпуске, поэтому если вам интересно что-то узнать про техэмпауэр, и как Microsoft, и как вообще ASP.NET Core с ним справляется, дожидайтесь следующего выпуска, там мы постараемся всё подробнейшим образом рассказать. -918.16 922.24 SPEAKER_01 Слушай, а почему ты ничего про майонез, о легионах не сказал? -922.24 924.12 SPEAKER_01 Тоже большая работа была проделана, почему это не -924.12 928.40 SPEAKER_00 упомянули? Почему это не упомянули на главной странице, я даже не знаю. -928.40 934.24 SPEAKER_00 То есть, это действительно большая работа, в докладе, кстати, который я на dotnext читал, я про это упоминал. -934.24 951.48 SPEAKER_00 Про это, наверное, так в паре слов не расскажешь, но смысл в том, что да, у нас теперь регионы исключены по умолчанию, теперь у нас память выделяется не большими сегментами, а маленькими кусочками, по 4 или сколько-то мегабайт, и в теории на вас это повлиять должно только в лучшую сторону, но может быть и в худшую. -951.48 961.84 SPEAKER_00 Если я правильно помню наше рассуждение из каких-то превью, из статьи Маони, что на старте приложения теперь может потреблять побольше памяти, зато более агрессивно отдавать ее в процессе работы. -961.84 968.08 SPEAKER_00 Так что тестируйте ваше приложение на новых режимах работы ГЦ и смотрите, что получилось. -968.08 983.00 SPEAKER_01 Ну, я думаю, надеюсь, что все-таки там не так все плохо, Майонь обычно не ошибается, всегда делает на совесть, поэтому хорошее обновление, хорошие анонсики, но, наверное, самое интересное, чего все ждут, это, конечно же, изменения в языке. -983.00 985.40 SPEAKER_01 Что нас в C# 11 порадовало? -985.40 1005.60 SPEAKER_00 Да, в C# 11 у нас довольно много всего завезли, причем я боюсь, что я не буду сейчас еще раз все аккуратно рассказывать смысл всех фич, потому что их довольно много, их, по-моему, 14 или 15 штук, таких, которые оказались достойны упоминания во всяких статьях. -1005.60 1008.28 SPEAKER_00 И вот с нее, ну, кратенько давайте перечислим. -1008.28 1011.80 SPEAKER_00 Мы про них, про все уже говорили, на самом деле, много раз. -1011.80 1014.00 SPEAKER_00 Для начала начнем работать со строками. -1014.00 1029.36 SPEAKER_00 У нас теперь появились UTF-8 литералы, то есть если вам вдруг зачем-то нужны быстрые UTF-8 строки, вы теперь можете после обычного литерала C# дописать U8, и вы получите сущность, которая имеет тип не string, а тип read-only span от байтов. -1029.36 1043.44 SPEAKER_01 Ну, скорее всего, это вам нужно где-нибудь на границах приложения, например, если вам нужно быстро отдать в сокет какую-нибудь строку без лишних конвертаций между UTF-16 и UTF-8, наверное, полезная вещь, почему нет? -1043.44 1047.20 SPEAKER_00 Да, все так, вот ровно для этого это и было сделано, вероятно, поэтому... -1047.20 1050.80 SPEAKER_00 И на этом, кстати, основа техампа русский матчмарк, в частности. -1050.80 1053.72 SPEAKER_00 Дальше у нас появились raw string литералы. -1053.72 1058.40 SPEAKER_00 Мы могли раньше задать строку, в которой вы задаете, например, JSONчик. -1058.40 1062.28 SPEAKER_00 Но проблема в том, что JSON содержит много кавычек, вы должны их экранировать через бэкслэш. -1062.28 1076.08 SPEAKER_00 Можно было написать вначале строки символ "собаки", после чего вам не нужно было ничего экранировать, кроме, опять же, кавычек, потому что строка ограничена кавычками, но в этом случае нужно кавычки игнорировать двойной кавычкой, ну, в смысле, вместо одной писать две. -1076.08 1077.72 SPEAKER_00 И так и так неудобно. -1077.72 1086.64 SPEAKER_00 Теперь у нас появились raw string литералы, это вы можете начать строку с трех и более кавычек, написать внутри все что угодно и закончить таким же количеством кавычек. -1086.64 1094.32 SPEAKER_00 Любое количество кавычек меньше, чем использовано при открытии строки, считается простым литералом и не требует экранирования. -1094.32 1098.28 SPEAKER_00 Второй момент, они могут быть многострочными. -1098.28 1102.64 SPEAKER_00 В этом случае открывающие и закрывающие кавычки должны быть на своей отдельной строке. -1102.64 1112.04 SPEAKER_00 То есть вы объявляете переменную, пишете равно, там три кавычки, например, дальше со следующей строки начинаете текст, и потом в конце на отдельной строке закрываете тремя кавычками. -1112.04 1119.80 SPEAKER_00 Положение этих закрывающих трех кавычек тоже важно, в зависимости от этого компилятор будет откусывать лишние начальные пробелы у всех строк внутри. -1119.80 1130.08 SPEAKER_00 Внутри этих литералов можно использовать string interpolation, понятное дело, для этого вы перед этими тремя кавычками запихиваете нужное количество долларов, один, два, три и так далее. -1130.08 1136.28 SPEAKER_00 Чем больше долларов вы запихнете, тем больше последовательных фигурных скобок вам можно использовать внутри без того, чтобы это считалось подстановкой. -1136.28 1148.88 SPEAKER_00 Но для того, чтобы работала подстановка, то есть если вы, например, пишете строку с трех долларов и трех кавычек, то чтобы внутри string interpolation работал, нужно тремя фигурными скобками обозначать места, где будет string interpolation. -1148.88 1153.12 SPEAKER_00 Если у вас много interpolation, наверное, выгоднее поменьше долларов использовать. -1153.12 1166.12 SPEAKER_00 Но если у вас, грубо говоря, огромный JSON, куда подставляется два каких-нибудь поля, то может быть имеет смысл как раз использовать тройной такой доллар и в одном или двух местах указать три открывающихся фигурных скобки, а весь остальной JSON будет из обычных одинарных. -1166.12 1174.32 SPEAKER_01 На самом деле полезная штука, я в всяких скриптовых языках часто таким пользуюсь, где нужно организовать какие-то большие темплейты и еще что-то. -1174.32 1184.20 SPEAKER_01 Единственное, что меня до сих пор смущает, это вот эта безумная магия, когда нужно там три кавычки поставить с определенным отступом, если отступ другой, то поведение внутри меняется. -1184.20 1201.64 SPEAKER_01 Если вдруг вы поставили три кавычки и два вопросительных знака, это совсем не то, что один вопросительный знак, и вот эти всякие тонкости, они, конечно, я думаю, будут не один мозг еще убьют, но надо признать, что команда попыталась выжать максимум из этой фичи, попыталась сделать максимально удобно. -1201.64 1207.52 SPEAKER_01 Ну посмотрим, как на практике этот баланс сумели ли они соблюсти между понятностью и используемостью. -1207.52 1223.64 SPEAKER_00 Да, там на самом деле компилятор очень старается, если вы, например, поставите закрывающую кавычку, закрывающие три кавычки на последней строке слишком далеко вправо, и у вас нормальный контент начинается левее, то там компилятор, раз ошибка компиляции будет писать, что у вас кавычка не там стоит. -1223.64 1224.64 SPEAKER_00 Короче, они постарались. -1224.64 1227.84 SPEAKER_00 Дальше, про мемберы. -1227.84 1241.72 SPEAKER_00 Мемберы у нас теперь могут быть не только там static, readonly, вот это все, они не только могут быть там с getset или init этими модификаторами, но еще они могут теперь быть required. -1241.72 1251.16 SPEAKER_00 Required означает, что этот мембер должен быть обязательно интеллизирован либо через конструктор, либо через object initializer. -1251.16 1273.64 SPEAKER_00 Причем проблема состоит в том, что через конструктор оно как-то работает фигово, в том смысле, что если у вас есть конструктор, который принимает два поля, ну даже не два, допустим у вас есть пропертиа, которая обозвонка required, у вас есть конструктор, который принимает какой-то аргумент и проставляет в это поле, компилятор не поймет, что таким образом эта штука интеллизируется, если у вас есть пустой конструктор дополнительно. -1273.64 1279.56 SPEAKER_00 И нужно такой конструктор помещать дополнительным атрибутом setsRequiredMembers. -1279.56 1294.24 SPEAKER_00 Я попытался, вот после доклада меня спрашивали, зачем вообще такая штука, зачем нужен был атрибут, что-то я быстро не смог найти, надо читать всякие обсуждения, ну читать и слушать обсуждения именно API-дизайна, почему так было сделано. -1294.24 1302.08 SPEAKER_00 Не получилось у меня быстро понять, зачем вот таким атрибутом, почему компилятор нельзя было научить, что все на самом деле нормально работает. -1302.08 1306.88 SPEAKER_01 Но смысл в том… Ну по идее это сложный flow-анализ, у нас в компиляторе сейчас нигде нет flow-анализа. -1306.88 1321.16 SPEAKER_00 Ну сложный, не сложный, но в общем да, так или иначе это было сделано, в результате надо понимать, что если у вас есть requiredMembers и есть вот такой атрибутик на каком-то конструкторе, то у вас никто не гарантирует, что requiredMembers будут заполнены, к сожалению. -1321.16 1323.08 SPEAKER_00 Они могут остаться непроинтеллизированы. -1323.08 1328.52 SPEAKER_00 Дальше, про field'ы, у нас появились reffield'ы и scopedref'ы. -1328.52 1337.20 SPEAKER_00 Я не буду сейчас сильно углубляться, что это такое, но смысл такой, в общем-то это чисто для того, чтобы нормально поддержать спаны, потому что раньше они были поддержаны с некоторым хаком. -1337.20 1347.00 SPEAKER_00 А scopedref'ы это как раз тот самый flow-анализ, чтобы понять, куда какие ref'ы можно отдавать выше-ниже по стэку и понимать, можно ли нельзя отдавать. -1347.00 1353.80 SPEAKER_00 Там фича довольно сложная, надо вдумываться, чтобы понять, я на слух не смогу ее, наверное, объяснить. -1353.80 1355.68 SPEAKER_00 Про типы, что у нас еще есть? -1355.68 1367.84 SPEAKER_00 У нас появились filescoped-типы, то есть если перед классом или структуркой написать вместо слова public или internal слово file, то такой тип будет доступен только в рамках этого файла. -1367.84 1371.88 SPEAKER_00 Нужно это… И зачем на практике такая штука нужна? -1371.88 1395.56 SPEAKER_00 Я так понял, в основном такая штука используется для source-генераторов, то есть типа тот самый partial-класс, который генерится source-генератором, он же как бы в общем-то не нужен ни для чего, кроме как для того, чтобы вписать туда код этого самого непосредственно сгенеренного метода или там чего вы аннотируете вашим атрибутикам для source-генератора. -1395.56 1409.24 SPEAKER_00 И вот чтобы этот класс больше нигде не светился, ни в каких interessence-ах нигде, вот его, я так понимаю, можно сгенерить со scope-file, и тогда он будет виден только в рамках того файла, куда он подставлен. -1409.24 1411.28 SPEAKER_01 Интересно, а что там в ILLI получается? -1411.28 1414.88 SPEAKER_01 Ведь когда мы в assembly запихиваем все это дело, у нас уже нет никакого файла. -1414.88 1425.08 SPEAKER_00 Да, там генерится специальное имя, которое, оно конечно глобально видимо, то есть тот факт, что его не видно в namespace в подсказках, это чисто фича Visual Studio. -1425.08 1438.24 SPEAKER_00 Понятно, что в атрибутах там ничего такого нету, там просто имя, в которое включен hash SHA-256 от пути к файлу в компилятор с генерированным имя. -1438.24 1441.04 SPEAKER_01 Ну и namespace, конечно. -1441.04 1451.00 SPEAKER_01 Ну вообще если такая вещь, которая нужна чисто для IDE, типа скрыть от interessence, они раньше делались атрибутами, и кажется, что это более разумный и вменяемый способ, чем заводить новые кейворты. -1451.00 1453.52 SPEAKER_01 Зачем они нужны, если только студия должна не видеть -1453.52 1455.52 SPEAKER_00 это? Непонятно. -1455.52 1473.72 SPEAKER_00 Кстати, интересный момент, вот как раз про эту фичу есть на dotnet.conf видосик от Джаррида Парсонса, там 20 с копеечками минут, где он как раз рассказывает про дизайн такой фичи, то есть вообще у него видосик типа let's design language feature, где он показывает, про что команда думает, как она подходит к тому, как что задизайнить. -1473.72 1480.44 SPEAKER_00 Вот на примере файла этих скоп-тайпов можно посмотреть, как они что-нибудь делали. -1480.44 1481.44 SPEAKER_00 Давай дальше. -1481.44 1502.44 SPEAKER_00 Дальше у нас есть из мелочей nameof, которые теперь можно использовать снаружи методов, то есть если вы хотите, допустим, в атрибут указать имя параметра, а такое бывает надо для всяких там хитрых атрибутов, ну для вот nullability нужно, да, там not null if not null, когда вам нужно указать имя параметра какого-то. -1502.44 1511.24 SPEAKER_00 И для атрибутов, если вы хотите что-то про параметры тоже сказать, можно теперь использовать nameof, и можно использовать generic attribute. -1511.24 1520.32 SPEAKER_00 Ну и так, еще я забыл про лист паттерны, теперь есть у нас во всяких из выражениях можно указывать списки. -1520.32 1536.76 SPEAKER_00 Работает это немножко кривовато, то есть это хорошо работает на массивах, это не очень хорошо работает на списках, то есть там есть фича, которая позволяет, например, сказать, что этот массив из квадрата на скобках открывается там, не знаю, 0, точка, точка, var y. -1536.76 1541.80 SPEAKER_00 И вот в var y положится весь хвост массива, если первый элемент 0. -1541.80 1546.92 SPEAKER_00 То есть таким образом можно откусить нужный кусочек массива, серединку, там край, край. -1546.92 1552.60 SPEAKER_00 Но проблема в том, что это работает только на коллекции, где реализован range, ну индексатор от range. -1552.60 1556.96 SPEAKER_00 А листы такого не реализуют, поэтому на листах такое работать, к сожалению, не будет. -1556.96 1558.24 SPEAKER_00 Странно, а почему? -1558.24 1559.92 SPEAKER_00 У листа же есть индексатор. -1559.92 1564.08 SPEAKER_00 У листа есть индексатор от индекса, ну от int. -1564.08 1565.08 SPEAKER_00 От int, да. -1565.08 1566.08 SPEAKER_00 А нужно? -1566.08 1567.08 SPEAKER_00 А нужно от range. -1567.08 1568.08 SPEAKER_00 А, понятно. -1568.08 1571.48 SPEAKER_00 Чтобы ты мог написать там квадратные скобки, 2, точка, точка 5. -1571.48 1572.48 SPEAKER_00 Погоди, почему не реализовать-то? -1572.48 1573.48 SPEAKER_00 Ничего не мешает? -1573.48 1574.48 SPEAKER_00 Вот это интересный момент. -1574.48 1576.16 SPEAKER_00 Не знаю, почему не реализовали. -1576.16 1579.96 SPEAKER_00 Если хотите так работать с листами, пишите своего наследника листа. -1579.96 1581.56 SPEAKER_00 Не знаю, почему не сделали. -1581.56 1585.16 SPEAKER_01 Да нет, делайте pull request, настоящий лист, что это такое? -1585.16 1589.56 SPEAKER_00 Ну да, либо почитайте историю, может быть там будет написано, почему они так не сделали. -1589.56 1605.76 SPEAKER_00 И да, generic математика, мы про неё много раз говорили, статические абстрактные методы интерфейсов плюс generic математика, там несколько десятков интерфейсов в system numerix, которые теперь реализованы всеми стандартными примитивами, можно писать свою generic математику. -1605.76 1625.16 SPEAKER_00 Если вам интересно более детально посмотреть на всё это, потрогать руками, во-первых, есть официальные гайды от Microsoft, во-вторых, есть хорошая статья, ссылочка будет в описании, плюс есть GitHub репозиторий с некоторыми примерочками на седьмом linkpad, который я использовал для своего доклада на dootmxt, который недавно прошёл. -1625.16 1630.52 SPEAKER_00 Там тоже можно потрогать, там есть простые примеры почти на все фичи. -1630.52 1632.60 SPEAKER_00 Не абсолютно на все, но почти на все. -1632.60 1643.56 SPEAKER_01 Не забывайте уже про ранее упомянутый тобой dotnet.conf, там куча видосиков про фреймворк, по tool, по всяким фичам языка, там тоже много чего интересного можно посмотреть. -1643.56 1649.40 SPEAKER_00 По-моему, там, кстати, сам Matt Storgerson рассказывает про какие-то фичи по крайней мере языка. -1649.40 1657.28 SPEAKER_01 Может быть, ну соответственно у нас после языка C# есть ещё один самый главный язык, это всё-таки F#. -1657.28 1661.00 SPEAKER_01 Не Visual Basic, почему-то про Visual Basic в этот раз было совсем мало. -1661.00 1664.84 SPEAKER_01 Давайте посмотрим, что у нас такого интересного произошло в F#. -1664.84 1674.72 SPEAKER_01 В принципе, самая главная цель, на которую были направлены авторы в этом релизе, это сделать F# как можно ближе к народу, как можно более понятным, более простым. -1674.72 1685.48 SPEAKER_01 И кажется, что им это удалось, у них много было улучшений в инструментарии, особенно вокруг, в поддерживании EDE, ну и конечно же, перформанс, куда же без перформанса, всё улучшили. -1685.48 1692.40 SPEAKER_01 Ещё одним большим таким направлением по развитию это была интеграция с новыми фичами C#. -1692.40 1697.44 SPEAKER_01 В частности, уже упомянутый к ночи был Static Abstract Member в интерфейсах. -1697.44 1705.84 SPEAKER_01 Теперь в F# в седьмом это тоже поддерживается, это один из базовых концептов для того, чтобы делать Generic Math. -1705.84 1717.08 SPEAKER_01 И также поддерживает встроенные BCL-типы, которые реализуют всякие вот эти магические интерфейсы iNumber, iAdditional и прочее. -1717.08 1722.20 SPEAKER_01 В общем, F# это тоже умеет понимать и тоже применять к ним всякую математику. -1722.20 1742.92 SPEAKER_01 Мне вообще интересно, что сейчас спрашивают в Juno на собеседованиях, потому что после того, как Майоня там переделала всё, что только можно переделывать со всякими поколениями, после того, как у нас появились абстрактные статические методы в интерфейсах, после того, как уже нет никакой разницы между референсом и ref value, что вообще можно на собеседованиях спрашивать? -1742.92 1743.92 SPEAKER_01 Как Juno валят, интересно. -1743.92 1761.88 SPEAKER_00 Да спрашивать, наверное, всё то же самое, про поколения спрашивать можно всё так же, но вот если тебе Juno ответит, ну у нас теперь можно из нуля и во второе поколение, потому что у нас регионы, то ты знаешь, что это либо очень начитанный Juno, либо он слушает наш подкаст, либо он просто наоборот что-то где-то слышал и надо копать дальше. -1761.88 1763.92 SPEAKER_01 Или наоборот выпендривается, да. -1763.92 1767.40 SPEAKER_01 Хорошо, погнали дальше. -1767.40 1771.96 SPEAKER_01 Упростилась работа со Statical Result Type Parameters. -1771.96 1781.28 SPEAKER_01 Это такие специальные типы параметров, которые могут заменяться во время компиляции, в отличие от обычного случая, когда заменяются они в ран тайме. -1781.28 1790.80 SPEAKER_01 Тоже очень полезная штука для оптимизации, для скорости, в общем сейчас с ними стало работать намного удобнее и применяться они стали намного чаще. -1790.80 1802.08 SPEAKER_01 Также был поддержан Required Keyword, про который говорил Игорь, и нет Keyword в свойствах, которые позволяют инициализировать проперти в тех или иных условиях, это все тоже F# понимает. -1802.08 1819.88 SPEAKER_01 Также F# теперь умеет компилировать, то есть компилятор F# умеет генерировать reference assembly, это специальные сборки, которые содержат минимум информации, в которой есть по сути только metadata. -1819.88 1833.96 SPEAKER_01 Эта metadata покрывает только публичный API, что позволяет вам просто компилировать ваше приложение с какими-то сборками, зная, что там этот публичный API точно есть, но запускаться с ними вы естественно не можете. -1833.96 1849.00 SPEAKER_01 Почему это полезно, когда вы хотите например скомпилироваться на одной операционной системе, а запускаться будете на другой операционной системе, но для этого вам нужны какие-то API, которые будут на целевой естественной операционной системе, и вот как раз reference assembly в этом помогут. -1849.00 1854.32 SPEAKER_01 У нас тоже там была отдельная тема, большая тема в каком-то выпуске про reference assembly, если интересно, поищите. -1854.32 1875.60 SPEAKER_01 И F# уже давно умеет триммиться, он уже давно умеет запускаться под нативным кодом, ну то есть как нативный код, ну а теперь это сделали еще лучше, еще нативнее, еще триммленнее, в общем тоже nativeout и selfcontained deployment тоже проимпровили. -1875.60 1877.60 SPEAKER_01 Такие небольшие изменения. -1877.60 1888.32 SPEAKER_00 Там получше сделали разметку собственно, что можно триммить в стандартной библиотеке F# и F# core, за счет чего там, я так понимаю, более аккуратно выкидывается и приложение с большей вероятностью не будет падать. -1888.32 1896.60 SPEAKER_01 Да-да, именно так, в принципе, весь стриминг на это и завязан, насколько хорошо у вас про аннотированные библиотеки. -1896.60 1919.88 SPEAKER_00 Давай дальше, дальше у нас, наверное, одна из самых, ну, наверное, вторая по обсуждаемости часть дотнета это, конечно, sp.net core, которую мы много раз обсуждаем и которая всегда заслуживает довольно большой кусок подкаста по мере прихода каждого превью, поэтому в релизе наверняка в нем тоже много всего интересного. -1919.88 1934.20 SPEAKER_01 Да, насобирали большую интересную пачку, прежде всего хотелось бы отметить, что добавили стандартный rate limiting, это возможность каким-то образом ограничивать те входящие запросы, которые идут в ваш sp.net приложение. -1934.20 1948.76 SPEAKER_01 Из интересного есть огромное число алгоритмов, которые уже внедрили в стандартную поставку, в стандартную библиотеку, также еще большее число алгоритмов еще собираются написать или будут добавляться сторонними какими-то разработчиками. -1948.76 1953.60 SPEAKER_01 Очень гибко конфигурируется, там есть интересные полисы, которые позволяют вам настроить лимитинг. -1953.60 1968.12 SPEAKER_01 В общем, тема интересная, тема богатая, если кто-то хочет посмотреть поподробнее, кого это интересует, обязательно гляньте на официальную документацию, там уже много описано интересных специальных параметров для конфигурирования. -1968.12 1995.32 SPEAKER_01 Дальше у нас появился output caching, он в принципе уже у нас был, но сейчас он стал намного более производительнее и лучше настраивается, потому что теперь можно настроить в зависимости от более тонких опций вашего входящего запроса, что именно вам нужно, то есть исходящего, что нужно вам кэшировать, когда это там должно протухать, когда это должно обновлять, в общем, output caching тоже отлично заимпровили. -1995.32 2024.52 SPEAKER_00 Да, тут надо сказать, что он у нас был, но он был немножко другой, у нас был response caching, то есть у нас кэшировался уже готовый, грубо говоря, сериализованный ответ, а это завезли кэширование именно результата опишек, то есть то, что вы вернули какой-нибудь там ok result или там bad result, not found, кэшировать странно, поэтому, то есть короче json, еще даже не сериализованный в json объект, а именно прям вот c# объект, как он есть. -2024.52 2049.88 SPEAKER_00 И эта штука позволяет, во-первых, в отличие от response caching, позволяет использовать разные бэкэнды для кэширования, в смысле, что не только в памяти, вы можете положить это в Redis куда угодно, там есть точки расширения для этого, а во-вторых, поскольку это кэшируется у вас прямо в приложении, то там есть прям нативные хуки, чтобы, грубо говоря, пост-запрос тут же инвалидировал все закэшированные объекты для этого же IDшника внутри вашего кэша. -2049.88 2058.20 SPEAKER_00 Короче, прям гораздо более гибкий кэш, но ценой того, что это делается у вас в приложении, а не где-то на промежуточных там проксях. -2058.20 2060.08 SPEAKER_00 Вот, но штука мощная. -2060.08 2062.28 SPEAKER_01 Да, богатая тема. -2062.28 2082.04 SPEAKER_01 Еще к нам завезли декомпрессию, но декомпрессия респонса у нас уже была, вот сейчас мы теперь можем декомпрессить реквесты, то есть если к вам пришел какой-то входящий запрос, у которого контент как-то был сжат, то теперь его можно элементарно хорошо и прозрачно разжать. -2082.04 2092.32 SPEAKER_01 Включилась и поддержка HTTP/3, раньше она была в экспериментале, теперь это встроенная поддержка, то есть это последняя версия HTTP протокола, который основан на квике. -2092.32 2100.40 SPEAKER_01 Теперь его можно использовать в различных ваших каких-то случаях, если вам вдруг это нужно, то официальная зарелиженная поддержка. -2100.40 2114.64 SPEAKER_01 При этом у нас будет еще HTTP/2 WebSockets, это новый транспорт, который позволяет вам запускать WebSockets по уже отлаженному HTTP/2. -2114.64 2122.04 SPEAKER_01 И мы добавили, то есть ISP.NET команда добавила новый WebTransport, который называется WebTransport. -2122.04 2130.64 SPEAKER_01 Вот, специальный протокол общения, который построен на датограммах поверх HTTP/3, и он сейчас находится в глубоком эксперименте. -2130.64 2134.04 SPEAKER_01 Показывает цифры довольно интересные, но посмотрим, что там с ним будет. -2134.04 2146.04 SPEAKER_01 В общем, если вы хотите его включить, то уже в текущем релизе можете с помощью экспериментального флага переключить, включить поддержку WebTransport и потестировать, допустим, на своих нагрузках со своими данными, которые есть у вас. -2146.04 2155.24 SPEAKER_01 Очень много изменений коснулось минимум API, почему-то его все время улучшают очень активно, в отличие от стандартного MVC подхода. -2155.24 2164.04 SPEAKER_01 Что-то я боюсь, что с такой эффективностью, с таким рвением, Microsoft делает ставку на то, что MVC развиваться больше не будет. -2164.04 2167.88 SPEAKER_00 А про это у меня всегда есть что добавить. -2167.88 2193.16 SPEAKER_00 Про это можно посмотреть видосик в .NET Conf видео, есть отдельный видосик, называется Architects Panel, где Дамиан Эдвардс, Дэвид Фаулер и кто-то третий, я забыл кто, как раз обсуждают всякие штуки типа Minimal API, MVC, Green 3D, если вам интересно, Дэвид Фаулер сейчас с ними экспериментирует. -2193.16 2204.00 SPEAKER_00 Короче, это тоже полчасовое или около 40-минутное что-ли видео, посмотрите, тоже очень неплохо узнать, что думают главные ISP-NET архитекторы. -2204.00 2207.36 SPEAKER_01 Ну, посмотрим, да. -2207.36 2222.88 SPEAKER_01 Из Minimal API у нас добавились фильтры, с помощью которых можно организовать Cross-Cutting Concern Code, то есть можно запускать какие-то ваши хуки, какие-то ваши делегаты перед каждым роутом и после выполнения каждого роута. -2222.88 2234.08 SPEAKER_01 У нас появились типизированные результаты, это строго типизированный классик, который умеет возвращать результаты, умеет их грамотно кэшировать и красиво форматировать и все так далее. -2234.08 2240.96 SPEAKER_01 Вот казалось бы типичный пример, почему бы такие Type Result не сделать для MVC тоже, но они поддерживаются только в Minimal API. -2240.96 2245.16 SPEAKER_01 Никаким образом к Minimal API, грубо говоря, отношения не имеют. -2245.16 2250.68 SPEAKER_01 Мы везде хотим возвращать нормальные респонсы с какими-нибудь закэшированными, оптимизированными ответами. -2250.68 2252.88 SPEAKER_00 Почему это было не сделать для MVC, непонятно. -2252.88 2254.44 SPEAKER_00 По-моему, ты можешь их использовать в MVC. -2254.44 2259.00 SPEAKER_00 В MVC же ты же этот I-Action Result, насколько я помню, возвращаешь. -2259.00 2260.00 SPEAKER_01 Именно так. -2260.00 2262.88 SPEAKER_01 Насколько я знаю, что вот эти Strong Result, они не реализуют I-Action Result. -2262.88 2266.24 SPEAKER_01 То есть там нужен какой-нибудь конвертер делать или оберточку влечеть в этом духе. -2266.24 2267.24 SPEAKER_00 Почему бы не реализовать? -2267.24 2268.24 SPEAKER_00 По-моему, можно. -2268.24 2274.88 SPEAKER_00 По-моему, я вот, надо посмотреть мое тестовое приложение на GitHub, примерно там же, которое я делал для доклада. -2274.88 2286.60 SPEAKER_00 По-моему, я что-то там возвращал, такое достаточно строго типизированное, типа JSON Result точка, что-то там, или просто JSON скобочка, что-то там, и оно вполне возвращалось. -2286.60 2288.32 SPEAKER_00 Так что, может быть, они в семерке сделали, что реализуют. -2288.32 2290.20 SPEAKER_01 Ну, может быть. -2290.20 2294.60 SPEAKER_01 Будет хорошо, если так, чтобы они все-таки не делили мир на две несовместимые части. -2294.60 2298.84 SPEAKER_01 Было бы хорошо, чтобы если фичу можно поддержать и там, и там, ее поддерживали бы и там, и там. -2298.84 2301.84 SPEAKER_01 Поэтому от этого бы все только выиграли. -2301.84 2302.84 SPEAKER_01 Погнали дальше. -2302.84 2304.60 SPEAKER_01 У нас появились road-группы. -2304.60 2314.16 SPEAKER_01 То есть это специальный способ, когда можно ваши minimal API-хендлеры объединить в какую-то одну группу, ей можно дать какой-нибудь общий префикс. -2314.16 2321.20 SPEAKER_01 Ну вот, мы приходим к тому, что у нас появляются некие подобия контроллеров, от чего, собственно, и убегали. -2321.20 2322.92 SPEAKER_01 Другой большой раздел – это gRPC. -2322.92 2326.80 SPEAKER_01 В gRPC самым главным нововведением было JSON-транскодинг. -2326.80 2334.88 SPEAKER_01 Это специальный сервис, специальная схема, которая позволяет вам из вашего gRPC сервиса выставить наружу JSON-бейст API. -2334.88 2339.24 SPEAKER_01 То есть якобы, как будто это ваш REST API сервис. -2339.24 2349.36 SPEAKER_01 Вот таким образом мы пытаемся обмануть клиентов, которые не поддерживают новомодные протоколы, там, HTTP/3, gRPC, прочие компрессии и прочие глупости. -2349.36 2358.76 SPEAKER_01 Вот мы можем сделать какой-нибудь совместимый такой JSON-бейст API и с помощью него поддержать старых клиентов. -2358.76 2376.20 SPEAKER_01 Также интересная штука, что сверху на этот JSON-транскодинг можно нацепить OpenAPI, то есть сгенерить какую-нибудь свагер-спецификацию и действительно прикинуться, что это вообще настоящие JSON-бейст контроллеры, JSON-API. -2376.20 2378.40 SPEAKER_01 Вот, тоже забавная вещь. -2378.40 2380.92 SPEAKER_01 Также в gRPC у нас добавились health-чеки. -2380.92 2387.84 SPEAKER_01 Теперь можно там репортить, проверять, каким образом себя чувствует gRPC сервер. -2387.84 2391.48 SPEAKER_01 И JSON-API клиент научился добавлять credentials. -2391.48 2398.48 SPEAKER_01 То есть можно отсылать authentication request на сервер с помощью барьер-токена. -2398.48 2400.72 SPEAKER_01 Тоже полезная штука. -2400.72 2403.20 SPEAKER_01 Не отстает от всех этих красавцев Blazor. -2403.20 2412.40 SPEAKER_01 Он научился генерить custom-ные элементы для того, чтобы создать стандарт HTML custom-элемент. -2412.40 2421.32 SPEAKER_01 То есть это специальные такие компоненты, которые позволяют Blazor-ным компонентам прозрачно интегрироваться в Java-бейст приложения. -2421.32 2437.12 SPEAKER_01 В общем, он может подстраиваться под те существующие HTML-элементы и может быть даже как-то обманывать существующие фреймворки и интегрироваться вместе с ними. -2437.12 2446.48 SPEAKER_01 В общем, тоже полезная фишка, которая позволит более плотно юзать уже существующие Java UI-ные фреймворки и вот как-то подмешивать к нему Blazor. -2446.48 2450.72 SPEAKER_00 Давай только мы не будем использовать существующие Java UI-ные фреймворки, а хотя бы JavaScript-овые. +0.00 10.72 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Радио.нет выпуск номер 62. +10.72 13.20 "Анатолий Кулаков" Сегодня в студии будет Анатолий Кулаков. +13.20 14.20 "Анатолий Кулаков" И Игорь Лобутин. +14.20 15.20 "Анатолий Кулаков" Всем привет. +15.20 25.36 "Анатолий Кулаков" Сначала хотелось бы поблагодарить всех наших помогаторов – Александр, Сергей, Владислав, Алексей, Шевченко Антон, Илья и Гурий Самарин, а также всех тех, кто пожелал остаться неизвестными. +25.36 30.64 "Анатолий Кулаков" Друзья, большое спасибо за помощь и эти выпуски выходят в частности благодаря вам. +30.64 38.72 "Анатолий Кулаков" Сегодня у нас немножко необычный будет выпуск, и в том же самом смысле обычный, потому что будем говорить мы про .NET и про C#. +38.72 43.16 "Анатолий Кулаков" Ну, в принципе, как и всегда в нашем подкасте мы обсуждаем именно это. +43.16 66.16 "Анатолий Кулаков" Но сегодня мы поговорим как раз-таки про конференцию .NET Conf 2022, на котором было представлено в частности .NET 7, C# 11 и множество вокруг этого всего от лзов, технологий, какие-то новые библиотеки, планов и прочего-прочего. +66.16 80.64 "Анатолий Кулаков" Наверное, стоит сразу на берегу оговориться, что подробно мы обсуждать каждую тему не будем, потому что этим мы как раз-таки и занимались целый год с прошлого релиза .NET, поэтому кому интересно, можете смело переслушивать наши подкасты там за последний год. +80.64 90.92 "Анатолий Кулаков" Информация там практически вся актуальная, не устарела, и где мы в детальностях разобрали в принципе все те новинки, которые сейчас уже предстали перед нами. +90.92 105.56 "Анатолий Кулаков" Цель нашего сегодняшнего выпуска, наверное, быстро пробежаться и в общем обозреть, что в итоге получилось, что у нас за релиз, что он за собой потащил, какие инструменты подтянулись и что он нам вообще готовит, чем мы на ближайший год будем пользоваться. +105.56 106.56 "Анатолий Кулаков" Правильно я говорю? +106.56 107.84 "Анатолий Кулаков" Да, все так. +107.84 120.60 "Игорь Лабутин" Мы попробуем, так скажем, рассказать про инструменты, тулзы, новинки, библиотеки, фреймворки, которые каким либо образом обновились. +120.60 126.08 "Игорь Лабутин" Действительно, наверное, 90%, если не больше, мы уже каким-то образом в этом подкасте упоминали. +126.08 142.36 "Игорь Лабутин" Но составить цельную картину, составить полное понимание, что же у нас такое .NET 7, возможно, это как-то проще запомнить, когда теперь оно свелось все в единый релизный .NET 7, теперь этим можно начинать пользоваться, продакшене, все такое. +142.36 145.44 "Игорь Лабутин" Так что как раз на этом мы все это и будем смотреть. +145.44 155.48 "Анатолий Кулаков" Ну, я напоминаю, что следующий .NET, который через годик будет, он уже будет LTS, и вот там будет, наверное, уже и больше фич, и больше клиентов, и больше переводов. +155.48 157.28 "Анатолий Кулаков" Ну, то есть LTS, он в Африке LTS. +157.28 173.92 "Анатолий Кулаков" Вот, и чтобы не пропустить этот момент, чтобы, опять же, ушами не хлопать, когда выйдет релиз, смело подписывайтесь на наш подкаст, не теряйте ни одного выпуска, а мы, соответственно, будем вас практически каждый выпуск посвящать в те новинки, которые ждут на вас в LTS. +173.92 180.56 "Анатолий Кулаков" Поэтому рассказывайте о нас своим друзьям, нам шарри, репост, сабскрайб, колокольчики, всеми возможными способами. +180.56 187.36 "Анатолий Кулаков" Подписывайтесь, нам будет приятно, и следите за нашими выпусками, мы будем держать вас в курсе. +187.36 192.28 "Игорь Лабутин" Начнем, давай на самом деле, действительно, вот мы тут говорим LTS, не LTS, LTS, не LTS. +192.28 197.40 "Игорь Лабутин" У нас текущий релиз, это не LTS, как он правильно называется, знаешь? +197.40 198.40 "Игорь Лабутин" - СТС. +198.40 219.08 "Игорь Лабутин" - СТС, да, ну то есть он раньше назывался Current, теперь он должен называться STS, это LTS, это у нас Long Term Support, то есть релиз, который поддерживается три года с момента выпуска, а Current, который не LTS, или теперь он называется STS, он поддерживается полтора года, то есть ближайший год до ближайшего LTS и еще полгодика после этого, чтобы дать вам время перейти. +219.08 231.96 "Игорь Лабутин" STS это не Short Term Support, это Standard Term Support, чтобы вы понимали, но я никогда не видел практически, чтобы использовали термин Current, так что, скорее всего, STS тоже вряд ли сильно будут использовать и просто говорить LTS или Non-LTS. +231.96 253.80 "Игорь Лабутин" Релиз этот, который семерка, он большой, в него довольно много контрибьюшенов и Microsoft отдельно подчеркивает, что очень много всяких open-source внешних контрибьюшенов, то есть в этом релизе поучаствовало по каким-то замерам порядка 8900 внешних контрибьюторов, которые принесли 28000 контрибьютов. +253.80 266.60 "Игорь Лабутин" Конечно, там, скорее всего, распределение не такое, что все поровну, но почти 9000 внешних человек поучаствовали в том или ином виде в развитии этого релиза, и это прикольно. +266.60 295.56 "Игорь Лабутин" Дальше, основная цель команды это сделать более-менее унифицированный SDK, то есть чтобы вам не нужно было ставить там SDK такой, SDK секой, SDK эдакий, чтобы вы просто ставите .NET SDK и в нем добавляете, возможно, какие-то нужные части, мы говорили про такую тему как ворклоуды, то есть части SDK идут отдельно, они не ставятся сразу, их нужно добавить потом отдельно, и потом вы полученный, собственно, комплект тулов можете использовать для разработки для тех или иных платформ. +295.56 300.36 "Игорь Лабутин" И в частности, одной из платформ, над которой велась довольно большая работа, был ARM64. +300.36 328.84 "Игорь Лабутин" Эта штука, она сейчас трендовая, во-первых, она трендовая в лэптопах в каком-то смысле, потому что там потихонечку армы становятся популярные там, ну и на серверах тоже, дело не отстает, там в Амазоне есть соответствующие, как они, гравитоны, да, в Ажуре, по-моему, тоже что-то появилось, не помню как называется, Ажур Ампер, по-моему так. +328.84 356.40 "Игорь Лабутин" И Microsoft работает над тем, чтобы .NET на ARM64 работал ну с той же скоростью, как на x64, потому что в рекламе всегда говорится, что ARM процы вам будут дешевле, потому что они потребляют меньше энергии и всё такое, но при этом в старых версиях .NET, которые уже начинали поддерживать ARM64, они, конечно, потребляют меньше электричества, работают эффективнее, но .NET на них работал существенно медленнее, и поэтому хорошо, если тон оттуда и выйдет, а то и медленнее будет. +356.40 361.40 "Игорь Лабутин" Цель была добиться того, чтобы перформанс был похож на x64. +361.40 380.84 "Игорь Лабутин" Там были проблемы с атомиками, ARM64 до некоторой версии не поддерживал атомарные записи чтения, ну в смысле типа compare and swap, или load and store, не помню точно, но ещё какую-то из них он не поддерживал, в какой-то версии начал поддерживать, и в .NET это добавили. +380.84 402.12 "Игорь Лабутин" В векторизацию добавили, поддержку векторных операций, и в результате получили, не только эти два изменения, конечно, было много ещё других, получили, что сейчас по результатам замеров на .NET 7, перформанс подбирался и подбирался, подбирался по мере превьюшек к перформансу на x64, и наконец-таки сравнялся, и даже чуть-чуть превзошёл. +402.12 411.48 "Игорь Лабутин" Так что в общем-то можно сказать, что более-менее цель достигнута с точки зрения поддержки ARM64. +411.48 431.88 "Игорь Лабутин" Дальше вторая причина, проблема, не знаю, цель с Unified SDK в том, что этот SDK должен быть унифицирован вообще для всех платформ, куда мы ставимся, то есть работаем ли мы на Windows, работаем ли мы на Linux, на Mac, SDK, ну в смысле инсталлятор, конечно, разный, но с точки зрения того, что вы получаете, должно быть всё более-менее одинаково. +431.88 437.68 "Игорь Лабутин" В этом смысле есть довольно большая работа, которая делается для Linux, для Ubuntu. +437.68 454.24 "Игорь Лабутин" Начиная с шестёрки, там .NET поддерживается уже в прям в нативном менеджере пакетов, то есть не нужно качать инсталлятор, можно просто сказать "Up to install .NET 6", и начиная с этого релиза у нас есть прикольные компактные образы про Ubuntu, мы про них поговорим ближе к концу. +454.24 473.28 "Игорь Лабутин" С точки зрения таргетинга или одной из тоже целей .NET 7, конечно, является большое хайповое движение под названием Cloud Native, то есть всё, что мы пишем, если мы пишем для Web или ещё для чего-то, должно быть, конечно же, Cloud Native. +473.28 485.32 "Игорь Лабутин" И тут возникает несколько моментов, которых .NET был, ну не то чтобы прям медленный или неудобный, но который всегда можно было что-то улучшить, вот поулучшали. +485.32 488.12 "Игорь Лабутин" Во-первых, поулучшали поддержку контейнеров, поговорим попозже. +488.12 499.60 "Игорь Лабутин" Во-вторых, почему-то в анонсе именно в этом месте Microsoft упоминает такой фреймворк как Carlins, мы про Carlins тоже чуть дальше поговорим, почему он в Cloud Native находится, я не очень понял, но тем не менее. +499.60 503.76 "Игорь Лабутин" Зато там точно находится штука, которая должна быть, это работа с JSON. +503.76 512.84 "Игорь Лабутин" Пишите ли вы веб-сервисы, или может быть даже если вы пишете какие-то command-line тулы, как ни странно, или что-нибудь ещё, вы довольно много всегда работаете с JSON. +512.84 519.72 "Игорь Лабутин" И в Dota 7 JSON, стандартный JSON-сериализатор, получил довольно много улучшений и изменений. +519.72 535.68 "Игорь Лабутин" Во-первых, там теперь стала возможна поддержка полиморфных типов, вы можете указать на родительском типе специальный атрибутик JSON Derived Types и указать список, соответственно, дочерних типов, которые вы хотите уметь реализовывать. +535.68 540.80 "Игорь Лабутин" Это будет такая статическая полиморфиза, можно сделать динамически, чуть более сложно. +540.80 552.04 "Игорь Лабутин" И есть ещё специальный атрибут JSON Polymorphic, который позволяет настроить на самом деле то, как всё это работает, что делать, если встретился неизвестный тип, как вообще определять, что за тип. +552.04 559.12 "Игорь Лабутин" Это делается всё с помощью специального полидискриминатора, как его назвать, ну и в общем, вся кастомизация делается через него. +559.12 563.24 "Игорь Лабутин" А кроме этого ещё можно делать кастомизацию непосредственно контракта. +563.24 599.40 "Игорь Лабутин" То есть если, например, у вас есть какой-нибудь класс, может быть ваш, может быть из вообще сторонней библиотеки, в котором у вас нет исходников, но вы хотите либо ваш класс как-то очень хитро сериализовывать в JSON, либо вы хотите этот сторонний класс как-то хитро сериализовывать или десериализовывать из JSON, то теперь стало возможно написать специальный TypeResolver, который сериализатор будет дёргать в моменты, когда он сериализует объекты этого класса, и в этом резолвере определять вообще, что делать с объектом, причём там доступно значение самого объекта, то есть там можно намутить логику типа там "если поле объекта true, то два соседних поля сериализовывать не надо" или наоборот. +599.40 608.12 "Игорь Лабутин" То есть всякую сложную логику я думаю, что на этой штуке можно там практически полное поведение Newtonsoft'а воспроизвести, хотя на 100% понятно не уверен. +608.12 628.96 "Игорь Лабутин" А при апдейте .NET естественно обновляется core библиотека, BaseClass library, там довольно много, понятное дело, всяких довольно мелких улучшений, несколько штук были признаны достаточно значимыми, чтобы попасть в главный анонс про релиз .NET 7. +628.96 637.08 "Игорь Лабутин" Это nullable аннотации на весь namespace Microsoft Extensions, если вы что-то оттуда используете, знайте, теперь это что-то поддерживает nullable. +637.08 654.00 "Игорь Лабутин" В типы работы с датой и временем, то есть date/time и timeonly/timespan завезли поддержку micro и nanosecond, то есть раньше всё, что меньше, чем миллисекунды, нужно было оперировать тиками, теперь можно работать с микро и наносекундами, есть соответствующие API, ну и оверлоды конструкторов и так далее. +654.00 672.32 "Игорь Лабутин" В iMemoryCache завезли метрики, я вот на самом деле в своих проектах всё чаще и чаще замечаю, что мы кэшируем через iMemoryCache, и соответственно было бы здорово выставить метрики наружу, в какой-нибудь Prometheus или ещё куда-нибудь, чтобы следить вообще, в каком состоянии эти кэши, теперь это можно сделать. +672.32 683.28 "Игорь Лабутин" Класс, соответственно, ну интерфейсы класса имеют соответствующие методы, которые вы можете использовать, чтобы всё это выставить наружу в нормальный ваш коллектор-метрик. +683.28 695.68 "Игорь Лабутин" Ну и поддержка tar-архивов, понятно, что поддержка Linux должна быть, поэтому tar-архивы на Linux довольно популярны, вот оно там есть, плюс оно ещё потребовалось для докера, как оказалось. +695.68 701.92 "Игорь Лабутин" В SDK в целом изменений не так много, именно с точки зрения тулинга, вот .NET тулинга. +701.92 707.88 "Игорь Лабутин" Понятно, что там есть всякие разные изменения, типа .NET watch, там всякие смайлики завезли, это в одном из первых превьюшек, мне кажется, было. +707.88 710.64 "Игорь Лабутин" Hot reload, там вот теперь всякие иконочки рисуют. +710.64 723.32 "Игорь Лабутин" Появилась возможность нормального автодополнения в команде .NET new, там теперь какой-то более клёвый парсер и тап комплешн. +723.32 743.44 "Игорь Лабутин" Ну и темплетики, то есть шаблоны проектов, которые вы можете создавать в .NET new и которые вы можете, честно говоря, создавать сами, теперь можно создавать, появилось возможность ограничений, то есть можно сказать, что если вы там создаете в таком-то ворклоуде, то вот этот шаблон теперь неприменим, ну и так далее. +743.44 748.84 "Игорь Лабутин" Есть возможность какую-то условную, грубо говоря, доступность шаблонов организовать. +748.84 753.60 "Игорь Лабутин" Последняя секция в большой статье анонса — это про перформанс. +753.60 762.36 "Игорь Лабутин" Куда же без перформанса, мы весь год говорили про перформанс, по-моему, ни один превью у нас не был без новостей о перформансе, то ли иные штуки. +762.36 766.68 "Игорь Лабутин" Ну в перформансе три главных вещи, которые произошли. +766.68 768.56 "Игорь Лабутин" Во-первых, это онстайк реплейсмент. +768.56 796.60 "Игорь Лабутин" У нас был уже то, что называется tired compilation, ну и здесь, это было уже в шестом .NET, но проблема с ним была в том, что он не мог подменять функции, то есть смысл в чём, что если какая-то функция или какой-то кусок кода используется чаще, чем обычно, то есть количество вызовов этого кода превышает некоторый порог, то он перекомпилировался более оптимально и ссылка на него подменялась. +796.60 800.60 "Игорь Лабутин" Проблема в том, что если вы это сделали для функции, которая сейчас исполняется, ну как бы подменить её сложно. +800.60 801.60 "Игорь Лабутин" Вот теперь можно. +801.60 813.44 "Игорь Лабутин" .NET 7 умеет это делать, если у вас есть большой цикл в функции, то как раз .NET 7 умеет теперь перекомпилировать и подменять такие функции, даже пока они выполняются. +813.44 816.84 "Игорь Лабутин" File Guided Optimization туда же и Native OUT. +816.84 837.20 "Игорь Лабутин" Native OUT в семёрке получил прям очень хороший boost, он работает, ну как я понял, довольно неплохо для всяких разных таких классических ворклоудов типа консольных приложений, ASP.NET Core, а не, если ASP.NET Core как раз не работает, там Reflection сейчас много пока ещё, и про это ведутся активные разговоры, как бы так сделать, чтобы заработало. +837.20 840.80 "Игорь Лабутин" Но есть эксперименты по всяким WinForm и прочим. +840.80 856.76 "Игорь Лабутин" При этом Native OUT там работали довольно хорошо над всяким триммингом и прочим, пустая консольная приложенка, которая скомпилирована в Native OUT на винде, сейчас занимает 3,6 мегабайта, то есть в общем-то уже, ну, более-менее разумный размер. +856.76 871.00 "Игорь Лабутин" Но понятно, что как только вы начнёте тащить внутрь всякие зависимости, в зависимости от того, насколько хорошо для них определены настройки тримминга, размер может резко поползти наверх, потому что все эти зависимости будут упакованы в этот single file. +871.00 875.08 "Игорь Лабутин" Ну и говоря про performance, нельзя не сказать, конечно, про бенчмарки. +875.08 885.32 "Игорь Лабутин" Если вы посмотрите открывающий видосик с .NET Conf, там будет сказано, что .NET 7, он, короче, круче, крут-крут-крут, он круче Go, он круче Node.js, он круче кого? +885.32 886.32 "Игорь Лабутин" Java. +886.32 888.24 "Игорь Лабутин" Понятно, ну короче, мы круче всех. +888.24 902.16 "Игорь Лабутин" Это всё основано на техэмпауэре, верить ему надо с большими-большими оговорками, и там на самом деле несколько тестов на ASP.NET Core, смотреть надо только на некоторые, и смотря что вы хотите добиться, какую информацию вы хотите узнать. +902.16 918.16 "Игорь Лабутин" Про это есть отдельная большая статья, мы про неё, наверное, поговорим, постараемся в следующем выпуске, поэтому если вам интересно что-то узнать про техэмпауэр, и как Microsoft, и как вообще ASP.NET Core с ним справляется, дожидайтесь следующего выпуска, там мы постараемся всё подробнейшим образом рассказать. +918.16 922.24 "Анатолий Кулаков" Слушай, а почему ты ничего про майонез, о легионах не сказал? +922.24 924.12 "Анатолий Кулаков" Тоже большая работа была проделана, почему это не +924.12 928.40 "Игорь Лабутин" упомянули? Почему это не упомянули на главной странице, я даже не знаю. +928.40 934.24 "Игорь Лабутин" То есть, это действительно большая работа, в докладе, кстати, который я на dotnext читал, я про это упоминал. +934.24 951.48 "Игорь Лабутин" Про это, наверное, так в паре слов не расскажешь, но смысл в том, что да, у нас теперь регионы исключены по умолчанию, теперь у нас память выделяется не большими сегментами, а маленькими кусочками, по 4 или сколько-то мегабайт, и в теории на вас это повлиять должно только в лучшую сторону, но может быть и в худшую. +951.48 961.84 "Игорь Лабутин" Если я правильно помню наше рассуждение из каких-то превью, из статьи Маони, что на старте приложения теперь может потреблять побольше памяти, зато более агрессивно отдавать ее в процессе работы. +961.84 968.08 "Игорь Лабутин" Так что тестируйте ваше приложение на новых режимах работы ГЦ и смотрите, что получилось. +968.08 983.00 "Анатолий Кулаков" Ну, я думаю, надеюсь, что все-таки там не так все плохо, Майонь обычно не ошибается, всегда делает на совесть, поэтому хорошее обновление, хорошие анонсики, но, наверное, самое интересное, чего все ждут, это, конечно же, изменения в языке. +983.00 985.40 "Анатолий Кулаков" Что нас в C# 11 порадовало? +985.40 1005.60 "Игорь Лабутин" Да, в C# 11 у нас довольно много всего завезли, причем я боюсь, что я не буду сейчас еще раз все аккуратно рассказывать смысл всех фич, потому что их довольно много, их, по-моему, 14 или 15 штук, таких, которые оказались достойны упоминания во всяких статьях. +1005.60 1008.28 "Игорь Лабутин" И вот с нее, ну, кратенько давайте перечислим. +1008.28 1011.80 "Игорь Лабутин" Мы про них, про все уже говорили, на самом деле, много раз. +1011.80 1014.00 "Игорь Лабутин" Для начала начнем работать со строками. +1014.00 1029.36 "Игорь Лабутин" У нас теперь появились UTF-8 литералы, то есть если вам вдруг зачем-то нужны быстрые UTF-8 строки, вы теперь можете после обычного литерала C# дописать U8, и вы получите сущность, которая имеет тип не string, а тип read-only span от байтов. +1029.36 1043.44 "Анатолий Кулаков" Ну, скорее всего, это вам нужно где-нибудь на границах приложения, например, если вам нужно быстро отдать в сокет какую-нибудь строку без лишних конвертаций между UTF-16 и UTF-8, наверное, полезная вещь, почему нет? +1043.44 1047.20 "Игорь Лабутин" Да, все так, вот ровно для этого это и было сделано, вероятно, поэтому... +1047.20 1050.80 "Игорь Лабутин" И на этом, кстати, основа техампа русский матчмарк, в частности. +1050.80 1053.72 "Игорь Лабутин" Дальше у нас появились raw string литералы. +1053.72 1058.40 "Игорь Лабутин" Мы могли раньше задать строку, в которой вы задаете, например, JSONчик. +1058.40 1062.28 "Игорь Лабутин" Но проблема в том, что JSON содержит много кавычек, вы должны их экранировать через бэкслэш. +1062.28 1076.08 "Игорь Лабутин" Можно было написать вначале строки символ "собаки", после чего вам не нужно было ничего экранировать, кроме, опять же, кавычек, потому что строка ограничена кавычками, но в этом случае нужно кавычки игнорировать двойной кавычкой, ну, в смысле, вместо одной писать две. +1076.08 1077.72 "Игорь Лабутин" И так и так неудобно. +1077.72 1086.64 "Игорь Лабутин" Теперь у нас появились raw string литералы, это вы можете начать строку с трех и более кавычек, написать внутри все что угодно и закончить таким же количеством кавычек. +1086.64 1094.32 "Игорь Лабутин" Любое количество кавычек меньше, чем использовано при открытии строки, считается простым литералом и не требует экранирования. +1094.32 1098.28 "Игорь Лабутин" Второй момент, они могут быть многострочными. +1098.28 1102.64 "Игорь Лабутин" В этом случае открывающие и закрывающие кавычки должны быть на своей отдельной строке. +1102.64 1112.04 "Игорь Лабутин" То есть вы объявляете переменную, пишете равно, там три кавычки, например, дальше со следующей строки начинаете текст, и потом в конце на отдельной строке закрываете тремя кавычками. +1112.04 1119.80 "Игорь Лабутин" Положение этих закрывающих трех кавычек тоже важно, в зависимости от этого компилятор будет откусывать лишние начальные пробелы у всех строк внутри. +1119.80 1130.08 "Игорь Лабутин" Внутри этих литералов можно использовать string interpolation, понятное дело, для этого вы перед этими тремя кавычками запихиваете нужное количество долларов, один, два, три и так далее. +1130.08 1136.28 "Игорь Лабутин" Чем больше долларов вы запихнете, тем больше последовательных фигурных скобок вам можно использовать внутри без того, чтобы это считалось подстановкой. +1136.28 1148.88 "Игорь Лабутин" Но для того, чтобы работала подстановка, то есть если вы, например, пишете строку с трех долларов и трех кавычек, то чтобы внутри string interpolation работал, нужно тремя фигурными скобками обозначать места, где будет string interpolation. +1148.88 1153.12 "Игорь Лабутин" Если у вас много interpolation, наверное, выгоднее поменьше долларов использовать. +1153.12 1166.12 "Игорь Лабутин" Но если у вас, грубо говоря, огромный JSON, куда подставляется два каких-нибудь поля, то может быть имеет смысл как раз использовать тройной такой доллар и в одном или двух местах указать три открывающихся фигурных скобки, а весь остальной JSON будет из обычных одинарных. +1166.12 1174.32 "Анатолий Кулаков" На самом деле полезная штука, я в всяких скриптовых языках часто таким пользуюсь, где нужно организовать какие-то большие темплейты и еще что-то. +1174.32 1184.20 "Анатолий Кулаков" Единственное, что меня до сих пор смущает, это вот эта безумная магия, когда нужно там три кавычки поставить с определенным отступом, если отступ другой, то поведение внутри меняется. +1184.20 1201.64 "Анатолий Кулаков" Если вдруг вы поставили три кавычки и два вопросительных знака, это совсем не то, что один вопросительный знак, и вот эти всякие тонкости, они, конечно, я думаю, будут не один мозг еще убьют, но надо признать, что команда попыталась выжать максимум из этой фичи, попыталась сделать максимально удобно. +1201.64 1207.52 "Анатолий Кулаков" Ну посмотрим, как на практике этот баланс сумели ли они соблюсти между понятностью и используемостью. +1207.52 1223.64 "Игорь Лабутин" Да, там на самом деле компилятор очень старается, если вы, например, поставите закрывающую кавычку, закрывающие три кавычки на последней строке слишком далеко вправо, и у вас нормальный контент начинается левее, то там компилятор, раз ошибка компиляции будет писать, что у вас кавычка не там стоит. +1223.64 1224.64 "Игорь Лабутин" Короче, они постарались. +1224.64 1227.84 "Игорь Лабутин" Дальше, про мемберы. +1227.84 1241.72 "Игорь Лабутин" Мемберы у нас теперь могут быть не только там static, readonly, вот это все, они не только могут быть там с getset или init этими модификаторами, но еще они могут теперь быть required. +1241.72 1251.16 "Игорь Лабутин" Required означает, что этот мембер должен быть обязательно интеллизирован либо через конструктор, либо через object initializer. +1251.16 1273.64 "Игорь Лабутин" Причем проблема состоит в том, что через конструктор оно как-то работает фигово, в том смысле, что если у вас есть конструктор, который принимает два поля, ну даже не два, допустим у вас есть пропертиа, которая обозвонка required, у вас есть конструктор, который принимает какой-то аргумент и проставляет в это поле, компилятор не поймет, что таким образом эта штука интеллизируется, если у вас есть пустой конструктор дополнительно. +1273.64 1279.56 "Игорь Лабутин" И нужно такой конструктор помещать дополнительным атрибутом setsRequiredMembers. +1279.56 1294.24 "Игорь Лабутин" Я попытался, вот после доклада меня спрашивали, зачем вообще такая штука, зачем нужен был атрибут, что-то я быстро не смог найти, надо читать всякие обсуждения, ну читать и слушать обсуждения именно API-дизайна, почему так было сделано. +1294.24 1302.08 "Игорь Лабутин" Не получилось у меня быстро понять, зачем вот таким атрибутом, почему компилятор нельзя было научить, что все на самом деле нормально работает. +1302.08 1306.88 "Анатолий Кулаков" Но смысл в том… Ну по идее это сложный flow-анализ, у нас в компиляторе сейчас нигде нет flow-анализа. +1306.88 1321.16 "Игорь Лабутин" Ну сложный, не сложный, но в общем да, так или иначе это было сделано, в результате надо понимать, что если у вас есть requiredMembers и есть вот такой атрибутик на каком-то конструкторе, то у вас никто не гарантирует, что requiredMembers будут заполнены, к сожалению. +1321.16 1323.08 "Игорь Лабутин" Они могут остаться непроинтеллизированы. +1323.08 1328.52 "Игорь Лабутин" Дальше, про field'ы, у нас появились reffield'ы и scopedref'ы. +1328.52 1337.20 "Игорь Лабутин" Я не буду сейчас сильно углубляться, что это такое, но смысл такой, в общем-то это чисто для того, чтобы нормально поддержать спаны, потому что раньше они были поддержаны с некоторым хаком. +1337.20 1347.00 "Игорь Лабутин" А scopedref'ы это как раз тот самый flow-анализ, чтобы понять, куда какие ref'ы можно отдавать выше-ниже по стэку и понимать, можно ли нельзя отдавать. +1347.00 1353.80 "Игорь Лабутин" Там фича довольно сложная, надо вдумываться, чтобы понять, я на слух не смогу ее, наверное, объяснить. +1353.80 1355.68 "Игорь Лабутин" Про типы, что у нас еще есть? +1355.68 1367.84 "Игорь Лабутин" У нас появились filescoped-типы, то есть если перед классом или структуркой написать вместо слова public или internal слово file, то такой тип будет доступен только в рамках этого файла. +1367.84 1371.88 "Игорь Лабутин" Нужно это… И зачем на практике такая штука нужна? +1371.88 1395.56 "Игорь Лабутин" Я так понял, в основном такая штука используется для source-генераторов, то есть типа тот самый partial-класс, который генерится source-генератором, он же как бы в общем-то не нужен ни для чего, кроме как для того, чтобы вписать туда код этого самого непосредственно сгенеренного метода или там чего вы аннотируете вашим атрибутикам для source-генератора. +1395.56 1409.24 "Игорь Лабутин" И вот чтобы этот класс больше нигде не светился, ни в каких interessence-ах нигде, вот его, я так понимаю, можно сгенерить со scope-file, и тогда он будет виден только в рамках того файла, куда он подставлен. +1409.24 1411.28 "Анатолий Кулаков" Интересно, а что там в ILLI получается? +1411.28 1414.88 "Анатолий Кулаков" Ведь когда мы в assembly запихиваем все это дело, у нас уже нет никакого файла. +1414.88 1425.08 "Игорь Лабутин" Да, там генерится специальное имя, которое, оно конечно глобально видимо, то есть тот факт, что его не видно в namespace в подсказках, это чисто фича Visual Studio. +1425.08 1438.24 "Игорь Лабутин" Понятно, что в атрибутах там ничего такого нету, там просто имя, в которое включен hash SHA-256 от пути к файлу в компилятор с генерированным имя. +1438.24 1441.04 "Анатолий Кулаков" Ну и namespace, конечно. +1441.04 1451.00 "Анатолий Кулаков" Ну вообще если такая вещь, которая нужна чисто для IDE, типа скрыть от interessence, они раньше делались атрибутами, и кажется, что это более разумный и вменяемый способ, чем заводить новые кейворты. +1451.00 1453.52 "Анатолий Кулаков" Зачем они нужны, если только студия должна не видеть +1453.52 1455.52 "Игорь Лабутин" это? Непонятно. +1455.52 1473.72 "Игорь Лабутин" Кстати, интересный момент, вот как раз про эту фичу есть на dotnet.conf видосик от Джаррида Парсонса, там 20 с копеечками минут, где он как раз рассказывает про дизайн такой фичи, то есть вообще у него видосик типа let's design language feature, где он показывает, про что команда думает, как она подходит к тому, как что задизайнить. +1473.72 1480.44 "Игорь Лабутин" Вот на примере файла этих скоп-тайпов можно посмотреть, как они что-нибудь делали. +1480.44 1481.44 "Игорь Лабутин" Давай дальше. +1481.44 1502.44 "Игорь Лабутин" Дальше у нас есть из мелочей nameof, которые теперь можно использовать снаружи методов, то есть если вы хотите, допустим, в атрибут указать имя параметра, а такое бывает надо для всяких там хитрых атрибутов, ну для вот nullability нужно, да, там not null if not null, когда вам нужно указать имя параметра какого-то. +1502.44 1511.24 "Игорь Лабутин" И для атрибутов, если вы хотите что-то про параметры тоже сказать, можно теперь использовать nameof, и можно использовать generic attribute. +1511.24 1520.32 "Игорь Лабутин" Ну и так, еще я забыл про лист паттерны, теперь есть у нас во всяких из выражениях можно указывать списки. +1520.32 1536.76 "Игорь Лабутин" Работает это немножко кривовато, то есть это хорошо работает на массивах, это не очень хорошо работает на списках, то есть там есть фича, которая позволяет, например, сказать, что этот массив из квадрата на скобках открывается там, не знаю, 0, точка, точка, var y. +1536.76 1541.80 "Игорь Лабутин" И вот в var y положится весь хвост массива, если первый элемент 0. +1541.80 1546.92 "Игорь Лабутин" То есть таким образом можно откусить нужный кусочек массива, серединку, там край, край. +1546.92 1552.60 "Игорь Лабутин" Но проблема в том, что это работает только на коллекции, где реализован range, ну индексатор от range. +1552.60 1556.96 "Игорь Лабутин" А листы такого не реализуют, поэтому на листах такое работать, к сожалению, не будет. +1556.96 1558.24 "Игорь Лабутин" Странно, а почему? +1558.24 1559.92 "Игорь Лабутин" У листа же есть индексатор. +1559.92 1564.08 "Игорь Лабутин" У листа есть индексатор от индекса, ну от int. +1564.08 1565.08 "Игорь Лабутин" От int, да. +1565.08 1566.08 "Игорь Лабутин" А нужно? +1566.08 1567.08 "Игорь Лабутин" А нужно от range. +1567.08 1568.08 "Игорь Лабутин" А, понятно. +1568.08 1571.48 "Игорь Лабутин" Чтобы ты мог написать там квадратные скобки, 2, точка, точка 5. +1571.48 1572.48 "Игорь Лабутин" Погоди, почему не реализовать-то? +1572.48 1573.48 "Игорь Лабутин" Ничего не мешает? +1573.48 1574.48 "Игорь Лабутин" Вот это интересный момент. +1574.48 1576.16 "Игорь Лабутин" Не знаю, почему не реализовали. +1576.16 1579.96 "Игорь Лабутин" Если хотите так работать с листами, пишите своего наследника листа. +1579.96 1581.56 "Игорь Лабутин" Не знаю, почему не сделали. +1581.56 1585.16 "Анатолий Кулаков" Да нет, делайте pull request, настоящий лист, что это такое? +1585.16 1589.56 "Игорь Лабутин" Ну да, либо почитайте историю, может быть там будет написано, почему они так не сделали. +1589.56 1605.76 "Игорь Лабутин" И да, generic математика, мы про неё много раз говорили, статические абстрактные методы интерфейсов плюс generic математика, там несколько десятков интерфейсов в system numerix, которые теперь реализованы всеми стандартными примитивами, можно писать свою generic математику. +1605.76 1625.16 "Игорь Лабутин" Если вам интересно более детально посмотреть на всё это, потрогать руками, во-первых, есть официальные гайды от Microsoft, во-вторых, есть хорошая статья, ссылочка будет в описании, плюс есть GitHub репозиторий с некоторыми примерочками на седьмом linkpad, который я использовал для своего доклада на dootmxt, который недавно прошёл. +1625.16 1630.52 "Игорь Лабутин" Там тоже можно потрогать, там есть простые примеры почти на все фичи. +1630.52 1632.60 "Игорь Лабутин" Не абсолютно на все, но почти на все. +1632.60 1643.56 "Анатолий Кулаков" Не забывайте уже про ранее упомянутый тобой dotnet.conf, там куча видосиков про фреймворк, по tool, по всяким фичам языка, там тоже много чего интересного можно посмотреть. +1643.56 1649.40 "Игорь Лабутин" По-моему, там, кстати, сам Matt Storgerson рассказывает про какие-то фичи по крайней мере языка. +1649.40 1657.28 "Анатолий Кулаков" Может быть, ну соответственно у нас после языка C# есть ещё один самый главный язык, это всё-таки F#. +1657.28 1661.00 "Анатолий Кулаков" Не Visual Basic, почему-то про Visual Basic в этот раз было совсем мало. +1661.00 1664.84 "Анатолий Кулаков" Давайте посмотрим, что у нас такого интересного произошло в F#. +1664.84 1674.72 "Анатолий Кулаков" В принципе, самая главная цель, на которую были направлены авторы в этом релизе, это сделать F# как можно ближе к народу, как можно более понятным, более простым. +1674.72 1685.48 "Анатолий Кулаков" И кажется, что им это удалось, у них много было улучшений в инструментарии, особенно вокруг, в поддерживании EDE, ну и конечно же, перформанс, куда же без перформанса, всё улучшили. +1685.48 1692.40 "Анатолий Кулаков" Ещё одним большим таким направлением по развитию это была интеграция с новыми фичами C#. +1692.40 1697.44 "Анатолий Кулаков" В частности, уже упомянутый к ночи был Static Abstract Member в интерфейсах. +1697.44 1705.84 "Анатолий Кулаков" Теперь в F# в седьмом это тоже поддерживается, это один из базовых концептов для того, чтобы делать Generic Math. +1705.84 1717.08 "Анатолий Кулаков" И также поддерживает встроенные BCL-типы, которые реализуют всякие вот эти магические интерфейсы iNumber, iAdditional и прочее. +1717.08 1722.20 "Анатолий Кулаков" В общем, F# это тоже умеет понимать и тоже применять к ним всякую математику. +1722.20 1742.92 "Анатолий Кулаков" Мне вообще интересно, что сейчас спрашивают в Juno на собеседованиях, потому что после того, как Майоня там переделала всё, что только можно переделывать со всякими поколениями, после того, как у нас появились абстрактные статические методы в интерфейсах, после того, как уже нет никакой разницы между референсом и ref value, что вообще можно на собеседованиях спрашивать? +1742.92 1743.92 "Анатолий Кулаков" Как Juno валят, интересно. +1743.92 1761.88 "Игорь Лабутин" Да спрашивать, наверное, всё то же самое, про поколения спрашивать можно всё так же, но вот если тебе Juno ответит, ну у нас теперь можно из нуля и во второе поколение, потому что у нас регионы, то ты знаешь, что это либо очень начитанный Juno, либо он слушает наш подкаст, либо он просто наоборот что-то где-то слышал и надо копать дальше. +1761.88 1763.92 "Анатолий Кулаков" Или наоборот выпендривается, да. +1763.92 1767.40 "Анатолий Кулаков" Хорошо, погнали дальше. +1767.40 1771.96 "Анатолий Кулаков" Упростилась работа со Statical Result Type Parameters. +1771.96 1781.28 "Анатолий Кулаков" Это такие специальные типы параметров, которые могут заменяться во время компиляции, в отличие от обычного случая, когда заменяются они в ран тайме. +1781.28 1790.80 "Анатолий Кулаков" Тоже очень полезная штука для оптимизации, для скорости, в общем сейчас с ними стало работать намного удобнее и применяться они стали намного чаще. +1790.80 1802.08 "Анатолий Кулаков" Также был поддержан Required Keyword, про который говорил Игорь, и нет Keyword в свойствах, которые позволяют инициализировать проперти в тех или иных условиях, это все тоже F# понимает. +1802.08 1819.88 "Анатолий Кулаков" Также F# теперь умеет компилировать, то есть компилятор F# умеет генерировать reference assembly, это специальные сборки, которые содержат минимум информации, в которой есть по сути только metadata. +1819.88 1833.96 "Анатолий Кулаков" Эта metadata покрывает только публичный API, что позволяет вам просто компилировать ваше приложение с какими-то сборками, зная, что там этот публичный API точно есть, но запускаться с ними вы естественно не можете. +1833.96 1849.00 "Анатолий Кулаков" Почему это полезно, когда вы хотите например скомпилироваться на одной операционной системе, а запускаться будете на другой операционной системе, но для этого вам нужны какие-то API, которые будут на целевой естественной операционной системе, и вот как раз reference assembly в этом помогут. +1849.00 1854.32 "Анатолий Кулаков" У нас тоже там была отдельная тема, большая тема в каком-то выпуске про reference assembly, если интересно, поищите. +1854.32 1875.60 "Анатолий Кулаков" И F# уже давно умеет триммиться, он уже давно умеет запускаться под нативным кодом, ну то есть как нативный код, ну а теперь это сделали еще лучше, еще нативнее, еще триммленнее, в общем тоже nativeout и selfcontained deployment тоже проимпровили. +1875.60 1877.60 "Анатолий Кулаков" Такие небольшие изменения. +1877.60 1888.32 "Игорь Лабутин" Там получше сделали разметку собственно, что можно триммить в стандартной библиотеке F# и F# core, за счет чего там, я так понимаю, более аккуратно выкидывается и приложение с большей вероятностью не будет падать. +1888.32 1896.60 "Анатолий Кулаков" Да-да, именно так, в принципе, весь стриминг на это и завязан, насколько хорошо у вас про аннотированные библиотеки. +1896.60 1919.88 "Игорь Лабутин" Давай дальше, дальше у нас, наверное, одна из самых, ну, наверное, вторая по обсуждаемости часть дотнета это, конечно, sp.net core, которую мы много раз обсуждаем и которая всегда заслуживает довольно большой кусок подкаста по мере прихода каждого превью, поэтому в релизе наверняка в нем тоже много всего интересного. +1919.88 1934.20 "Анатолий Кулаков" Да, насобирали большую интересную пачку, прежде всего хотелось бы отметить, что добавили стандартный rate limiting, это возможность каким-то образом ограничивать те входящие запросы, которые идут в ваш sp.net приложение. +1934.20 1948.76 "Анатолий Кулаков" Из интересного есть огромное число алгоритмов, которые уже внедрили в стандартную поставку, в стандартную библиотеку, также еще большее число алгоритмов еще собираются написать или будут добавляться сторонними какими-то разработчиками. +1948.76 1953.60 "Анатолий Кулаков" Очень гибко конфигурируется, там есть интересные полисы, которые позволяют вам настроить лимитинг. +1953.60 1968.12 "Анатолий Кулаков" В общем, тема интересная, тема богатая, если кто-то хочет посмотреть поподробнее, кого это интересует, обязательно гляньте на официальную документацию, там уже много описано интересных специальных параметров для конфигурирования. +1968.12 1995.32 "Анатолий Кулаков" Дальше у нас появился output caching, он в принципе уже у нас был, но сейчас он стал намного более производительнее и лучше настраивается, потому что теперь можно настроить в зависимости от более тонких опций вашего входящего запроса, что именно вам нужно, то есть исходящего, что нужно вам кэшировать, когда это там должно протухать, когда это должно обновлять, в общем, output caching тоже отлично заимпровили. +1995.32 2024.52 "Игорь Лабутин" Да, тут надо сказать, что он у нас был, но он был немножко другой, у нас был response caching, то есть у нас кэшировался уже готовый, грубо говоря, сериализованный ответ, а это завезли кэширование именно результата опишек, то есть то, что вы вернули какой-нибудь там ok result или там bad result, not found, кэшировать странно, поэтому, то есть короче json, еще даже не сериализованный в json объект, а именно прям вот c# объект, как он есть. +2024.52 2049.88 "Игорь Лабутин" И эта штука позволяет, во-первых, в отличие от response caching, позволяет использовать разные бэкэнды для кэширования, в смысле, что не только в памяти, вы можете положить это в Redis куда угодно, там есть точки расширения для этого, а во-вторых, поскольку это кэшируется у вас прямо в приложении, то там есть прям нативные хуки, чтобы, грубо говоря, пост-запрос тут же инвалидировал все закэшированные объекты для этого же IDшника внутри вашего кэша. +2049.88 2058.20 "Игорь Лабутин" Короче, прям гораздо более гибкий кэш, но ценой того, что это делается у вас в приложении, а не где-то на промежуточных там проксях. +2058.20 2060.08 "Игорь Лабутин" Вот, но штука мощная. +2060.08 2062.28 "Анатолий Кулаков" Да, богатая тема. +2062.28 2082.04 "Анатолий Кулаков" Еще к нам завезли декомпрессию, но декомпрессия респонса у нас уже была, вот сейчас мы теперь можем декомпрессить реквесты, то есть если к вам пришел какой-то входящий запрос, у которого контент как-то был сжат, то теперь его можно элементарно хорошо и прозрачно разжать. +2082.04 2092.32 "Анатолий Кулаков" Включилась и поддержка HTTP/3, раньше она была в экспериментале, теперь это встроенная поддержка, то есть это последняя версия HTTP протокола, который основан на квике. +2092.32 2100.40 "Анатолий Кулаков" Теперь его можно использовать в различных ваших каких-то случаях, если вам вдруг это нужно, то официальная зарелиженная поддержка. +2100.40 2114.64 "Анатолий Кулаков" При этом у нас будет еще HTTP/2 WebSockets, это новый транспорт, который позволяет вам запускать WebSockets по уже отлаженному HTTP/2. +2114.64 2122.04 "Анатолий Кулаков" И мы добавили, то есть ISP.NET команда добавила новый WebTransport, который называется WebTransport. +2122.04 2130.64 "Анатолий Кулаков" Вот, специальный протокол общения, который построен на датограммах поверх HTTP/3, и он сейчас находится в глубоком эксперименте. +2130.64 2134.04 "Анатолий Кулаков" Показывает цифры довольно интересные, но посмотрим, что там с ним будет. +2134.04 2146.04 "Анатолий Кулаков" В общем, если вы хотите его включить, то уже в текущем релизе можете с помощью экспериментального флага переключить, включить поддержку WebTransport и потестировать, допустим, на своих нагрузках со своими данными, которые есть у вас. +2146.04 2155.24 "Анатолий Кулаков" Очень много изменений коснулось минимум API, почему-то его все время улучшают очень активно, в отличие от стандартного MVC подхода. +2155.24 2164.04 "Анатолий Кулаков" Что-то я боюсь, что с такой эффективностью, с таким рвением, Microsoft делает ставку на то, что MVC развиваться больше не будет. +2164.04 2167.88 "Игорь Лабутин" А про это у меня всегда есть что добавить. +2167.88 2193.16 "Игорь Лабутин" Про это можно посмотреть видосик в .NET Conf видео, есть отдельный видосик, называется Architects Panel, где Дамиан Эдвардс, Дэвид Фаулер и кто-то третий, я забыл кто, как раз обсуждают всякие штуки типа Minimal API, MVC, Green 3D, если вам интересно, Дэвид Фаулер сейчас с ними экспериментирует. +2193.16 2204.00 "Игорь Лабутин" Короче, это тоже полчасовое или около 40-минутное что-ли видео, посмотрите, тоже очень неплохо узнать, что думают главные ISP-NET архитекторы. +2204.00 2207.36 "Анатолий Кулаков" Ну, посмотрим, да. +2207.36 2222.88 "Анатолий Кулаков" Из Minimal API у нас добавились фильтры, с помощью которых можно организовать Cross-Cutting Concern Code, то есть можно запускать какие-то ваши хуки, какие-то ваши делегаты перед каждым роутом и после выполнения каждого роута. +2222.88 2234.08 "Анатолий Кулаков" У нас появились типизированные результаты, это строго типизированный классик, который умеет возвращать результаты, умеет их грамотно кэшировать и красиво форматировать и все так далее. +2234.08 2240.96 "Анатолий Кулаков" Вот казалось бы типичный пример, почему бы такие Type Result не сделать для MVC тоже, но они поддерживаются только в Minimal API. +2240.96 2245.16 "Анатолий Кулаков" Никаким образом к Minimal API, грубо говоря, отношения не имеют. +2245.16 2250.68 "Анатолий Кулаков" Мы везде хотим возвращать нормальные респонсы с какими-нибудь закэшированными, оптимизированными ответами. +2250.68 2252.88 "Игорь Лабутин" Почему это было не сделать для MVC, непонятно. +2252.88 2254.44 "Игорь Лабутин" По-моему, ты можешь их использовать в MVC. +2254.44 2259.00 "Игорь Лабутин" В MVC же ты же этот I-Action Result, насколько я помню, возвращаешь. +2259.00 2260.00 "Анатолий Кулаков" Именно так. +2260.00 2262.88 "Анатолий Кулаков" Насколько я знаю, что вот эти Strong Result, они не реализуют I-Action Result. +2262.88 2266.24 "Анатолий Кулаков" То есть там нужен какой-нибудь конвертер делать или оберточку влечеть в этом духе. +2266.24 2267.24 "Игорь Лабутин" Почему бы не реализовать? +2267.24 2268.24 "Игорь Лабутин" По-моему, можно. +2268.24 2274.88 "Игорь Лабутин" По-моему, я вот, надо посмотреть мое тестовое приложение на GitHub, примерно там же, которое я делал для доклада. +2274.88 2286.60 "Игорь Лабутин" По-моему, я что-то там возвращал, такое достаточно строго типизированное, типа JSON Result точка, что-то там, или просто JSON скобочка, что-то там, и оно вполне возвращалось. +2286.60 2288.32 "Игорь Лабутин" Так что, может быть, они в семерке сделали, что реализуют. +2288.32 2290.20 "Анатолий Кулаков" Ну, может быть. +2290.20 2294.60 "Анатолий Кулаков" Будет хорошо, если так, чтобы они все-таки не делили мир на две несовместимые части. +2294.60 2298.84 "Анатолий Кулаков" Было бы хорошо, чтобы если фичу можно поддержать и там, и там, ее поддерживали бы и там, и там. +2298.84 2301.84 "Анатолий Кулаков" Поэтому от этого бы все только выиграли. +2301.84 2302.84 "Анатолий Кулаков" Погнали дальше. +2302.84 2304.60 "Анатолий Кулаков" У нас появились road-группы. +2304.60 2314.16 "Анатолий Кулаков" То есть это специальный способ, когда можно ваши minimal API-хендлеры объединить в какую-то одну группу, ей можно дать какой-нибудь общий префикс. +2314.16 2321.20 "Анатолий Кулаков" Ну вот, мы приходим к тому, что у нас появляются некие подобия контроллеров, от чего, собственно, и убегали. +2321.20 2322.92 "Анатолий Кулаков" Другой большой раздел – это gRPC. +2322.92 2326.80 "Анатолий Кулаков" В gRPC самым главным нововведением было JSON-транскодинг. +2326.80 2334.88 "Анатолий Кулаков" Это специальный сервис, специальная схема, которая позволяет вам из вашего gRPC сервиса выставить наружу JSON-бейст API. +2334.88 2339.24 "Анатолий Кулаков" То есть якобы, как будто это ваш REST API сервис. +2339.24 2349.36 "Анатолий Кулаков" Вот таким образом мы пытаемся обмануть клиентов, которые не поддерживают новомодные протоколы, там, HTTP/3, gRPC, прочие компрессии и прочие глупости. +2349.36 2358.76 "Анатолий Кулаков" Вот мы можем сделать какой-нибудь совместимый такой JSON-бейст API и с помощью него поддержать старых клиентов. +2358.76 2376.20 "Анатолий Кулаков" Также интересная штука, что сверху на этот JSON-транскодинг можно нацепить OpenAPI, то есть сгенерить какую-нибудь свагер-спецификацию и действительно прикинуться, что это вообще настоящие JSON-бейст контроллеры, JSON-API. +2376.20 2378.40 "Анатолий Кулаков" Вот, тоже забавная вещь. +2378.40 2380.92 "Анатолий Кулаков" Также в gRPC у нас добавились health-чеки. +2380.92 2387.84 "Анатолий Кулаков" Теперь можно там репортить, проверять, каким образом себя чувствует gRPC сервер. +2387.84 2391.48 "Анатолий Кулаков" И JSON-API клиент научился добавлять credentials. +2391.48 2398.48 "Анатолий Кулаков" То есть можно отсылать authentication request на сервер с помощью барьер-токена. +2398.48 2400.72 "Анатолий Кулаков" Тоже полезная штука. +2400.72 2403.20 "Анатолий Кулаков" Не отстает от всех этих красавцев Blazor. +2403.20 2412.40 "Анатолий Кулаков" Он научился генерить custom-ные элементы для того, чтобы создать стандарт HTML custom-элемент. +2412.40 2421.32 "Анатолий Кулаков" То есть это специальные такие компоненты, которые позволяют Blazor-ным компонентам прозрачно интегрироваться в Java-бейст приложения. +2421.32 2437.12 "Анатолий Кулаков" В общем, он может подстраиваться под те существующие HTML-элементы и может быть даже как-то обманывать существующие фреймворки и интегрироваться вместе с ними. +2437.12 2446.48 "Анатолий Кулаков" В общем, тоже полезная фишка, которая позволит более плотно юзать уже существующие Java UI-ные фреймворки и вот как-то подмешивать к нему Blazor. +2446.48 2450.72 "Игорь Лабутин" Давай только мы не будем использовать существующие Java UI-ные фреймворки, а хотя бы JavaScript-овые. 2450.72 2451.72 None Ну, да-да-да. -2451.72 2460.44 SPEAKER_00 Не, ну Java UI-ные тоже можно, возможно, это примерно одно и, так сказать, одного уровня проблемы. -2460.44 2468.08 SPEAKER_01 Я думаю, я просто уже морально смирился, что Java мертва, это имя уже свободно и можно для сокращения JavaScript -2468.08 2472.72 SPEAKER_00 сюда добавить. Я только сегодня разбирал проект на Java Server Pages и тут на фреймворке 33.5. -2472.72 2475.72 SPEAKER_01 Я думаю, что ты очень не радовался. -2475.72 2481.12 SPEAKER_00 Ничего, нормально, будем переводить на Blazor и .NET, что там, 7, 8. -2481.12 2484.28 SPEAKER_00 К тому времени, когда переведу, я думаю, что уже девятка может выйдет. -2484.28 2488.76 SPEAKER_01 Которая автоматически научится транскопировать, видишь, что сейчас модно все транскопировать. -2488.76 2491.44 SPEAKER_01 Да, в васм все это, в васм. -2491.44 2501.88 SPEAKER_01 Еще до Blazor хотелось добавить, это теперь появилась возможность наконец-то обрабатывать изменения у Location, то есть тот участок, куда вводится ваш адрес. -2501.88 2512.88 SPEAKER_01 То есть вы теперь можете перехватить изменения адреса и, соответственно, создать какой-то эффект, какой-то дополнительный User Experience в навигации. -2512.88 2518.04 SPEAKER_01 То есть или подменять адрес, или наоборот, навигироваться без подменения адреса, или как-то управлять историей. -2518.04 2525.76 SPEAKER_01 В общем, очень полезная штука, практически все UI и JavaScript фреймворки обязательно эту вещь используют. -2525.76 2528.72 SPEAKER_01 В общем, и с Blazor теперь тоже можно это удобно делать. -2528.72 2533.04 SPEAKER_00 Да, и это все было, как я понимаю, все-таки про Blazor сервер, вроде как? -2533.04 2537.12 SPEAKER_00 Или это, у нас же есть Blazor Wasm, надо же каждый раз говорить, кто из них кто. -2537.12 2541.36 SPEAKER_01 Я думаю, это общие вещи, которые поддерживаются и там, и там. -2541.36 2542.36 SPEAKER_00 Угу, хорошо. -2542.36 2547.96 SPEAKER_00 В васме тоже, на самом деле, появилось некоторое количество разных штук, прям специфичных для васма. -2547.96 2563.80 SPEAKER_00 То есть там теперь можно, вот я не помню, это в семерке появилось все-таки раньше, но сейчас точно улучшили, что теперь можно запихнуть это все в native варианте, то есть вы можете же в ваш Blazor Wasm приложение запихнуть в васм двумя способами. -2563.80 2572.24 SPEAKER_00 Либо положить C#, ну, или код, да, фактически, плюс интерпретатор, либо сразу его скомпилировать, так сказать, нативно в нативные васмовские обкоды. -2572.24 2589.84 SPEAKER_00 И вот если вы это делаете в нативный вариант, в native out, то у вас сразу, компилятор теперь знает про всякие CMD, exception handling нативный васмовский, и, конечно, ну и у вас приложение становится прям круче работать. -2589.84 2594.72 SPEAKER_00 Но это требует, понятно, native out компиляции, которая со своими ограничениями. -2594.72 2606.60 SPEAKER_00 И в качестве эксперимента в Blazor Wasm завезли поддержку многопоточности, то есть вы теперь все # коди пишете там new thread, ну, как вы обычно пишете на C#, хотя это, наверное, давно много кто не писал уже new thread, все на тасках. -2606.60 2621.32 SPEAKER_00 Но если вам вдруг именно нужен мультитрейдинг такой нормальный, то вы пишете в C# new thread, а внутри это в браузере будет нормально через worker обрабатываться, и все будет работать как будто это обычное многопоточное приложение. -2621.32 2622.80 SPEAKER_00 Хотя это браузер, который по определению не многопоточен. -2622.80 2631.84 SPEAKER_01 Слушай, нет, ну thread-то не обязательно писать, даже если ты будешь async/await-ами пользоваться, то они уже автоматически подхватят эти background полы и сделают -2631.84 2636.56 SPEAKER_00 тебе параллельность. Ну вот async/await, да, это, по-моему, и было. -2636.56 2642.56 SPEAKER_00 А вот если ты писал new thread, вот прям тебе нужно какую-то длинную бэкграундную работу зафигачить, вот этого раньше не было. -2642.56 2644.64 SPEAKER_00 New thread API вроде не была поддержана, теперь будет. -2644.64 2652.04 SPEAKER_01 Ну именно так, async/await были, но они запускались в одном потоке, а теперь async/await на месте же останутся, но теперь они будут запускаться в нескольких потоках. -2652.04 2656.84 SPEAKER_01 То есть вам достаточно перекомпилировать, грубо говоря, ваш код с async/await-ами, и все заработает уже параллельно. -2656.84 2663.24 SPEAKER_00 В общем, нам из вас мы делают такой полноценный рантайм, в котором можно делать вообще все, что вы обычно делаете. -2663.24 2665.76 SPEAKER_00 Останется только добавить какой-нибудь нормальный UI. -2665.76 2668.76 SPEAKER_00 Смотри, Maui, да, например. -2668.76 2675.68 SPEAKER_00 И можно будет, да, отказаться от JavaScript, наконец-таки может быть когда-нибудь, но не факт. -2675.68 2677.20 SPEAKER_00 Давай пойдем дальше. -2677.20 2685.72 SPEAKER_00 Третий наш большой кусок от документа, который мы всегда тоже отсматриваем, это Entity Framework. -2685.72 2689.64 SPEAKER_00 Работа с данными всегда важна, в Entity Framework тоже много изменений. -2689.64 2693.76 SPEAKER_00 Основной фокус шестого Entity Framework был на перформанс по чтению. -2693.76 2699.48 SPEAKER_00 Они там пытались догнать даппер, и, насколько я помню, если не догнали, то очень-очень близко приблизились. -2699.48 2706.36 SPEAKER_00 Фокус седьмого Entity Framework был на перформансе сохранения, то есть перформансе записи и всего, что с этим связано. -2706.36 2713.36 SPEAKER_00 Тем не менее, помимо сохранения, завелись и какое-то количество просто общих фич, про которые мы сначала и поговорим. -2713.36 2720.80 SPEAKER_00 Во-первых, это Table Per Concrete Type Mapping, то есть если вы иерархию объектов хотите хранить в байте, у вас есть три варианта. -2720.80 2735.16 SPEAKER_00 Либо всю иерархию храним в одной широкой таблице, либо мы храним кучку таблиц на каждый класс, включая все абстрактные и промежуточные классы, либо мы храним только листовые классы с конкретным набором полей уже. -2735.16 2738.28 SPEAKER_00 Каждая такая табличка будет включать набор всех, в том числе родителей. -2738.28 2740.20 SPEAKER_00 Вот третий вариант теперь поддерживается. -2740.20 2741.88 SPEAKER_00 Два предыдущих были поддержаны до этого. -2741.88 2751.80 SPEAKER_00 Все это можно настраивать в вашем OnModule, в модул-конфигураторе, и Entity Framework это все нативно теперь нормально поддерживает. -2751.80 2753.56 SPEAKER_00 Кроме того, поддержаны JSON-колонки. -2753.56 2775.84 SPEAKER_00 Причем JSON-колонки поддержаны хитрым образом, если он будет очень стараться, пытаться собрать именно SQL выражения, которые, например, при апдейте будут обновлять только кусочек JSON, значения JSON-колонки, а не просто перезаписывать целиком колонку заново, а прям генерить SQL, который обновит содержимое JSON внутри колонки, если SQL, понятно, база такое поддерживает. -2775.84 2782.44 SPEAKER_00 Доступ к этим JSON-колонкам делает через LinkU, и все это совершенно замечательно работает довольно нативно. -2782.44 2794.48 SPEAKER_00 Скорее всего это, конечно, супернативно работает именно на SQL-сервере как основной, понятное дело и первой, наверное, базе, на которой все обычно поддерживается в Entity Framework, но в FosgreSQL, скорее всего, тоже все хорошо работает. -2794.48 2797.44 SPEAKER_00 Про остальные базы сказать не могу. -2797.44 2823.52 SPEAKER_00 Entity Framework обрел поддержку bulk-updates и bulk-deletes, если вам, например, нужно было обновить пачку объектов по какому-то условию и поставить им всем определенное значение в какой-то поле, там, не знаю, флажок в бульоне, в колонке, то на старых фреймворках нужно было сказать сначала получить все это дело, то есть загрузить все это из базы, обновить, просто в обычном C# коде, и потом сказать save changes. -2823.52 2833.76 SPEAKER_00 Это накладывает некоторые ограничения на скорость, потому что включается object tracker, чтобы save changes нормально работал, в Entity Framework нужно потракить все изменения и так далее. -2833.76 2834.76 SPEAKER_00 Теперь появляется возможность сделать по-другому. -2834.76 2851.68 SPEAKER_00 Вы теперь пишете "ef.where...execute bulk-update", дальше пишете, что собственно нужно сделать с этим book'ом, лямдочку, и он на основе этого сгенерит правильный SQL, который прям сразу update where сделает, как надо. -2851.68 2853.60 SPEAKER_00 Такая же штука с delete'ом. -2853.60 2854.60 SPEAKER_00 Теперь работает. -2854.60 2857.40 SPEAKER_00 Save changes тоже стал быстрее. -2857.40 2873.56 SPEAKER_00 В save changes, по-моему, это был даже чуть ли не последний выпуск, ну последний выпуск был про dotnext, по-моему, перед этим выпуском мы обсуждали save changes довольно активно, про то, что там брали лишнее количество транзакций, то есть, например, если вы делали один-единственный insert, то это приводило к трем round trip'ам. -2873.56 2882.12 SPEAKER_00 Сначала скажи там begin transaction, потом выполни, потом скажи commit transaction, хотя на самом деле база и так все это сделает за вас, если вы делаете один-единственный insert. -2882.12 2887.28 SPEAKER_00 И всякие такие штуки, плюс batching по 42 элемента. -2887.28 2890.92 SPEAKER_00 В общем, save теперь стал работать тоже пошустрее. -2890.92 2896.76 SPEAKER_00 Из дополнительных таких фич еще появился маппинг на хранимые процедуры. -2896.76 2901.64 SPEAKER_00 Он был для select'ов, теперь можно для insert'ов, update'ов и delete'ов теперь тоже хранимки использовать. -2901.64 2919.84 SPEAKER_00 Если вы используете, генерите структуру ваших классов, моделей данных из базы данных, то есть то, что называется database first, то вы теперь можете специальной командой через .NET tool поставить себе темплейты в t4 темплейты внутрь проекта и их подкастомизировать как вам угодно. -2919.84 2938.64 SPEAKER_00 То есть, например, если у вас по дефолту entity framework коллекции поменяет как лист от t, если вам хочется observable collection какой-нибудь или ваш кастомный тип коллекции, то там это прям в t4 темплейте правите и когда вы будете генерить в следующий раз модели с базы, ну все будет уже согласно вашим темплейтам. -2938.64 2959.76 SPEAKER_00 Ну и если вы крутой чувак, который хорошо знает внутренности entity framework и всячески кастомизируете его или подписываетесь на его события или используете так называемые интерцепторы, то завезли некоторое количество новых штук, которые вызываются перед компиляцией запроса, после компиляции запроса, перед выполнением обращения к BD, после выполнения обращения к BD. -2959.76 2972.04 SPEAKER_00 Если вы это используете, то вот как раз смотрите туда, там появились новые штуки, которые возможно помогут вам сделать какие-нибудь еще крутые вещи на entity framework, как-то в его pipeline клинится. -2972.04 2975.80 SPEAKER_01 Ну что ж, пойдем посмотрим, что у нас здесь еще есть. -2975.80 2980.80 SPEAKER_01 У нас притаилась и такая неочевидная вещь для .NET, это как UI-ки. -2980.80 2984.28 SPEAKER_01 Давай посмотрим, UI-ков у нас много теперь. -2984.28 3004.32 SPEAKER_00 В UI-ке в .NET это какая-то такая странная немножко история, их действительно много, мы сегодня обсудим три, их на самом деле больше, потому что есть те, которые неофициальные и не от Microsoft, но UI в .NET это всегда какая-то такая штука, которая непонятно где работает, как работает, в каком она состоянии работает и чем вообще надо пользоваться. -3004.32 3007.80 SPEAKER_00 Я до сих пор беру Windows Forms, когда мне что-то надо по-быстренькому наклепать. -3007.80 3014.04 SPEAKER_01 Ну, нужно признать, что все было довольно понятно и просто, когда мы были только под виндой. -3014.04 3017.88 SPEAKER_01 Вот когда появились всякие Mac и Linux, и вот там началось разброты шатания. -3017.88 3020.96 SPEAKER_01 И куда надо шататься? -3020.96 3026.64 SPEAKER_01 До сих пор мы не имеем какого-то одного ответа, и я думаю, что сейчас вы по анонсам, примерно, поймете почему. -3026.64 3044.28 SPEAKER_01 Начнем, как всегда, с твоего любимого старичка, Windows Forms, который по-прежнему жив, и я вообще, если честно, удивился, найдя его анонс вместе с .NET 7, и еще больше удивился, когда прочитал его анонс, потому что происходит что-то странное, друзья, и поэтому предлагаю все вместе посудить. -3044.28 3046.16 SPEAKER_01 Давайте пробежимся по нововведениям. -3046.16 3055.96 SPEAKER_01 Прежде всего, улучшили accessibility в Windows Forms, то есть сделали много таких интересных вещей, которые помогают, например, в автоматизации. -3055.96 3063.80 SPEAKER_01 Ну, улучшили, например, Scream Reader и тот сервис, который известен под названием Narrator. -3063.80 3076.28 SPEAKER_01 Это штука, которая позволяет слабовидящим людям считывать с экрана различные надписи или элементы, и позволяет им каким-то образом общаться с UI. -3076.28 3078.80 SPEAKER_01 В общем, это все заулучшили. -3078.80 3096.44 SPEAKER_01 Далее был улучшен UI Automation, то есть это специальный фреймворк, который зашит Windows Forms, который помогает вам делать, например, автоматизированные тесты или с какой-то другой целью управлять UI автоматически, то есть использованием юзера. -3096.44 3101.20 SPEAKER_01 Тоже прекрасная штука, что-то улучшили. -3101.20 3120.28 SPEAKER_01 Далее подобрали более подходящие цвета для того, чтобы сделать как контрастные темы более контрастными, и соответственно для того, чтобы обычные темы сделать тоже немножко более контрастными, чтобы их лучше было разглядеть и удобнее было на них смотреть. -3120.28 3124.36 SPEAKER_01 Улучшили High DPI всякие режимы. -3124.36 3131.72 SPEAKER_01 Например, сделали поддержку High DPI на мультимониторингах более умную. -3131.72 3141.16 SPEAKER_01 Она начала лучше рендериться, начала качественнее увеличивать те контроллы, которые внутри формочки находятся. -3141.16 3162.84 SPEAKER_01 И так как все вот эти изменения довольно рискованные, потому что уже очень много у нас собралось всяких WinForm приложений, уже очень много настроено каких-то автоматизированных средств и всяких тестовых средств под этот фреймворк, в общем команда ввела возможность отключить все эти нововведения с помощью фичи-флагов. -3162.84 3173.60 SPEAKER_01 Мы уже с фичи-флагами часто сталкивались и уже знаем, если вдруг какие-то проблемы возникнут, то всегда вот эти вот настроечки, их можно отменить. -3173.60 3179.84 SPEAKER_01 Более интересное нововведение – это новые датабайдинги. -3179.84 3184.56 SPEAKER_01 WinForm завезли современные датабайдинги. -3184.56 3188.20 SPEAKER_01 То есть раньше в WinForm они и были, но там были довольно убогие. -3188.20 3194.36 SPEAKER_01 В общем назвать это датабайдингами даже язык не поворачивался, это вообще какой-то примитивный способ связывания. -3194.36 3212.92 SPEAKER_01 Сейчас же сюда завезли байдинги полноценные, практически такие, как были в .dpf, такие, как есть в .dpf, то есть с датаконтекстом, с поддержкой команд Pattern, то есть можно там команды делать, можно какие-то объекты в датаконтекст засовывать, их там разбирать с помощью ключей. -3212.92 3217.20 SPEAKER_01 В общем все то, что вы наверняка видели в .dpf. -3217.20 3224.28 SPEAKER_01 И в .dpf это была, наверное остается, это самая мощная штука, которая много релизов двигала .dpf вперед. -3224.28 3227.68 SPEAKER_01 Теперь все это может делать наш старичок в WinForms. -3227.68 3234.88 SPEAKER_01 И нужно это для того, чтобы естественно реализовать полноценный Model-View-Model, MVVM, так называемый, паттерн. -3234.88 3241.20 SPEAKER_01 MVVM – это очень крутецкая штука, она помогает вам очень сильно увеличивать переиспользование кода. -3241.20 3244.48 SPEAKER_01 И самое главное – это тестирование кода. -3244.48 3259.56 SPEAKER_01 Переиспользование кода, чтобы вы оценили, насколько она позволяет переиспользовать кода, что прямо в статье автор отмечает, что если вы перейдете на MVVM, то в принципе вы уже будете никак не ограничены WinForms. -3259.56 3269.32 SPEAKER_01 Если у вас будут View-модели, то вы без проблем сможете пересесть и на .dpf, и на UVP, и на WinUI, и как ни странно на MOYU тоже. -3269.32 3275.16 SPEAKER_01 В общем, может быть это такая стратегия Microsoft по миграции. -3275.16 3282.64 SPEAKER_01 То есть вам уже не нужно просто взять, выбрасывать ваши WinForms, переписывать все с нуля, а вы можете сделать более прозрачную штуку. -3282.64 3300.72 SPEAKER_01 Вы можете существующие WinForms проапгрейдить на новую версию, перевести постепенно все ваше приложение на MVVM, и после того, как вы это сделаете, выбрасывание WinForms и подставление туда MOYU, это будет просто элементарное действие практически. -3300.72 3308.12 SPEAKER_01 Таким образом может быть Microsoft планирует захватить наших старичков, которые до сих пор живут на WinForms и перевести их на новый MOYU. -3308.12 3320.24 SPEAKER_01 Но другой причиной так сильно импровидить дата баннинг, того чего мы не могли дождаться десятилетия, сейчас зачем этим заниматься, другого оправдания я найти не могу. -3320.24 3332.92 SPEAKER_01 Microsoft также отдельно подчеркивает, что никаких планов переводить приносить XAML в WinForms у них нет, то есть с помощью XAML мы все еще не сможем описывать WinForms. -3332.92 3338.24 SPEAKER_01 Это конечно грустно, но надо же до пифа хоть что-то ставить, хоть какую-то фишку. -3338.24 3341.04 SPEAKER_01 Иначе вообще не будет понятно, зачем он нужен. -3341.04 3346.20 SPEAKER_01 Следующий из больших разделов это Comvwrapper и Native IOT. -3346.20 3357.28 SPEAKER_01 С WinForms была большая проблема, к нему не мог прицепиться никак Native IOT и Trimming вместе с ним. -3357.28 3369.24 SPEAKER_01 И в этом релизе команда решила обновить Com-интеропы, которые как раз были главной причиной, заменила их с помощью Comvwrapper. -3369.24 3382.12 SPEAKER_01 Это специальная технология, которая теперь позволяет при определенной реализации всех Com-интерфейсов как надо избавиться от той проблемы, что мы не могли Trimming раньше и применять IOT сценарий. -3382.12 3392.00 SPEAKER_01 Теперь это можно сделать, теперь WinForms можно скомпилировать как Native IOT приложение и запускать как нормальное Native приложение. -3392.00 3410.60 SPEAKER_01 Эта стадия все еще в большом эксперименте, там еще возможны какие-то проблемы, там еще не все размечено, не все Com-интерфейсы переведены, но активная работа в этом направлении ведется и в принципе уже сейчас можно пробовать, если на каких-то ваших приложениях это критично или нужно, то я думаю, что уже можно поэкспериментировать. -3410.60 3417.40 SPEAKER_01 Вот такие глобальные, мне кажется, довольно большие мощные нововведения коснулись WinForms. -3417.40 3419.40 SPEAKER_01 Как, Игорь, тебя впечатлили? -3419.40 3431.96 SPEAKER_00 Да, я на самом деле хочу попробовать DataBinding, посмотреть что это такое, потому что может быть это еще больше ускорит то, как я быстренько клепаю приложение, когда мне нужно что-то очень простое и быстрое. -3431.96 3432.96 SPEAKER_00 Надо посмотреть. -3432.96 3444.80 SPEAKER_00 Я еще хотел сказать, что вот Comvwrapper и Native IOT, то есть ты сказал, что там команда работала, я так понимаю, что это работа в основном комьюнити, по большому счету. -3444.80 3450.60 SPEAKER_00 Там, конечно, команда что-то тоже помогала и содействовала, но основная работа была проведена силами комьюнити. -3450.60 3453.88 SPEAKER_00 То есть вся эта фишка с Comvwrapper и Native IOT. -3453.88 3455.56 SPEAKER_01 Да, вполне может быть. -3455.56 3458.64 SPEAKER_01 Ну что ж, пойдем дальше по возрастающей. -3458.64 3471.32 SPEAKER_01 После этого открывает DPF, я уже не знал чего ожидать, думал, может наконец-то перенесут его на кроссплатформу, запустят под Linux, завезут в виртуальную реальность, что-нибудь еще с ним сделают. -3471.32 3478.36 SPEAKER_01 Но изменения в DPF оказались намного более скромными и практически сводятся к секции Pro Performance. -3478.36 3492.00 SPEAKER_01 Конечно, там нашли очень много мест, где был ненужный анбоксинг-анбоксинг, перевели на спаны, там манипулирование со строками, там очень много было строк, все это тоже прооптимизировали. -3492.00 3501.00 SPEAKER_01 Улучшили локацию памяти, а точнее избавились от локации памяти, там где она была не нужна, там где она нужна ее максимально сократили. -3501.00 3510.04 SPEAKER_01 В общем, сильно профайлили память, улучшили потребление и использование памяти, соответственно, у нас DPF стал немножко меньше кушать. -3510.04 3524.84 SPEAKER_01 Улучшили рендеринг шрифтов, рендеринг шрифтов, кажется, это какая-то больная родовая травма, его там улучшают каждый релиз и все еще он как-то хреново иногда в некоторых ситуациях рендерится, но будем надеяться, что что-то наконец докрутили. -3524.84 3542.88 SPEAKER_01 И очень сильно почистили код, что тоже сделало возможность некоторые куски прям повыбрасывать, что положительно сказалось на перформансе, и некоторые плацдарм для будущих фич подготовить, потому что теперь код стал более читабельный, более консистентный, более красивый. -3542.88 3545.08 SPEAKER_01 Ну и там в аксессибилити тоже что-то завезли. -3545.08 3554.92 SPEAKER_01 В общем, как мы видим, такие дежурные исправления, какие-то дежурные работы над перформансом, никакого большого изменения, по сути, WPF не получил. -3554.92 3558.56 SPEAKER_01 Так стал немножко красивее, немножко быстрее и немножко -3558.56 3574.04 SPEAKER_00 получше. Там есть еще интересная тема, что, насколько я помню, в прошлом релизе он был, собственно, за open-source, то есть выложен его исходники в open-source, и в него можно контрибьютить, но проблема была в том, что не было выложено suite автоматических тестов для WPF. -3574.04 3581.44 SPEAKER_00 То есть вы могли что-нибудь закинуть, pull-request какой-нибудь, но проверить локально, что какой-то набор тестов проходит, вы, в общем-то, не могли. -3581.44 3595.04 SPEAKER_00 Вот штука, которую сделали в 7-м дотнете, это этот набор тестов тоже пушили на GitHub, ну или открыли его на GitHub, и настроили в основной репе WPF, насколько я понимаю, пайплайны, чтобы эти самые тесты запускались по pull-request. -3595.04 3605.60 SPEAKER_00 Все это выглядит, честно говоря, как то, что типа мы сильно WPF развивать не планируем, вот вам, как бы, наконец-таки тесты, теперь давайте несите ваши pull-requests, дорогой комьюнити. -3605.60 3606.80 SPEAKER_00 Мучаетесь с этими самыми. -3606.80 3611.16 SPEAKER_00 Ну, как бы, вам что-то надо в WPF, видите, правьте, а мы не хотим. -3611.16 3612.80 SPEAKER_00 Вот для меня пока это выглядит так. -3612.80 3614.28 SPEAKER_00 Не знаю, как на самом деле внутри. -3614.28 3628.12 SPEAKER_01 Ну, это ожидаемо, если они, в принципе, взяли себе направление на развитие MyUI, то тратиться на старые фреймворки, наверное, никакого смысла нет, кроме вот поддержки, улучшения, перформанса, рендеринга и так далее. -3628.12 3631.16 SPEAKER_01 Удивительно, вот почему они за WinForms взялись в этом -3631.16 3641.20 SPEAKER_00 контексте. Ну, тут, возможно, команда как-то, то есть, видимо, WinForms всё ещё действительно жив и популярен, и у команды нашлись ресурсы вот такое попробовать. -3641.20 3643.88 SPEAKER_00 Видимо, других улучшений особо не нужно было делать. -3643.88 3646.32 SPEAKER_00 Вот, попробовали, получилось что-то прикольное, видимо, -3646.32 3655.12 SPEAKER_01 надо пробовать. Да, в интерпрайзе такого не бывает, что у тебя нашлись ресурсы для того, чтобы принести баннинги, которые люди просили там десятилетиями, они раз и сделали. -3655.12 3659.04 SPEAKER_01 Там должна стоять какая-то более теория заговора. -3659.04 3662.56 SPEAKER_00 Может быть, мы что-то узнали, либо пришёл какой-нибудь большой кастер и рассказал нам очень надо. -3662.56 3664.12 SPEAKER_01 Ну да, может быть. -3664.12 3665.12 SPEAKER_01 Ладно, пойдём дальше. -3665.12 3677.36 SPEAKER_01 Вот, как я уже упоминал, всё у Microsoft нацелено на Moyu и вот открывая релиз ноутса Moyu, тут, конечно же, должна была быть огромная-огромная простыня всяких нововведений, но, опять же, нет, нифига. -3677.36 3681.32 SPEAKER_01 Единственное, что впечатляет у Moyu в том, что это General Availability. -3681.32 3683.24 SPEAKER_01 В принципе, и это всё. -3683.24 3690.56 SPEAKER_00 Ну, подожди, но он же был полгода назад объявлен, что он уже General Availability, нет? -3690.56 3693.52 SPEAKER_00 Или он там был просто, типа, релиз? -3693.52 3705.80 SPEAKER_01 Да, да, там его каким-то просто релизом обозвали, теперь сказали, что нам вот ещё немножко таймфрейм, пока мы подмачимся под наш новый DotNet 7, вот теперь они подмачиваются, теперь они смело кричат, что они наконец-то General Availability. -3705.80 3710.00 SPEAKER_01 В общем, не очень понятно статус, но вроде как зарелизилось. -3710.00 3712.96 SPEAKER_01 Ну, зарелизилось, можно пользоваться, хорошо. -3712.96 3713.96 SPEAKER_01 Типа того. -3713.96 3721.92 SPEAKER_01 Из мелочей улучшен Map Control, теперь, даже не улучшен, а добавлен, потому что раньше его вообще не было. -3721.92 3736.20 SPEAKER_01 Теперь вместе с DotMail.io поставляется Map Control, как всегда, это какой-то обновленный компонент от Xamarin.Forms, то есть это кроссплатформенная абстракция, которая нативно на конкретной операционной системе будет подцеплять нативный контроль. -3736.20 3743.52 SPEAKER_01 И там уже у вас будет и геокодирование, и позиционирование, и локации, и всё в этом духе. -3743.52 3764.40 SPEAKER_01 Улучшения для десктопа сводятся к банальным, типа, улучшили API для изменения размеров окна и его позиционирования, улучшили контекстное меню, тулт-типы, различные подсказки над контроллами, улучшили обработку правого клика. -3764.40 3769.68 SPEAKER_01 Ну, в общем, такие тоже какие-то мелочи, которые больше похожи на отмазки, чем на нормальный фичик релиза. -3769.68 3773.00 SPEAKER_00 Тут надо сказать, что слово "улучшили" неправильно. -3773.00 3794.60 SPEAKER_00 А если я правильно помню статью, смысл в том, что эти штуки добавили, MAUI настолько сильно концентрировался на всяких мобильных приложениях, ну а собственно с него, я так понимаю, всё начиналось, чтобы эта нативная кроплоформер работала на Android и iOS, что когда выяснилось, что вообще-то он должен работать в том числе на десктопе, оказалось, что, например, невозможно обработать right-click мыши. -3794.60 3796.76 SPEAKER_00 Ну нет, в телефоне right-кликов мыши. -3796.76 3798.84 SPEAKER_00 И поэтому такого API просто не было. -3798.84 3811.88 SPEAKER_00 И вот, поскольку к релизу нужно всё-таки, мы же релизим в том числе для десктопа, пришлось добавлять вот все эти API, про контекстные менюшки, про tooltip и вот всё то, что нужно на десктопе, чтобы с этим можно было в принципе работать. -3811.88 3822.84 SPEAKER_01 Ну, в целом про историю ты прав, единственное, что я не знаю, я не видел, добавили, я увидел везде там "улучшили", "заимпрувили" и "заинхэчмили" и всё в этом духе. -3822.84 3823.84 SPEAKER_00 Ну может быть. -3823.84 3827.40 SPEAKER_00 Ну не важно, но скорее всего, если оно работало фигово, можно считать, что его не было. -3827.40 3832.40 SPEAKER_00 Скорее всего, его действительно сильно не тестировали, потому что ну где ж ты там на телефоне будешь менять размер окна. -3832.40 3835.28 SPEAKER_00 Оно у тебя всегда одно и на весь экран. -3835.28 3836.28 SPEAKER_01 Да, да, может это. -3836.28 3850.56 SPEAKER_01 Ну смотри, вот глядя на вот эти три фреймворка, вот три анонса, которые мы сегодня с вами разобрали, у меня сложилось полное впечатление, что самый главный наш передовой UI фреймворк это WinForms, потому что во всех остальных это какие-то нелепые оправдания, а не анонсы. -3850.56 3853.16 SPEAKER_00 Ну, может тайной, не знаю. -3853.16 3860.12 SPEAKER_00 У Microsoft есть три команды, которые соревнуются, и вот WinForms это, вырывается вперёд, там долго сидели в засаде. -3860.12 3867.04 SPEAKER_01 Ну может быть, для нас, как для обычных разработчиков это вносит ещё больше путаницы, не более, не менее. -3867.04 3868.52 SPEAKER_01 А потом придёт Аполлония и всех победит. -3868.52 3878.24 SPEAKER_01 Да, скорее бы уже, может Microsoft наконец-то бы её купил там или задоптил, или ещё что-то с ней сделал, и наконец-то у нас был бы нормальный какой-то фреймворк, вместо десятка ненормальных. -3878.24 3883.00 SPEAKER_01 Ладно, хватит фантазировать и пойдём дальше, что у нас там есть. -3883.00 3884.68 SPEAKER_01 Машинное обучение, кажется, ещё рассказывали интересное. -3884.68 3885.68 SPEAKER_00 Ох, машинное обучение. -3885.68 3898.08 SPEAKER_00 Машинное обучение действительно рассказывали, я, честно говоря, не знаю, кто занимается машинным обучением прямо на дотнете, именно прямо не использованием сеточек, а созданием нейросеток, да, там типа вот это всё. -3898.08 3899.08 SPEAKER_00 Таксошников же. -3899.08 3908.96 SPEAKER_00 Нет, подожди, он занимается, конечно, в демо-примерах, но я не слышал ни разу, что этим занимались прямо в промышленном смысле. -3908.96 3911.44 SPEAKER_00 Но, может, действительно такие люди есть. -3911.44 3935.00 SPEAKER_00 Ну короче, есть ML.net, если кто не знает, это такая умотнученная штука, точнее это framework, кроссплатформенный для машин-лёрнинга, для дотнет-разработчиков, который, соответственно, позволяет вам вписать в ваше дотнет-приложение любые, в общем-то, какие-то модели, да, ML-ные, для их использования. -3935.00 3941.04 SPEAKER_00 Для этого есть ещё Extend, для Visual Studio 2022 есть Extension Model Builder, который позволяет, собственно, создавать эти штуки. -3941.04 3952.40 SPEAKER_00 И в этом релизе в 2.0 завезли новые API для работы с текстами, то есть теперь там есть classification поиск, по подобию, то, что они называют similarity API. -3952.40 3958.16 SPEAKER_00 И есть улучшение в штуке, которая называется AutoML, automated machine learning. -3958.16 3969.80 SPEAKER_00 Теперь вы можете автоматически перепроцессить нужные данные, как-то автоматически тренить всякие классификаторы, мультикласс классификаторы, регрессионные модели. -3969.80 3981.72 SPEAKER_00 Ну вот, кастомизировать гиперпараметры, это я сейчас вот прям статью читаю, тюнить алгоритмы для поиска оптимальных гиперпараметров, ты знаешь? -3981.72 3982.72 SPEAKER_00 Нет, к сожалению, не приходилось делать. -3982.72 3985.72 SPEAKER_00 И после того, как вы всё это закастомизируете, заоптимизируете, затюните, можно всё это заперсистить и, видимо, потом впихнуть в ваше дотнет-приложение, и оно будет оптимально работать. -3985.72 4009.36 SPEAKER_00 То есть, грубо говоря, вы действительно, видимо, можете на основе каких-то входных данных, например, включить какие-то модели, например, в какой-то модели, и из дотнет-приложения заиспользовать. -4009.36 4025.12 SPEAKER_00 Я не знаю практических применений этого, я не слышал, но я не интересуюсь особо этой областью, поэтому, если вы вдруг работаете на ML-дотнете и что-то про это знаете, на самом деле, напишите нам, мы вас позовём и с вами это обсудим, нам это тоже интересно. -4025.12 4035.96 SPEAKER_00 А если вы этим интересовались и вам интересно, вдруг что-то новенькое есть, ну загляните в ML-дотнет 2.0, может быть, вы там найдёте что-то интересное для вас. -4035.96 4040.40 SPEAKER_00 Наверное, вот это всё, что я могу рассказать про ML-дотнет, учитывая, что я им не занимаюсь. -4040.40 4041.40 SPEAKER_01 Ну, отлично. -4041.40 4046.44 SPEAKER_01 Я думаю, что если кто-то действительно занимается, приходите, пообсудим и поговорим. -4046.44 4055.12 SPEAKER_01 Я тоже не знаю ни одного живого человека, который на практике с этим сталкивался, поэтому даже представления не имею, как оно там всё живёт. -4055.12 4057.24 SPEAKER_01 Но, судя по анонсам, развиваются довольно бодренько. -4057.24 4063.80 SPEAKER_01 То есть, я бы сказал, что там какие-то громкие названия, громкие пункты и громкие импрувменты, они всё время встречаются. -4063.80 4070.00 SPEAKER_01 Не сказать бы, что оно мертво, наверное, где-то в какой-то индустрии, в какой-то стране кто-то этим пользуется. -4070.00 4074.64 SPEAKER_00 Давай про следующую технологию, которую тоже очень активно все пользуются, в кавычках. -4074.64 4078.72 SPEAKER_01 Да ничего не в кавычках, нормальная технология, чего ты наезжаешь. -4078.72 4081.76 SPEAKER_01 Речь у нас сейчас пойдёт про Microsoft Orleans. -4081.76 4093.68 SPEAKER_01 Это, для тех, кто не знает, Microsoft Orleans – это кроссплатформенный фреймворк для того, чтобы создавать различные сложные, масштабируемые, распределённые приложения. -4093.68 4095.52 SPEAKER_01 Звучит нормально, да? -4095.52 4097.20 SPEAKER_01 Возможно, многое насобирали. -4097.20 4100.88 SPEAKER_01 На самом деле, довольно популярная штука, довольно уже устоявшаяся. -4100.88 4108.00 SPEAKER_01 То есть, это не какой-то там молодняк, а это уже хорошо тестированное на больших продакшн-системах, в том числе внутри самого Microsoft. -4108.00 4112.00 SPEAKER_01 И много микрософтовских игр его используют, и Microsoft Bing его используют. -4112.00 4124.20 SPEAKER_01 Фреймворк построен на так называемой концепции акторов, на модели акторов, но у него есть свой собственный подход, своё собственное видение на модель, так называемые виртуальные акторы. -4124.20 4129.24 SPEAKER_01 В общем, если кто-то знаком с ACO.NET, то это, наверное, самое близкое, что можно представить. -4129.24 4134.40 SPEAKER_01 То есть, ACO.NET – это примерно примерный конкурент Orleans. -4134.40 4140.04 SPEAKER_01 У них есть общие концепции, у них есть концепции, которые расходятся. -4140.04 4142.88 SPEAKER_01 В общем, примерно это про одно и то же. -4142.88 4147.32 SPEAKER_01 Хороший фреймворк, как я уже сказал, интересный. -4147.32 4149.76 SPEAKER_01 Microsoft решила сделать следующий фильм душами. -4149.76 4153.40 SPEAKER_01 Она решила объединить команды Microsoft Orleans и ISP.NET Core. -4153.40 4156.48 SPEAKER_01 Ну и там даже не ISP.NET, а прямо самого .NET. -4156.48 4163.56 SPEAKER_01 В общем, там команда Orleans рассыпалась и по .NET, и по ISP.NET, или, может быть, это неправильно назвать, влилась. -4163.56 4167.16 SPEAKER_01 В общем, теперь они стали взаимодействовать намного ближе. -4167.16 4182.08 SPEAKER_01 И в результате этого взаимодействия появился новый релиз Microsoft Orleans 7.0, который прежде всего рассказывает нам про огромное число импрувментов, которые произошли в результате вот этого корпоративного слияния. -4182.08 4184.72 SPEAKER_01 Что же у нас там за импрувменты? -4184.72 4185.72 SPEAKER_01 Давайте посмотрим. -4185.72 4192.48 SPEAKER_01 Во-первых, нужно отметить, что в самом Orleans, прямо в его репозитории на GitHub есть огромное число клевых тестов. -4192.48 4200.24 SPEAKER_01 Прекрасны они тем, что тестируют очень различные сценарии, там сило-то сило, клиент-то сило. -4200.24 4210.60 SPEAKER_01 И у них есть различные симуляции различных инвайорментов на лэптопе, на десктопе, на виртуальных машинах, на различных серверах с различной масштабированностью, с различным количеством клиентов. -4210.60 4223.04 SPEAKER_01 В общем, все вот эти разнообразные сценарии и разнообразные взаимодействия, разнообразные инвайорменты, они очень плотно покрыты тестами и это прекрасно. -4223.04 4238.24 SPEAKER_01 Так вот, в результате того, что Orleans что-то там поимпрувили, заулучшили, у них по некоторым тестам производительность увеличилась от 40% до 170%. -4238.24 4249.08 SPEAKER_01 Такие хорошие, довольно качественные цифры, особенно с учетом того, что никаких глубоких примеров большого рефакторинга и чего-то такого они не приводят. -4249.08 4255.82 SPEAKER_01 То есть кажется, что это просто взаимодействие, плотное взаимодействие действительно с Untamed и прочими командами. -4255.82 4266.96 SPEAKER_01 И соответственно в результате Microsoft Orleans 7 может через себя пропускать 4,5 миллиона сообщений в секунду, что довольно-таки приличные цифры. -4266.96 4268.68 SPEAKER_01 4,5 миллиона – это прямо хорошо. -4268.68 4275.40 SPEAKER_01 Вот в принципе вот такими вот примерными понятиями оперируют данные фреймворки. -4275.40 4290.04 SPEAKER_01 Еще из-за того, что они стали взаимодействовать больше с людьми, с нормальными людьми, с нормальными потребителями, у них немножко изменился подход к тому, как они распространяют Nuget пакеты и в общем как организуют свой API. -4290.04 4300.20 SPEAKER_01 Например, в третьем Orleans для того, чтобы вам сделать какую-то кастомную штуку, вам нужно было подключить пакет, называющийся Orleans Code Generator MS Build. -4300.20 4306.76 SPEAKER_01 В общем, это довольно неочевидная вещь, которую в памяти держать сложно, но она вам нужна для практической генерации там силосовых клиентов. -4306.76 4318.00 SPEAKER_01 В новом 7 Orleans все это упростили, теперь вам достаточно подключить к вашему проекту просто MicrosoftOrleans.client пакет и вы получите клиента. -4318.00 4322.60 SPEAKER_01 Если вы подключите MicrosoftOrleans.server, не поверите, но вы получите сервер. -4322.60 4327.92 SPEAKER_01 И все это довольно стало таким человеческим языком, с человеческим лицом, теперь заработало. -4327.92 4345.04 SPEAKER_01 Вот в принципе все такие нововведения, которые стоит упомянуть для того, чтобы рассказать, что Orleans тоже примкнул к релизам .NET, к команде .NET, и теперь, скорее всего, будет как-то рядышком вместе с ним развиваться и тоже как-то улучшать свою общую инфраструктуру. -4345.04 4347.96 SPEAKER_00 Ну, неплохо. -4347.96 4360.52 SPEAKER_00 Наверное, это не тот фреймворк, который там прям широко распространен с точки зрения там среднего проекта, наверное, его не используют, но есть наверняка те, кому он нужен и интересен. -4360.52 4368.08 SPEAKER_00 И если вы уже его вдруг используете, то как раз обновиться на 7, кажется, однозначно нужно, получите бесплатный буст в перформансе. -4368.08 4375.24 SPEAKER_00 Давай пойдем дальше, мы много чего проговорили про всякие нововведения во фреймворках, теперь пора поговорить про тулы. -4375.24 4378.32 SPEAKER_00 А как же всем этим пользоваться? -4378.32 4389.36 SPEAKER_00 Понятное дело, что у нас есть SDK, который можно скачать и поставить, и вам ничего не нужно будет больше делать, но код где-то редактировать надо, и для этого у нас есть и DE. -4389.36 4399.60 SPEAKER_00 Для начала это Visual Studio 2022.17.4, официальная студия от Microsoft, последний стейбл-релиз, он поддерживает как раз .NET 7. -4399.60 4410.24 SPEAKER_00 Там есть много всяких разных улучшений помимо, собственно, самой поддержки .NET 7, мы про них рассказывали раньше, я на них не буду сильно прям останавливаться, хотя быстренько пробежимся. -4410.24 4422.76 SPEAKER_00 Мы говорили про то, что у нас теперь в студии появились звуки, то есть всякие штуки, которые срабатывают, когда происходят деленные события в студии, там когда у вас breakpoint сработал, или когда вы в поиске что-то сделали, или когда у вас билд закончился. -4422.76 4424.24 SPEAKER_00 Можно теперь настроить разные звуки. -4424.24 4425.24 SPEAKER_00 Датабейс визуал... -4425.24 4426.24 SPEAKER_00 Датабейс, дататейбл визуалайзер. -4426.24 4433.96 SPEAKER_00 Если у вас есть айнумерабл, либо что-то подобное, вы теперь в дебайгере можете посмотреть содержимое в красивом табличном виде. -4433.96 4439.52 SPEAKER_00 Ну и если у вас есть эксепшн, то у него появляется окошко, там теперь можно нормально посмотреть call stack. -4439.52 4440.52 SPEAKER_00 Прям удобно. -4440.52 4449.28 SPEAKER_00 Это те штуки, которые мы рассказывали до этого, там понятно, что перформанс улучшился, всячески разные тесты быстрее запускаются, вот это все. -4449.28 4458.56 SPEAKER_00 Помимо этого в последний, так сказать, вагон релиза успела запрыгнуть новая фича, которой не было в превьюшках, про которую мы не говорили, называется multi-repo-support, ну multi-repository-support. -4458.56 4465.36 SPEAKER_00 Эта штука позволяет вам иметь до 10 активных гид-репозиториев одновременно. -4466.24 4473.04 SPEAKER_00 То есть у вас, Microsoft говорит, например, если у вас есть солюшен, в котором есть больше, чем один репозиторий. -4473.04 4480.60 SPEAKER_00 Мне сложно представить, как у меня так есть солюшен, который распилен на много репозиторий, но наверное у Microsoft есть или у каких-то кастеров есть. -4480.60 4485.20 SPEAKER_01 То есть у тебя как репозиторий будут внутри репозиторий или рядом с репозиториями? -4485.20 4487.04 SPEAKER_01 Как это вообще технически это организовать? -4487.04 4500.40 SPEAKER_00 Ну у меня есть репозиторий, в котором лежит солюшен, который нужно склонировать, рядом склонировать репозиторий, допустим, с какими-то другими частями, а из солюшена, через какие-нибудь, знаешь, относительные пути, у меня будут ссылочки на CS Project. -4500.40 4504.56 SPEAKER_01 Да, но тогда у тебя получается, что структура не очень стандартная, да? -4504.56 4508.76 SPEAKER_01 Не когда у тебя солюшен лежит на верхнем уровне, а под низом там всякие папочки с проектами. -4508.76 4521.36 SPEAKER_00 И я согласен, поэтому фича выглядит немножко странной для солюшена, но написано, что можно это делать не только на солюшенах, но и просто открыть несколько гид-репозиторий из фолдера. -4521.36 4528.72 SPEAKER_00 Они приводят пример, что, ну например, вы работаете над каким-нибудь веб-проектом, и у вас часто там frontend и backend лежат в разных репозиториях. -4528.72 4532.04 SPEAKER_00 Но обычно это разные солюшены. -4532.04 4535.20 SPEAKER_00 Ну frontend это иногда вообще не солюшен. -4535.20 4536.20 SPEAKER_00 Давай начнем с этого. -4536.20 4540.80 SPEAKER_01 Ну в терминах нормальных людей, конечно же, это не солюшен, но скорее всего у них там есть какой-нибудь файл проекта. -4540.80 4555.72 SPEAKER_00 Ну вот, короче, по мнению Microsoft, теперь вы можете открыть одновременно и там, и там, и смысл фичи заключается в том, что когда вы будете говорить create branch, он будет создаваться одновременно во всех гид-репозиториях, когда вы будете говорить push, он будет вас спрашивать там в каком порядке запушить и пушить во все репозитории. -4555.72 4559.80 SPEAKER_00 Когда вы будете переключать branch, он будет переключаться во всех репозиториях одновременно. -4559.80 4569.52 SPEAKER_00 Что-то в этом есть, то есть мне иногда полезна фича, когда на нескольких гид-репозиториях нужно одновременно переключиться на мой какой-нибудь branch, на котором я работаю. -4569.52 4574.36 SPEAKER_00 Но как это будет работать в реальной жизни, пока непонятно. -4574.36 4579.60 SPEAKER_01 Ну да, с несколькими репозиториями это как-то выглядит довольно пока непонятно. -4579.60 4590.64 SPEAKER_00 Ну то есть у нас был кейс, у нас был проект, как-то действительно, ну там по сути получалось, что у тебя несколько сервисов живут, каждый в своем solution и каждый в своем репозитории. -4590.64 4598.12 SPEAKER_00 Плюс еще библиотечка какая-то была, которая тоже живет, ну типа Nuget свой, он тоже с отдельной solution, но в отдельном репозитории. -4598.12 4604.08 SPEAKER_00 Была необходимость работать с ними со всеми одновременно, создав везде один и тот же branch. -4604.08 4608.28 SPEAKER_01 Не, ну это окей, но скорее всего для этого используются обычно сабмодули. -4608.28 4610.12 SPEAKER_01 Нет, зачем сабмодули, почему? -4610.12 4615.76 SPEAKER_00 Я Nuget же solution собираю, он пабличится в Nuget, какой мне сабмодуль, зачем мне сабмодуль для Nuget? -4615.76 4620.48 SPEAKER_01 Нет, здесь же проблема не в Nuget solution, а именно в его физическом расположении. -4620.48 4630.96 SPEAKER_01 Nuget или не Nuget, это не важно, что ты соберешь, главное как ты его расположишь у себя на диске, то есть каким образом ты на диске себе сделаешь 10 репозиторий рядом и на них натравишь один solution. -4630.96 4639.00 SPEAKER_00 Вот у меня это были разные solution, это было 3 разных solution в 3 разных репозиториях, но мне хотелось с ними работать как бы одновременно, везде создавать один и тот же -4639.00 4641.00 SPEAKER_01 branch. Ну это окей, но кажется, что это не твой кейс. -4641.00 4642.00 SPEAKER_01 Вот непонятно. -4642.00 4645.92 SPEAKER_01 Они так смотрят, что у тебя обязан быть один solution, иначе студия его не откроет, она не поймет, что открывать. -4645.92 4651.08 SPEAKER_00 Я согласен, непонятно пока, как это работает и как это будет выглядеть, но я не пробовал ещё. -4651.08 4659.92 SPEAKER_00 У меня стоит, кстати, по-моему, 17.4 по идее, я обновлялся сразу после релиза, так что теоретически у меня это есть, можно проверить, надо будет попробовать, может быть проверю, расскажу. -4659.92 4664.72 SPEAKER_01 Ну проверить ты можешь, что оно работает, просто непонятно, как это применять на практике. -4664.72 4670.76 SPEAKER_00 Ну вот, может быть мы последим, если появятся статьи про то, что вау, как это круто, мы не знали. -4670.76 4674.20 SPEAKER_00 Или если такую штуку завезут в райдер, потому что в райдере по-моему такого нету. -4674.20 4676.60 SPEAKER_00 Значит, эта штука действительно полезная. -4676.60 4684.36 SPEAKER_00 Так, параллельно с 17.4 релизом, естественно, зарелизился 17.5, превью 1. -4684.36 4686.80 SPEAKER_00 Там появились интересные штуки. -4686.80 4692.04 SPEAKER_00 Это понятно, что это превью 1, там ничего супер крутого обычно не завозят, но тем не менее. -4692.04 4699.04 SPEAKER_00 У нас теперь можно расцвечивать табы через RegEx, вы можете взять RegEx для матчинга соответствующих цветов. -4699.04 4703.12 SPEAKER_00 Я не знаю, опять же, зачем, но нужно, видимо, кому-то. -4703.12 4705.24 SPEAKER_00 Markdown поддержку улучшили. -4705.24 4724.88 SPEAKER_00 Если вам надоело, что при запуске вашего ASP.NET-приложения у вас открывается консолька, отдельная, в которой output пишется, то начиная с Visual Studio 17.5 превью 1 этот output будет перехватываться и писаться в терминалке, что-то внутри, в Tool Window в студии, без отдельной консольки. -4724.88 4730.24 SPEAKER_01 Блин, это самая большая фишка, которая меня бесит в райдере, и вот и они тут даже. -4730.24 4731.24 SPEAKER_01 Ну что это такое? -4731.24 4732.24 SPEAKER_00 Возможно, это отключаемо, посмотрим. -4732.24 4733.24 SPEAKER_00 Ну, будем надеяться. -4733.24 4737.56 SPEAKER_00 Когда доберемся, я надеюсь, у нас будет какая-нибудь отдельная статья про превью 1, где мы подробно это рассмотрим. -4737.56 4746.04 SPEAKER_00 И еще в дебагере, я вот не знаю, эта фича появилась уже в 17.4, в дебагере есть такая штука под названием Managed Memory. -4746.04 4751.56 SPEAKER_00 Не, ну по идее она была и раньше, наверное, всегда можно было посмотреть memory по определенному адресу. -4751.56 4766.80 SPEAKER_00 Но здесь это именно фишка под названием Managed Memory, в которой есть Duplicate String Visualizer, то есть теперь есть таблочка, в которой можно посмотреть все аллоцированные за время приложения работы строки, со статистикой, какие строки, в каком количестве были зааллоцированы, и есть ли там повторение. -4766.80 4771.44 SPEAKER_00 То есть прямо вот конкретно про Duplicate String. -4771.44 4782.60 SPEAKER_00 Скорее всего они будут, видимо, эту штуку развивать дальше, и там полноценной dot memory, наверное, не получится, но может быть что-то близкое потихонечку начнет вырисовываться. -4782.60 4785.96 SPEAKER_00 Надо сказать, что про студию, наверное, это все. -4785.96 4793.32 SPEAKER_00 В райдере, соответственно, используйте YAPK, и только YAPK полноценно поддерживает седьмой .NET. -4793.32 4801.00 SPEAKER_00 Надо сказать, что за время, собственно, подкаста с момента прошлого релиза на шестого .NET мы все время про студию говорили в трех ключах. -4801.00 4808.52 SPEAKER_00 У нас была просто студия, у нас была студия для Mac'а, и у нас была студия для ARM64. -4808.52 4814.76 SPEAKER_00 Сейчас студия для ARM64 это уже, собственно, никакая не отдельная студия, это просто студия. -4814.76 4820.16 SPEAKER_00 Она есть, она вышла тоже в том числе, то есть версия 17.4 доступна для ARM. -4820.16 4826.36 SPEAKER_00 Там есть не все workloads, которые вы, может быть, хотели бы там видеть. -4826.36 4831.28 SPEAKER_00 Там есть поддержка .NET, Desktop Development, причем как .NET и так плюсов. -4831.28 4840.52 SPEAKER_00 Там есть ASP.NET, понятное дело, Web Development, UVP, экстенджеры можно девелопить, игрушки можно девелопить на C++ и на Node.js можно девелопить. -4840.52 4844.48 SPEAKER_00 Вот это только те workloads, которые поддержаны на студии на ARM64. -4844.48 4853.24 SPEAKER_00 Собирать при этом их можно, используя седьмой или шестой .NET и .NET Framework 481, которые, как мы помним, обновились для поддержки ARM64. -4853.24 4860.68 SPEAKER_00 MAUI не поддержана, так что если вы планируете работать с MAUI, то пока не используйте ARM64 в Visual Studio. -4860.68 4863.28 SPEAKER_00 В общем, это все, что можно сказать про ARM64. -4863.28 4871.64 SPEAKER_00 Я не думаю, что какие-то будут отдельные дальше у нас упоминания конкретно про ARM64, кроме если каких-то отдельных кейсов. -4871.64 4874.92 SPEAKER_00 Что же там такое интересное завезли про Mac? -4874.92 4878.28 SPEAKER_00 Кстати, тишина и ничего не сказали в момент релиза. -4878.28 4884.68 SPEAKER_00 Я, по крайней мере, не видел нигде в анонсах никаких упоминаний про Visual Studio for Mac. -4884.68 4896.64 SPEAKER_00 Зато в версии 17.4 появилась фича под названием Visual Studio for Mac Rollback, которая позволяет откатить Visual Studio к предыдущему состоянию. -4896.64 4904.04 SPEAKER_00 Но единственное, что она позволяет сделать, это откатить версию к предыдущей заинсталированной версии, которая у вас была до этого. -4904.04 4906.92 SPEAKER_00 Дальше там есть тонкости с тем, что останется, что будет удалено. -4906.92 4917.68 SPEAKER_00 Если у вас были всякие там темы, фонты, клавиатурные сокращения, которые вы настроили, или положение окон, это все будет сохранено. -4917.68 4932.48 SPEAKER_00 Если у вас были какие-то профайлы специальные или юзер-сеттинги, которые не входят в набор синхронизируемых сеттингов, я не знаю, как это сходу понять, входит или не входит, то такие штуки будут заресторены в дефолт. -4932.48 4946.76 SPEAKER_00 И при этом, если вы делаете роллбэк на прошлую версию, то всяческие компоненты, которые входят в Visual Studio, там всякие SDK, вот это все, все, что оунится в самой Visual Studio, они будут зароллбэтчены. -4946.76 4959.68 SPEAKER_00 Если же какие-то есть системные компоненты, ну как пример это Ease, который в студии может быть поставлен, но Ease это такая системная компонента, которой может быть только одна и соответственно ее роллбэтчить не будут. -4959.68 4967.80 SPEAKER_00 Экстенджены могут быть тоже заанинсталлены, которые юзер инсталлил, и нельзя откатываться совсем уж назад. -4967.80 4977.70 SPEAKER_00 То есть для версии 17.4 вы можете откатиться максимум на 17.0.10 или 17.1.7, а для превью ченнелы только на 17.2 превью один. -4977.70 4981.24 SPEAKER_00 Зароллбэтчиться можно через UI или через command line. -4981.24 4989.20 SPEAKER_00 Дальше, в общем звучит в принципе норм, хотя есть несколько интересных моментов. -4989.20 4999.96 SPEAKER_00 В обсуждении этой статьи, ну в комментах к этой статье про анонс, там написано типа "Ооо, кажется студию 17.4 ставить нельзя, если они вписали туда такую фичу, значит они не уверены в качестве студии". -4999.96 5005.20 SPEAKER_00 Вот, типа надо ждать превьюшек, ну не превьюшек, а типа сервиспака в дальнейших. -5005.20 5014.36 SPEAKER_00 Второй момент, что, представьте, у вас стояло там не знаю 17, кто у нас там был в прошлом, ну 3 видимо, или там 17.2. -5014.36 5017.00 SPEAKER_00 Вы поставили 17.4, попробовать. -5017.00 5019.44 SPEAKER_00 Ну релиз, там все дела, дот над 7 хочется. -5019.44 5022.40 SPEAKER_00 Там например что-то не работает. -5022.40 5032.80 SPEAKER_00 Вы подумали, интересно, а не исправлено ли это в последнем каком-нибудь хотфиксе, и ну вот пока вы там пробовали и ждали, вышел хотфикс какой-нибудь, да, 17.4.1. -5032.80 5038.48 SPEAKER_00 Вы поставили 17.4.1, выяснили, что ваш баг не пофикшен, который вам там мешает в содалей поведении. -5038.48 5040.12 SPEAKER_00 Вы хотите сделать роллбэк? -5040.12 5042.56 SPEAKER_00 Куда вы сможете сделать роллбэк? -5042.56 5046.08 SPEAKER_01 Ну зависит от того, сколько версий там она хранит и как она их хранит. -5046.08 5052.92 SPEAKER_00 Хранит она ровно одну, поэтому вы сможете сделать откат только на 17.4, хотя хотелось бы на 17.2. -5052.92 5055.00 SPEAKER_00 Понятное дело, на ту, которая была стабильная. -5055.00 5066.52 SPEAKER_00 На самом деле там тоже был вопрос, хранит ли она что-то, она не хранит, она хранит только мета-данные, то есть непосредственно бинарников ничего не хранится, она их заново из интернета скачает и как бы поставит. -5066.52 5069.68 SPEAKER_00 Просто она это сделает с восстановлением каких-то сеттингов. -5069.68 5070.68 SPEAKER_00 Ну смысл в том… -5070.68 5074.96 SPEAKER_01 Не, ну твои-то шоткаты и вот эти положения окон, как ты говорила, они уже все, наверняка должны -5074.96 5080.92 SPEAKER_00 охранить локально. Не-не-не, это-то понятно, она хранит, ну в смысле, что она это возьмет из вот текущей студии. -5080.92 5090.60 SPEAKER_00 Не в смысле, что она… если вы поставили, не знаю, использовали 17.2, там настроили окна, поставили 17.4, перенастроили окна, откатились на 17.2, настройки окон останутся новыми от 17.4. -5090.60 5094.80 SPEAKER_01 А, я как раз думал, что она в том числе сохраняет и старые настройки окон. -5094.80 5100.76 SPEAKER_00 Не-не-не, она именно в смысле, что она чисто обновит, ну бинарники, но постарается сохранить настройки. -5100.76 5113.52 SPEAKER_00 То есть, грубо говоря, ну как, я не знаю, винда с апдейтами, то есть ты типа от того, что ты перенастроил чуть-чуть винду, постольку накатились апдейты, если ты снесешь апдейт, если этот апдейт не касался конкретной настройки, ну ничего не поменяется, настройки-то сохранятся. -5113.52 5120.80 SPEAKER_01 Слушай, а какая разница, если я вот снесу 17.4 и поставлю, ну, себе дезербитива, поставлю ручками 17.2, 17.3, какая разница? -5120.80 5124.32 SPEAKER_00 Там, я так понимаю, что скорее всего с настройками будет, не все так хорошо. -5124.32 5128.40 SPEAKER_00 Хотя, если они синхронизируются и через какую-нибудь облако синхронизируются, то должно быть пофигу. -5128.40 5129.40 SPEAKER_00 Не знаю. -5129.40 5130.40 SPEAKER_00 Типа да. -5130.40 5146.16 SPEAKER_00 Ну вот народ написал в таких комментах, что ну блин, если вот в том сценарии, что я перечислил, да, попробовали поставить hotfix, не помогло, хочу теперь откатиться, а откатиться я теперь не могу, потому что я поставил hotfix, я могу откатиться только на основную версию, а на предыдущую безбажную не могу, кажется, проще снести и поставить. -5146.16 5152.56 SPEAKER_00 В общем, странная фича, непонятно зачем сделана, непонятно зачем именно в таком виде сделана. -5152.56 5160.36 SPEAKER_00 С другой стороны, ну то есть, тот же, допустим, тулбокс от JetBrains, он тоже позволяет делать rollback, но там можно настроить сколько старых версий ты хранишь. -5160.36 5164.12 SPEAKER_00 Одну, две, три, пять, я не помню, есть ли там лимит, ну понятно. -5164.12 5171.84 SPEAKER_00 Но там все понятно, там они каждый ставят свою папочку, ну вот он просто переключит вас на старую папочку и все будет работать. -5171.84 5175.64 SPEAKER_01 Ну, может быть, эту штуку тоже допилят, будет тебе 10 версий хранить. -5175.64 5180.28 SPEAKER_01 Теперь мы чистим свой диск, не только от JetBrains будем чистить, а будем чистить свой диск еще от Visual Studio. -5180.28 5181.28 SPEAKER_00 А почему нет? -5181.28 5182.28 SPEAKER_00 Вот. -5182.28 5183.28 SPEAKER_00 Действительно. -5183.28 5187.56 SPEAKER_00 Это Visual Studio, давай теперь поговорим про NuGet, там тоже есть что новенького. -5187.56 5197.00 SPEAKER_01 Да, давай, не то чтобы прям много всего интересного, но такие концептуальные вещи, которых мы, опять же, упоминали в течение года, в NuGet и новом тоже зарелизились. -5197.00 5205.84 SPEAKER_01 NuGet вышел 6.4, и самым главным лейтмотивом этой версии – это, конечно же, Central Package Manager. -5205.84 5217.16 SPEAKER_01 Это специальный файлик, который можно положить в вашем солюшене, и он способен обрабатывать информацию для нескольких проектов, ну то есть для всех проектов, которые есть в вашем солюшене. -5217.16 5230.00 SPEAKER_01 Файлик называется directory.package.props, и он внутри себя содержит наименование пакетов и версии этих пакетов, которые приняты в вашем солюшене. -5230.00 5240.12 SPEAKER_01 Это значит, что теперь непосредственно в проектах вы можете указывать только наименования, которые нужны, те пакеты, которые нужны вашему проекту, и без указания версий. -5240.12 5244.76 SPEAKER_01 Версии он возьмет из вот этого глобального package management файла. -5244.76 5248.48 SPEAKER_01 Прелесть этого подхода в том, что вам больше не нужно консолидировать версии. -5248.48 5253.32 SPEAKER_01 То есть во всех проектах у вас в Сибибиблиотеке будут одно и то же версии. -5253.32 5260.04 SPEAKER_01 Это позволяет избежать кучи ошибок, это хорошо, это правильно, и плюсов у этого громадное количество. -5260.04 5268.84 SPEAKER_01 Но в принципе такую штуку вы могли сделать и раньше ручками с помощью сложной системы props и target файлов. -5268.84 5272.08 SPEAKER_01 Плюс вот этого подхода в том, что он поддерживается инструментарием. -5272.08 5288.48 SPEAKER_01 То есть там всякие Visual Studio, Riders, Nuget консольные приложения, все они понимают этот файлик, и в отличие от того кастомного подхода с костылями, они будут нормально обновлять здесь эти пакеты, нормально везде пробрасывать, нормально интеллисенсом подхватывать, и в общем дело нужное. -5288.48 5296.76 SPEAKER_01 В качестве велосипеда она живет давно и наконец-то прекрасно, что она теперь поддерживается официально и инструментарий соответственно тоже подхватил всю эту штуку. -5296.76 5307.20 SPEAKER_01 Еще одно интересное нововведение, это возможность указать элемент в наших props файлах, который называется Global Package Reference. -5307.20 5316.20 SPEAKER_01 Это штука, которая позволяет вам указать имя и версию пакета, которая автоматически подключится во все другие проекты. -5316.20 5320.20 SPEAKER_01 Типичным примером есть у нас анализаторы. -5320.20 5324.04 SPEAKER_01 Анализаторы обычно подключают просто ко всем проектам, которые есть в Solution. -5324.04 5332.88 SPEAKER_01 Опять же, это можно было добиться с помощью старых props файлов, но здесь поддержка инструментария, интеллисенсов и прочие вещи тоже часто хромали. -5332.88 5345.04 SPEAKER_01 Теперь у нас есть официальные директивы, официальные файли, как это можно сделать, и можно соответственно подключить любую библиотеку с любой версией прозрачно и однако всем проектам, которые в вашем Solution есть. -5345.04 5351.72 SPEAKER_01 Естественно, вы можете обновлять теперь ее в одном месте, можете контролировать использование, можете ее подменять в одном месте. -5351.72 5353.72 SPEAKER_01 Тоже довольно удобная штука. -5353.72 5355.40 SPEAKER_01 Будем пользоваться. -5355.40 5362.40 SPEAKER_01 Из мелочей увеличили производительность отображения и загрузки списка пакетов в Visual Studio. -5362.40 5376.92 SPEAKER_01 Наверняка многие из вас заходили в Visual Studio на вкладку Management Nugget Packages и долгие минуты и часы ждали, пока прогрузятся все пакеты, пока обновятся их версии, пока проверятся и сигнатуры, подтянутся ряды. -5376.92 5381.24 SPEAKER_01 Вот это все увеличили, говорят, обещают, что на 66%. -5381.24 5386.12 SPEAKER_01 Циферка небольшая, но довольно приятная, особенно если для тех, кто часто заходит в это визуальное окошко. -5386.12 5389.44 SPEAKER_00 Да, действительно штука удобная. -5389.44 5396.88 SPEAKER_00 Мы такое костыляли с помощью директории, как там это называлось, что там тоже, Props, не помню что. -5396.88 5409.68 SPEAKER_00 И действительно там была проблема в том, что не было возможности, ну или по крайней мере мы не нашли каких-то простых костылей, как ограничить, ну как убедиться, что в конкретных проектах ты таки не указал случайно нужную версию. -5409.68 5415.56 SPEAKER_00 И если указал, то она использовалась вместо той, которая указана в центральном версии. -5415.56 5424.44 SPEAKER_00 Здесь это все контролируется, там теперь можно контролировать, можно ли оверрайдить версии, и они оверрайдятся специальным прям атрибутом, version override. -5424.44 5426.76 SPEAKER_00 Поэтому здесь действительно все будет удобно и хорошо. -5426.76 5434.60 SPEAKER_01 Да, старый подход, он там основывался на какой-то концепции, главное не чихайте на этот файл, иначе все развалится. -5434.60 5437.76 SPEAKER_01 В общем, с новым все довольно более стабильно. -5437.76 5445.48 SPEAKER_00 Ну и давай поговорим то, про что я обещал в самой первой новости, в самом начале этого выпуска, про поддержку контейнеров. -5445.48 5452.08 SPEAKER_01 Да, давай, в принципе это кажется единственной нашей статьей, которой нет Microsoft за весь сегодняшний выпуск. -5452.08 5467.00 SPEAKER_01 Но статья грамотная, она еще покрывает несколько интересных смежных тем, делает это правильно, с хорошими цифрами, поэтому мы решили ее добавить в выпуск, и поговорим мы как раз-таки о поддержке контейнеров, и что интересного на этой поприще есть в Дотэнт 7. -5467.00 5470.72 SPEAKER_01 Прежде всего хочется вас познакомить с таким понятием, как числт убунту контейнер. -5470.72 5477.32 SPEAKER_01 Это специальный контейнер, который очень маленький и очень секурный. -5477.32 5479.48 SPEAKER_01 Он поставляется официальным каноникалом. -5479.48 5487.20 SPEAKER_01 И его преимущество в том, что он где-то на 100% меньше обычной стандартной убунты. -5487.20 5494.24 SPEAKER_01 Если стандартная убунта у нас занимает 219 Мб, то числт контейнер занимает где-то 116 Мб. -5494.24 5498.52 SPEAKER_01 И так как он маленький, у этого есть много преимуществ. -5498.52 5503.48 SPEAKER_01 В частности, у нас очень сильно уменьшается площадь атаки. -5503.48 5510.24 SPEAKER_01 То есть у нас намного меньше инструментов, намного меньше утилит внутри контейнера содержится, намного меньше пакетов, которые могут быть атакованы. -5510.24 5516.00 SPEAKER_01 В которых могут найти баги, в которых могут найти уязвимости, какие-нибудь бэкдоры вам затянуть или еще что-то. -5516.00 5519.68 SPEAKER_01 В общем, чем меньше у вас зависимости, тем всегда это лучше. -5519.68 5525.24 SPEAKER_01 И вот это пример, когда попытались сделать вот такой минимальный контейнер по зависимости. -5525.24 5532.96 SPEAKER_01 Там нет пакетдж менеджера, там нет популярных пакетов предустановленных, которые обычно вы видите в своих контейнерах. -5532.96 5535.52 SPEAKER_01 Там вообще даже нет шела. -5535.52 5537.96 SPEAKER_01 И там нет рутового пользователя. -5537.96 5541.16 SPEAKER_01 Там обычный юзер без рута. -5541.16 5547.92 SPEAKER_01 Специфика этого контейнера заключается в том, что вы там даже не сможете выполнить баши, потому что там нет баши. -5547.92 5552.00 SPEAKER_01 Вы там не сможете даже выполнить команду ls, там показать список файлов, потому что там нет команды ls. -5552.00 5560.56 SPEAKER_01 То есть даже таких элементарных базовых утилит, с помощью которых вы обычно там навигируетесь по контейнеру и там ищите какие-нибудь проблемы, их там нет. -5560.56 5568.32 SPEAKER_01 Поэтому отлаживать, возможно, вам будет его немножко сложнее на первом этапе, но зато размер и, соответственно, площадь атаки очень сильно уменьшена. -5568.32 5575.56 SPEAKER_01 Вот такой контейнер, он сейчас официально поддерживается Майкрософтом, он лежит в репозитории Майкрософта с контейнерами. -5575.56 5579.84 SPEAKER_01 Соответственно, его можно легко и непринужденно завязать в ваших приложениях. -5579.84 5586.24 SPEAKER_00 Тут надо сказать, что он не то чтобы поддерживается Майкрософтом, он еще поддерживается Каноникалом, что тоже важно. -5586.24 5589.24 SPEAKER_00 То есть Каноникал это тот, кто дистрибьютирует и производит Ubuntu. -5589.24 5594.84 SPEAKER_00 То есть это не просто Майкрософт решила взять и что-нибудь там урезать, это прям Каноникал. -5594.84 5597.44 SPEAKER_00 Вместе с Майкрософтом сделали такую штуку совместную. -5597.44 5607.16 SPEAKER_01 Ну да, я подозреваю, что Каноникал сделал числот образ, а Майкрософт просто добавил туда зависимости для того, чтобы запускать там Дотнет. -5607.16 5608.16 SPEAKER_01 Скорее всего. -5608.16 5613.48 SPEAKER_01 Как всегда они, в принципе, на таком уровне взаимодействия у них идет. -5613.48 5623.84 SPEAKER_01 Вот, и еще одно нововведение, то есть это не еще одно нововведение, это нововведение, которое было сделано в Дотнет 7, которое мы уже тоже упоминали, это возможность генерировать докер-файлы. -5623.84 5631.36 SPEAKER_01 Как вы, наверное, все уже знаете, чтобы упаковать приложение в докер-контейнер, у нас есть так называемые докер-файлы. -5631.36 5636.08 SPEAKER_01 У них там свой синдекс, если они там каким-то образом описываются, думаю, что с этим вы уже все знакомы. -5636.08 5651.80 SPEAKER_01 Вот, и, соответственно, новинка Дотнет 7 SDK заключается в том, что теперь вам не обязательно делать отдельный рядышком стоящий докер-файл для того, чтобы сделать имидж, в котором лежит ваше приложение. -5651.80 5665.64 SPEAKER_01 Микрософт изобрел новый output type, то есть достаточно в Дотнет паблише указать специальные магические ключи и у вас в результате вашего паблиша получится уже полноценный докер-имидж без всякого докер-файла. -5665.64 5682.92 SPEAKER_01 Единственное, что вам нужно сделать, это подключить к вашему проекту специальный пакет, ну, get-пакет, который называется Microsoft.NET Build Containers, но это все на уровне пока разработки, и в будущем этого пакета тоже подключать не нужно будет, он будет входить в стандартные SDK Дотнета. -5682.92 5684.84 SPEAKER_01 Пока это так. -5684.84 5688.48 SPEAKER_01 В общем, если не нужно будет подключать никаких пакетов, это совсем прекрасно. -5688.48 5698.32 SPEAKER_01 Вот вы делаете команду dotnet-publish, указываете ей там, что хотите, опясываете систему Linux и передаете ее в специальный флажок, который называется publish-para-file и равняется он дефолт-контейнеру. -5698.32 5707.84 SPEAKER_01 И в результате чего в вашем распоряжении получается, как я уже сказал, докер-имидж, по дефолту его размер 216 или около того мегабайт. -5707.84 5714.00 SPEAKER_01 И этот имидж, его можно настраивать. -5714.00 5721.32 SPEAKER_01 Обычно мы настраиваем докер-контейнеры через докер-файл, так как у нас докер-файла нет, то мы можем настраивать через MS Build свойства. -5721.32 5734.12 SPEAKER_01 Через свойства наших MS-publish-файлов, props-файлов, targets-файлов, там можно указать имя контейнера, там можно указать теги и кучу-кучу других разных параметров, которые обычно вы указываете в дотнет-файле. -5734.12 5737.12 SPEAKER_01 В докер-файле. -5737.12 5738.12 SPEAKER_01 Извините. -5738.12 5739.12 SPEAKER_01 Вот. -5739.12 5742.64 SPEAKER_01 Это то нововведение, которое у нас есть в дотнет-7 SDK. -5742.64 5747.72 SPEAKER_01 Теперь, каким же образом нам теперь свести вместе два этих интересных новости? -5747.72 5748.72 SPEAKER_01 Свести их довольно просто. -5748.72 5753.40 SPEAKER_01 Как я уже сказал, в MS Build файле мы можем настраивать докер-контейнеры. -5753.40 5757.00 SPEAKER_01 Там есть специальный ключевой элемент, который называется container-base-image. -5757.00 5761.72 SPEAKER_01 И в качестве базового имиджа мы можем указать вот этот числт-образ. -5761.72 5776.04 SPEAKER_01 В результате чего мы набираем команду dotnet-publish и у нас уже появляется докер-имидж размером 112 мегабайт против наших 216, которые были буквально одну команду назад. -5776.04 5779.42 SPEAKER_01 Мы всего лишь навсего что и сделали, это поменяли базовый образ. -5779.42 5783.26 SPEAKER_01 То есть мы выиграли 104 мегабайта на пустом месте. -5783.26 5787.88 SPEAKER_01 Довольно неплохой результат, но в принципе можно сделать еще лучше и еще больше. -5787.88 5791.52 SPEAKER_01 В частности, мы можем сделать self-content. -5791.52 5799.48 SPEAKER_01 Насколько вы, наверное, уже в курсе, у нас дотнет умеет поставляться без дотнет-рантайма. -5799.48 5802.28 SPEAKER_01 Дотнет-рантайм ему не обязателен. -5802.28 5807.44 SPEAKER_01 Он может включить все библиотеки, которые нужны вашему приложению внутрь этого приложения. -5807.44 5813.64 SPEAKER_01 То есть тут вообще скопировать все ассембли, все дейдельки и все, что ему нужно, просто в одну папочку. -5813.64 5820.72 SPEAKER_01 Вот если мы воспользуемся этой функциональностью, сделаем self-content, тогда у нас появится такая возможность, как затримить наше приложение. -5820.72 5822.56 SPEAKER_01 То есть убрать все ненужное. -5822.56 5826.88 SPEAKER_01 То есть мы не должны тащить с собой весь огромный SDK, весь огромный рантайм. -5826.88 5835.76 SPEAKER_01 Мы можем проанализировать наше приложение и сказать, какие сборки нужны, какие не нужны. -5835.76 5839.12 SPEAKER_01 И вот флажок Trimton как раз это и делает. -5839.12 5855.72 SPEAKER_01 Если мы запустим теперь нашу сборку, наш паблиш вместе с усечением и вместе с self-content, то результирующий образ у нас будет всего лишь на 56 Мб. -5855.72 5864.72 SPEAKER_01 То есть сравнивая с предыдущими 112 Мб, мы сэкономили еще 55 Мб, что тоже довольно крутецкая оптимизация. -5864.72 5869.24 SPEAKER_01 Можно сделать еще немножко поменьше. -5869.24 5878.56 SPEAKER_01 Секрет заключается в том, что self-content приложение, которое внутри себя включает все, что ему нужно для запуска, его еще можно собрать в один единственный файлик. -5878.56 5885.84 SPEAKER_01 То есть у нас есть папочка, в которой было много сборок до этого, а теперь у нас будет папочка, в которой лежит всего лишь один единственный файл. -5885.84 5889.84 SPEAKER_01 Один бинарник и внутри этого бинарника зашиты все множество-множество сборок. -5889.84 5899.00 SPEAKER_01 Тут нужно уточнить, что у этого подхода есть некоторые ограничения и существует специальный сценарий, где такая штука работать не будет, где она не поддерживается. -5899.00 5905.04 SPEAKER_01 Но в общем, как потенциально возможная оптимизация, он существует. -5905.04 5912.68 SPEAKER_01 В результате такой махинации, в результате сингл-файла у нас появится один единственный файл размером 48 мегабайт. -5912.68 5918.64 SPEAKER_01 Сравнивая с предыдущими пятью, десятью, шестью, мы выиграли 8 мегабайт. -5918.64 5927.00 SPEAKER_01 Не то чтобы много, но в принципе на размерах, на размерах которых мы уже работаем, там в размерах 50 мегабайт, 8 мегабайт, это в принципе существенная часть. -5927.00 5930.76 SPEAKER_01 Поэтому тоже хорошая качественная оптимизация. -5930.76 5939.24 SPEAKER_01 Еще одна интересная оптимизация, которая существует в Дотнете, это штука, которая называется invariant globalization. -5939.24 5963.64 SPEAKER_01 То есть если в вашем приложении вы не используете никаким образом различные культуры, вы не форматируете, допустим, даты на русском языке, вы не сравниваете строки на греческом языке, в общем все вот эти штуки вам не нужны, а эта вероятность довольно большая, потому что большинство Дотнет-приложений это все-таки какие-нибудь серверные бэкэнды. -5963.64 5970.12 SPEAKER_01 И на серверных бэкэндах существует такая best practice, что вам там ни в коем случае не нужна никакая локализация. -5970.12 5973.00 SPEAKER_01 Там все должно быть в invariant и в UTC. -5973.00 5977.44 SPEAKER_01 То есть ни времен, ни локализации быть не должно и в помине. -5977.44 5986.00 SPEAKER_01 Локализация и времена, всякие часовые зоны вам нужны только там, где вы представляете уже непосредственно пользователя. -5986.00 5993.60 SPEAKER_01 То есть это или UI, или какие-нибудь отчеты, или какие-нибудь письма, то есть какое-нибудь уже конечное представление для пользователя. -5993.60 6003.56 SPEAKER_01 Если у вас чистый бэкэнд, который суровый, письма не шлет, с пользователем не взаимодействует, а чисто что-то там у себя крутит, вы вполне легко, скорее всего, можете этот флажок использовать. -6003.56 6016.04 SPEAKER_01 И это очень крутой флажок, когда вы говорите «удали мне все культуры, которые там у тебя есть, все транслейшн, которые у тебя есть, все ресурсы с переводами, которые у тебя есть, оставь только invariant globalization». -6016.04 6026.20 SPEAKER_01 Если вы такой флажок задаете, то обычно у вас тоже… у вас тоже огромный прирост в месте, то есть очень много места освобождается. -6026.20 6032.00 SPEAKER_01 В данном же случае автор попробовал сделать проверную такую штуку, и у него практически ничего не получилось. -6032.00 6038.32 SPEAKER_01 Из 48,4 мегабайта у него стало 48,3 мегабайта. -6038.32 6045.92 SPEAKER_01 То есть он удалил глобализацию только из своего конкретного приложения, которых и так было немного. -6045.92 6049.40 SPEAKER_01 А с фреймворка ничего не случилось. -6049.40 6050.68 SPEAKER_01 Секрет очень простой. -6050.68 6057.44 SPEAKER_01 Дело в том, что вот этот числ имидж, он уже внутри себя содержит вот эту функциональность. -6057.44 6065.60 SPEAKER_01 Он уже внутри себя, по сути, удалил всю глобализацию, все вот эти ресурсы, которые нужны для использования различных языков, ее там уже нет. -6065.60 6069.16 SPEAKER_01 Поэтому он такой компактный, большой и красивый. -6069.16 6074.16 SPEAKER_01 Проделав все эти возможные на данный момент оптимизации, которые у нас получились, давайте подведем итог. -6074.16 6077.00 SPEAKER_01 Изначальный имидж у нас был 216 мегабайт. -6077.00 6084.04 SPEAKER_01 Это, скорее всего, то, что имеет каждое дотальное приложение в ваших проектах. -6084.04 6097.60 SPEAKER_01 Это тот размер, который у вас будет по дефолту, если вы используете все дефолтные настройки, дефолтные контейнеры, дефолтные паблиши, вы примерно получите ваше приложение примерно в контейнере 216 мегабайт. -6097.60 6104.20 SPEAKER_01 И довольно элементарно, простыми действиями, его можно довести всего лишь навсего до 48 мегабайт. -6104.20 6109.12 SPEAKER_01 То есть, по факту, это 77% удалось нам ужать. -6109.12 6120.08 SPEAKER_01 Вот такими незамысловатыми способами, используя знания от, даже не знания, а имидж от Canonical с Microsoft и небольшие знания по оптимизации, по отримингу нашего приложения. -6120.08 6124.08 SPEAKER_01 То есть, сейчас у нас примерный имидж, минимальный имидж дотлнет приложения. -6124.08 6130.92 SPEAKER_01 Опять же, мы сейчас говорим не про какой-то экстремальный минимализм, а такой вполне бытовой, вполне рабочий, вполне повседневный. -6130.92 6133.52 SPEAKER_01 И это 48 мегабайт. -6133.52 6136.60 SPEAKER_00 Все было бы хорошо, если бы... -6136.60 6141.96 SPEAKER_00 Нет, ну все-таки мне кажется, что self-contained и trimming это пока еще не настолько популярная штука. -6141.96 6148.20 SPEAKER_00 Ну, self-contained популярная, а вот trimming, по-моему, пока еще не настолько популярная штука, тем более и паблишинг сингл файл. -6148.20 6159.16 SPEAKER_00 Это тоже отдельный вопрос, поэтому я бы сказал, что ну, наверное, справедливость ради не 48, а все-таки 56, если мы уберем сингл файл паблишинг. -6159.16 6167.12 SPEAKER_00 Ну и опять же, то, что мы уменьшили с 216, это если мы использовали стандартный ubuntu-овский обычный базовый имидж. -6167.12 6182.96 SPEAKER_00 Я же, например, ну у нас практически все живет на alpine, alpine поменьше, но с alpine есть как бы проблема, ну не то чтобы проблема, alpine это все-таки не distroless, насколько я помню, то есть там есть root, там есть вот все те самые баши и все такое прочее, то есть секьюрность у него все-таки поменьше. -6182.96 6190.56 SPEAKER_00 Поэтому тут надо выбирать, надо посмотреть, нельзя ли из alpine получить такую конструкцию урезанную, тут вот не знаю. -6190.56 6199.16 SPEAKER_01 Да, да, да, ты во всем прав, действительно хотелось бы от alpine тоже все отсечь ненужное и посмотреть, сколько он сможет выдать на таких размерах. -6199.16 6213.96 SPEAKER_00 Ну может кто-то где-то это уже сделал, если вдруг вы знаете какие-нибудь там правильные distroless базовые имиджи для дотонета и майкрософта, и alpine, расскажите нам в комментариях где-нибудь, мы это дело попробуем проверим, посмотрим. -6213.96 6218.20 SPEAKER_00 Может быть даже попробуем собрать какое-нибудь такое же приложение и посмотреть какого размера оно получается. -6218.20 6221.00 SPEAKER_00 Ну а на этом я думаю, что надо завершать. -6221.00 6228.32 SPEAKER_00 Мы собственно обозрели по-моему практически все, что было хоть как-то упомянуто на dotnet.conf. -6228.32 6235.32 SPEAKER_00 Понятно, что там был еще большой кусок, ну кстати не такой большой, как я ожидал, который был посвящен ажуру и прочим облакам. -6235.32 6238.80 SPEAKER_00 Там есть некоторое количество видео про эту тему, но не такое большое. -6238.80 6246.32 SPEAKER_00 Основное все-таки внимание было уделено действительно дотонету и всяким таким более фреймворк-ориентированным вещам. -6246.32 6265.84 SPEAKER_01 Как всегда в наших заметках к выпуску будет куча разных ссылок, в том числе ссылки на доклады, которые были непосредственно на dotnet.conf, поэтому проходите, читайте, смотрите, пробуйте сами, углубляйтесь в каждой темы, ходите по ссылкам глубже, переслушивайте наши выпуски, в общем тут поле для изучения довольно большое. -6265.84 6287.52 SPEAKER_00 Да, и часть ссылок ведет на learn.microsoft.com, который раньше был docs.com.msd, там прямо действительно сейчас очень хорошая документация, отличные статьи, которые не просто там описание класса и апишка, а именно прям вот хорошие учебные статьи, которые помогают очень сильно понять, как же все это работает вместе. -6287.52 6291.32 SPEAKER_00 Ну а на сегодня, наверное, будем завершаться. -6291.32 6311.20 SPEAKER_00 Мы отсмотрели все, мы отсмотрели dotnet.7, dotnet.conf, c#, f#, dotnet.conf, f#, f#, spanet, entity framework, ui, потрогали windows.forms, wpf, dotmall, потрогали экзотические вещи типа ml.net и arlinz, ну и посмотрели на tooling, visual studio в разных ее видах, nuget и поддержка контейнеров. -6311.20 6340.08 SPEAKER_00 В dotnet.7 новостей много, новости разные, будем следить теперь, что будет происходить, как будет адоптиться dotnet.7, какие будут выходить статьи на эту тему, и возможно какие-то ранние уже dotnet.8 штучки будут так или иначе появляться даже до первого превью, может быть нам что-нибудь попадется на глаза, мы начнем уже смотреть какие-то ранние, подсматривать я бы даже сказал, в ранние эксперименты команды на тему 8-го дотнета. -6340.08 6345.68 SPEAKER_01 Ну а на сегодня это достаточно, всем спасибо, кто дослушал до конца и до новых встреч, всем пока. -6345.68 6346.04 SPEAKER_00 Всем пока. -6346.04 6347.04 SPEAKER_00 С вами был я, Александр Малинин. -6347.04 6347.04 None И до новых встреч. -6347.04 6352.04 None Пока. -6352.04 6357.04 None Пока. -6357.04 6359.04 None *Субтитры делал DimaTorzok* +2451.72 2460.44 "Игорь Лабутин" Не, ну Java UI-ные тоже можно, возможно, это примерно одно и, так сказать, одного уровня проблемы. +2460.44 2468.08 "Анатолий Кулаков" Я думаю, я просто уже морально смирился, что Java мертва, это имя уже свободно и можно для сокращения JavaScript +2468.08 2472.72 "Игорь Лабутин" сюда добавить. Я только сегодня разбирал проект на Java Server Pages и тут на фреймворке 33.5. +2472.72 2475.72 "Анатолий Кулаков" Я думаю, что ты очень не радовался. +2475.72 2481.12 "Игорь Лабутин" Ничего, нормально, будем переводить на Blazor и .NET, что там, 7, 8. +2481.12 2484.28 "Игорь Лабутин" К тому времени, когда переведу, я думаю, что уже девятка может выйдет. +2484.28 2488.76 "Анатолий Кулаков" Которая автоматически научится транскопировать, видишь, что сейчас модно все транскопировать. +2488.76 2491.44 "Анатолий Кулаков" Да, в васм все это, в васм. +2491.44 2501.88 "Анатолий Кулаков" Еще до Blazor хотелось добавить, это теперь появилась возможность наконец-то обрабатывать изменения у Location, то есть тот участок, куда вводится ваш адрес. +2501.88 2512.88 "Анатолий Кулаков" То есть вы теперь можете перехватить изменения адреса и, соответственно, создать какой-то эффект, какой-то дополнительный User Experience в навигации. +2512.88 2518.04 "Анатолий Кулаков" То есть или подменять адрес, или наоборот, навигироваться без подменения адреса, или как-то управлять историей. +2518.04 2525.76 "Анатолий Кулаков" В общем, очень полезная штука, практически все UI и JavaScript фреймворки обязательно эту вещь используют. +2525.76 2528.72 "Анатолий Кулаков" В общем, и с Blazor теперь тоже можно это удобно делать. +2528.72 2533.04 "Игорь Лабутин" Да, и это все было, как я понимаю, все-таки про Blazor сервер, вроде как? +2533.04 2537.12 "Игорь Лабутин" Или это, у нас же есть Blazor Wasm, надо же каждый раз говорить, кто из них кто. +2537.12 2541.36 "Анатолий Кулаков" Я думаю, это общие вещи, которые поддерживаются и там, и там. +2541.36 2542.36 "Игорь Лабутин" Угу, хорошо. +2542.36 2547.96 "Игорь Лабутин" В васме тоже, на самом деле, появилось некоторое количество разных штук, прям специфичных для васма. +2547.96 2563.80 "Игорь Лабутин" То есть там теперь можно, вот я не помню, это в семерке появилось все-таки раньше, но сейчас точно улучшили, что теперь можно запихнуть это все в native варианте, то есть вы можете же в ваш Blazor Wasm приложение запихнуть в васм двумя способами. +2563.80 2572.24 "Игорь Лабутин" Либо положить C#, ну, или код, да, фактически, плюс интерпретатор, либо сразу его скомпилировать, так сказать, нативно в нативные васмовские обкоды. +2572.24 2589.84 "Игорь Лабутин" И вот если вы это делаете в нативный вариант, в native out, то у вас сразу, компилятор теперь знает про всякие CMD, exception handling нативный васмовский, и, конечно, ну и у вас приложение становится прям круче работать. +2589.84 2594.72 "Игорь Лабутин" Но это требует, понятно, native out компиляции, которая со своими ограничениями. +2594.72 2606.60 "Игорь Лабутин" И в качестве эксперимента в Blazor Wasm завезли поддержку многопоточности, то есть вы теперь все # коди пишете там new thread, ну, как вы обычно пишете на C#, хотя это, наверное, давно много кто не писал уже new thread, все на тасках. +2606.60 2621.32 "Игорь Лабутин" Но если вам вдруг именно нужен мультитрейдинг такой нормальный, то вы пишете в C# new thread, а внутри это в браузере будет нормально через worker обрабатываться, и все будет работать как будто это обычное многопоточное приложение. +2621.32 2622.80 "Игорь Лабутин" Хотя это браузер, который по определению не многопоточен. +2622.80 2631.84 "Анатолий Кулаков" Слушай, нет, ну thread-то не обязательно писать, даже если ты будешь async/await-ами пользоваться, то они уже автоматически подхватят эти background полы и сделают +2631.84 2636.56 "Игорь Лабутин" тебе параллельность. Ну вот async/await, да, это, по-моему, и было. +2636.56 2642.56 "Игорь Лабутин" А вот если ты писал new thread, вот прям тебе нужно какую-то длинную бэкграундную работу зафигачить, вот этого раньше не было. +2642.56 2644.64 "Игорь Лабутин" New thread API вроде не была поддержана, теперь будет. +2644.64 2652.04 "Анатолий Кулаков" Ну именно так, async/await были, но они запускались в одном потоке, а теперь async/await на месте же останутся, но теперь они будут запускаться в нескольких потоках. +2652.04 2656.84 "Анатолий Кулаков" То есть вам достаточно перекомпилировать, грубо говоря, ваш код с async/await-ами, и все заработает уже параллельно. +2656.84 2663.24 "Игорь Лабутин" В общем, нам из вас мы делают такой полноценный рантайм, в котором можно делать вообще все, что вы обычно делаете. +2663.24 2665.76 "Игорь Лабутин" Останется только добавить какой-нибудь нормальный UI. +2665.76 2668.76 "Игорь Лабутин" Смотри, Maui, да, например. +2668.76 2675.68 "Игорь Лабутин" И можно будет, да, отказаться от JavaScript, наконец-таки может быть когда-нибудь, но не факт. +2675.68 2677.20 "Игорь Лабутин" Давай пойдем дальше. +2677.20 2685.72 "Игорь Лабутин" Третий наш большой кусок от документа, который мы всегда тоже отсматриваем, это Entity Framework. +2685.72 2689.64 "Игорь Лабутин" Работа с данными всегда важна, в Entity Framework тоже много изменений. +2689.64 2693.76 "Игорь Лабутин" Основной фокус шестого Entity Framework был на перформанс по чтению. +2693.76 2699.48 "Игорь Лабутин" Они там пытались догнать даппер, и, насколько я помню, если не догнали, то очень-очень близко приблизились. +2699.48 2706.36 "Игорь Лабутин" Фокус седьмого Entity Framework был на перформансе сохранения, то есть перформансе записи и всего, что с этим связано. +2706.36 2713.36 "Игорь Лабутин" Тем не менее, помимо сохранения, завелись и какое-то количество просто общих фич, про которые мы сначала и поговорим. +2713.36 2720.80 "Игорь Лабутин" Во-первых, это Table Per Concrete Type Mapping, то есть если вы иерархию объектов хотите хранить в байте, у вас есть три варианта. +2720.80 2735.16 "Игорь Лабутин" Либо всю иерархию храним в одной широкой таблице, либо мы храним кучку таблиц на каждый класс, включая все абстрактные и промежуточные классы, либо мы храним только листовые классы с конкретным набором полей уже. +2735.16 2738.28 "Игорь Лабутин" Каждая такая табличка будет включать набор всех, в том числе родителей. +2738.28 2740.20 "Игорь Лабутин" Вот третий вариант теперь поддерживается. +2740.20 2741.88 "Игорь Лабутин" Два предыдущих были поддержаны до этого. +2741.88 2751.80 "Игорь Лабутин" Все это можно настраивать в вашем OnModule, в модул-конфигураторе, и Entity Framework это все нативно теперь нормально поддерживает. +2751.80 2753.56 "Игорь Лабутин" Кроме того, поддержаны JSON-колонки. +2753.56 2775.84 "Игорь Лабутин" Причем JSON-колонки поддержаны хитрым образом, если он будет очень стараться, пытаться собрать именно SQL выражения, которые, например, при апдейте будут обновлять только кусочек JSON, значения JSON-колонки, а не просто перезаписывать целиком колонку заново, а прям генерить SQL, который обновит содержимое JSON внутри колонки, если SQL, понятно, база такое поддерживает. +2775.84 2782.44 "Игорь Лабутин" Доступ к этим JSON-колонкам делает через LinkU, и все это совершенно замечательно работает довольно нативно. +2782.44 2794.48 "Игорь Лабутин" Скорее всего это, конечно, супернативно работает именно на SQL-сервере как основной, понятное дело и первой, наверное, базе, на которой все обычно поддерживается в Entity Framework, но в FosgreSQL, скорее всего, тоже все хорошо работает. +2794.48 2797.44 "Игорь Лабутин" Про остальные базы сказать не могу. +2797.44 2823.52 "Игорь Лабутин" Entity Framework обрел поддержку bulk-updates и bulk-deletes, если вам, например, нужно было обновить пачку объектов по какому-то условию и поставить им всем определенное значение в какой-то поле, там, не знаю, флажок в бульоне, в колонке, то на старых фреймворках нужно было сказать сначала получить все это дело, то есть загрузить все это из базы, обновить, просто в обычном C# коде, и потом сказать save changes. +2823.52 2833.76 "Игорь Лабутин" Это накладывает некоторые ограничения на скорость, потому что включается object tracker, чтобы save changes нормально работал, в Entity Framework нужно потракить все изменения и так далее. +2833.76 2834.76 "Игорь Лабутин" Теперь появляется возможность сделать по-другому. +2834.76 2851.68 "Игорь Лабутин" Вы теперь пишете "ef.where...execute bulk-update", дальше пишете, что собственно нужно сделать с этим book'ом, лямдочку, и он на основе этого сгенерит правильный SQL, который прям сразу update where сделает, как надо. +2851.68 2853.60 "Игорь Лабутин" Такая же штука с delete'ом. +2853.60 2854.60 "Игорь Лабутин" Теперь работает. +2854.60 2857.40 "Игорь Лабутин" Save changes тоже стал быстрее. +2857.40 2873.56 "Игорь Лабутин" В save changes, по-моему, это был даже чуть ли не последний выпуск, ну последний выпуск был про dotnext, по-моему, перед этим выпуском мы обсуждали save changes довольно активно, про то, что там брали лишнее количество транзакций, то есть, например, если вы делали один-единственный insert, то это приводило к трем round trip'ам. +2873.56 2882.12 "Игорь Лабутин" Сначала скажи там begin transaction, потом выполни, потом скажи commit transaction, хотя на самом деле база и так все это сделает за вас, если вы делаете один-единственный insert. +2882.12 2887.28 "Игорь Лабутин" И всякие такие штуки, плюс batching по 42 элемента. +2887.28 2890.92 "Игорь Лабутин" В общем, save теперь стал работать тоже пошустрее. +2890.92 2896.76 "Игорь Лабутин" Из дополнительных таких фич еще появился маппинг на хранимые процедуры. +2896.76 2901.64 "Игорь Лабутин" Он был для select'ов, теперь можно для insert'ов, update'ов и delete'ов теперь тоже хранимки использовать. +2901.64 2919.84 "Игорь Лабутин" Если вы используете, генерите структуру ваших классов, моделей данных из базы данных, то есть то, что называется database first, то вы теперь можете специальной командой через .NET tool поставить себе темплейты в t4 темплейты внутрь проекта и их подкастомизировать как вам угодно. +2919.84 2938.64 "Игорь Лабутин" То есть, например, если у вас по дефолту entity framework коллекции поменяет как лист от t, если вам хочется observable collection какой-нибудь или ваш кастомный тип коллекции, то там это прям в t4 темплейте правите и когда вы будете генерить в следующий раз модели с базы, ну все будет уже согласно вашим темплейтам. +2938.64 2959.76 "Игорь Лабутин" Ну и если вы крутой чувак, который хорошо знает внутренности entity framework и всячески кастомизируете его или подписываетесь на его события или используете так называемые интерцепторы, то завезли некоторое количество новых штук, которые вызываются перед компиляцией запроса, после компиляции запроса, перед выполнением обращения к BD, после выполнения обращения к BD. +2959.76 2972.04 "Игорь Лабутин" Если вы это используете, то вот как раз смотрите туда, там появились новые штуки, которые возможно помогут вам сделать какие-нибудь еще крутые вещи на entity framework, как-то в его pipeline клинится. +2972.04 2975.80 "Анатолий Кулаков" Ну что ж, пойдем посмотрим, что у нас здесь еще есть. +2975.80 2980.80 "Анатолий Кулаков" У нас притаилась и такая неочевидная вещь для .NET, это как UI-ки. +2980.80 2984.28 "Анатолий Кулаков" Давай посмотрим, UI-ков у нас много теперь. +2984.28 3004.32 "Игорь Лабутин" В UI-ке в .NET это какая-то такая странная немножко история, их действительно много, мы сегодня обсудим три, их на самом деле больше, потому что есть те, которые неофициальные и не от Microsoft, но UI в .NET это всегда какая-то такая штука, которая непонятно где работает, как работает, в каком она состоянии работает и чем вообще надо пользоваться. +3004.32 3007.80 "Игорь Лабутин" Я до сих пор беру Windows Forms, когда мне что-то надо по-быстренькому наклепать. +3007.80 3014.04 "Анатолий Кулаков" Ну, нужно признать, что все было довольно понятно и просто, когда мы были только под виндой. +3014.04 3017.88 "Анатолий Кулаков" Вот когда появились всякие Mac и Linux, и вот там началось разброты шатания. +3017.88 3020.96 "Анатолий Кулаков" И куда надо шататься? +3020.96 3026.64 "Анатолий Кулаков" До сих пор мы не имеем какого-то одного ответа, и я думаю, что сейчас вы по анонсам, примерно, поймете почему. +3026.64 3044.28 "Анатолий Кулаков" Начнем, как всегда, с твоего любимого старичка, Windows Forms, который по-прежнему жив, и я вообще, если честно, удивился, найдя его анонс вместе с .NET 7, и еще больше удивился, когда прочитал его анонс, потому что происходит что-то странное, друзья, и поэтому предлагаю все вместе посудить. +3044.28 3046.16 "Анатолий Кулаков" Давайте пробежимся по нововведениям. +3046.16 3055.96 "Анатолий Кулаков" Прежде всего, улучшили accessibility в Windows Forms, то есть сделали много таких интересных вещей, которые помогают, например, в автоматизации. +3055.96 3063.80 "Анатолий Кулаков" Ну, улучшили, например, Scream Reader и тот сервис, который известен под названием Narrator. +3063.80 3076.28 "Анатолий Кулаков" Это штука, которая позволяет слабовидящим людям считывать с экрана различные надписи или элементы, и позволяет им каким-то образом общаться с UI. +3076.28 3078.80 "Анатолий Кулаков" В общем, это все заулучшили. +3078.80 3096.44 "Анатолий Кулаков" Далее был улучшен UI Automation, то есть это специальный фреймворк, который зашит Windows Forms, который помогает вам делать, например, автоматизированные тесты или с какой-то другой целью управлять UI автоматически, то есть использованием юзера. +3096.44 3101.20 "Анатолий Кулаков" Тоже прекрасная штука, что-то улучшили. +3101.20 3120.28 "Анатолий Кулаков" Далее подобрали более подходящие цвета для того, чтобы сделать как контрастные темы более контрастными, и соответственно для того, чтобы обычные темы сделать тоже немножко более контрастными, чтобы их лучше было разглядеть и удобнее было на них смотреть. +3120.28 3124.36 "Анатолий Кулаков" Улучшили High DPI всякие режимы. +3124.36 3131.72 "Анатолий Кулаков" Например, сделали поддержку High DPI на мультимониторингах более умную. +3131.72 3141.16 "Анатолий Кулаков" Она начала лучше рендериться, начала качественнее увеличивать те контроллы, которые внутри формочки находятся. +3141.16 3162.84 "Анатолий Кулаков" И так как все вот эти изменения довольно рискованные, потому что уже очень много у нас собралось всяких WinForm приложений, уже очень много настроено каких-то автоматизированных средств и всяких тестовых средств под этот фреймворк, в общем команда ввела возможность отключить все эти нововведения с помощью фичи-флагов. +3162.84 3173.60 "Анатолий Кулаков" Мы уже с фичи-флагами часто сталкивались и уже знаем, если вдруг какие-то проблемы возникнут, то всегда вот эти вот настроечки, их можно отменить. +3173.60 3179.84 "Анатолий Кулаков" Более интересное нововведение – это новые датабайдинги. +3179.84 3184.56 "Анатолий Кулаков" WinForm завезли современные датабайдинги. +3184.56 3188.20 "Анатолий Кулаков" То есть раньше в WinForm они и были, но там были довольно убогие. +3188.20 3194.36 "Анатолий Кулаков" В общем назвать это датабайдингами даже язык не поворачивался, это вообще какой-то примитивный способ связывания. +3194.36 3212.92 "Анатолий Кулаков" Сейчас же сюда завезли байдинги полноценные, практически такие, как были в .dpf, такие, как есть в .dpf, то есть с датаконтекстом, с поддержкой команд Pattern, то есть можно там команды делать, можно какие-то объекты в датаконтекст засовывать, их там разбирать с помощью ключей. +3212.92 3217.20 "Анатолий Кулаков" В общем все то, что вы наверняка видели в .dpf. +3217.20 3224.28 "Анатолий Кулаков" И в .dpf это была, наверное остается, это самая мощная штука, которая много релизов двигала .dpf вперед. +3224.28 3227.68 "Анатолий Кулаков" Теперь все это может делать наш старичок в WinForms. +3227.68 3234.88 "Анатолий Кулаков" И нужно это для того, чтобы естественно реализовать полноценный Model-View-Model, MVVM, так называемый, паттерн. +3234.88 3241.20 "Анатолий Кулаков" MVVM – это очень крутецкая штука, она помогает вам очень сильно увеличивать переиспользование кода. +3241.20 3244.48 "Анатолий Кулаков" И самое главное – это тестирование кода. +3244.48 3259.56 "Анатолий Кулаков" Переиспользование кода, чтобы вы оценили, насколько она позволяет переиспользовать кода, что прямо в статье автор отмечает, что если вы перейдете на MVVM, то в принципе вы уже будете никак не ограничены WinForms. +3259.56 3269.32 "Анатолий Кулаков" Если у вас будут View-модели, то вы без проблем сможете пересесть и на .dpf, и на UVP, и на WinUI, и как ни странно на MOYU тоже. +3269.32 3275.16 "Анатолий Кулаков" В общем, может быть это такая стратегия Microsoft по миграции. +3275.16 3282.64 "Анатолий Кулаков" То есть вам уже не нужно просто взять, выбрасывать ваши WinForms, переписывать все с нуля, а вы можете сделать более прозрачную штуку. +3282.64 3300.72 "Анатолий Кулаков" Вы можете существующие WinForms проапгрейдить на новую версию, перевести постепенно все ваше приложение на MVVM, и после того, как вы это сделаете, выбрасывание WinForms и подставление туда MOYU, это будет просто элементарное действие практически. +3300.72 3308.12 "Анатолий Кулаков" Таким образом может быть Microsoft планирует захватить наших старичков, которые до сих пор живут на WinForms и перевести их на новый MOYU. +3308.12 3320.24 "Анатолий Кулаков" Но другой причиной так сильно импровидить дата баннинг, того чего мы не могли дождаться десятилетия, сейчас зачем этим заниматься, другого оправдания я найти не могу. +3320.24 3332.92 "Анатолий Кулаков" Microsoft также отдельно подчеркивает, что никаких планов переводить приносить XAML в WinForms у них нет, то есть с помощью XAML мы все еще не сможем описывать WinForms. +3332.92 3338.24 "Анатолий Кулаков" Это конечно грустно, но надо же до пифа хоть что-то ставить, хоть какую-то фишку. +3338.24 3341.04 "Анатолий Кулаков" Иначе вообще не будет понятно, зачем он нужен. +3341.04 3346.20 "Анатолий Кулаков" Следующий из больших разделов это Comvwrapper и Native IOT. +3346.20 3357.28 "Анатолий Кулаков" С WinForms была большая проблема, к нему не мог прицепиться никак Native IOT и Trimming вместе с ним. +3357.28 3369.24 "Анатолий Кулаков" И в этом релизе команда решила обновить Com-интеропы, которые как раз были главной причиной, заменила их с помощью Comvwrapper. +3369.24 3382.12 "Анатолий Кулаков" Это специальная технология, которая теперь позволяет при определенной реализации всех Com-интерфейсов как надо избавиться от той проблемы, что мы не могли Trimming раньше и применять IOT сценарий. +3382.12 3392.00 "Анатолий Кулаков" Теперь это можно сделать, теперь WinForms можно скомпилировать как Native IOT приложение и запускать как нормальное Native приложение. +3392.00 3410.60 "Анатолий Кулаков" Эта стадия все еще в большом эксперименте, там еще возможны какие-то проблемы, там еще не все размечено, не все Com-интерфейсы переведены, но активная работа в этом направлении ведется и в принципе уже сейчас можно пробовать, если на каких-то ваших приложениях это критично или нужно, то я думаю, что уже можно поэкспериментировать. +3410.60 3417.40 "Анатолий Кулаков" Вот такие глобальные, мне кажется, довольно большие мощные нововведения коснулись WinForms. +3417.40 3419.40 "Анатолий Кулаков" Как, Игорь, тебя впечатлили? +3419.40 3431.96 "Игорь Лабутин" Да, я на самом деле хочу попробовать DataBinding, посмотреть что это такое, потому что может быть это еще больше ускорит то, как я быстренько клепаю приложение, когда мне нужно что-то очень простое и быстрое. +3431.96 3432.96 "Игорь Лабутин" Надо посмотреть. +3432.96 3444.80 "Игорь Лабутин" Я еще хотел сказать, что вот Comvwrapper и Native IOT, то есть ты сказал, что там команда работала, я так понимаю, что это работа в основном комьюнити, по большому счету. +3444.80 3450.60 "Игорь Лабутин" Там, конечно, команда что-то тоже помогала и содействовала, но основная работа была проведена силами комьюнити. +3450.60 3453.88 "Игорь Лабутин" То есть вся эта фишка с Comvwrapper и Native IOT. +3453.88 3455.56 "Анатолий Кулаков" Да, вполне может быть. +3455.56 3458.64 "Анатолий Кулаков" Ну что ж, пойдем дальше по возрастающей. +3458.64 3471.32 "Анатолий Кулаков" После этого открывает DPF, я уже не знал чего ожидать, думал, может наконец-то перенесут его на кроссплатформу, запустят под Linux, завезут в виртуальную реальность, что-нибудь еще с ним сделают. +3471.32 3478.36 "Анатолий Кулаков" Но изменения в DPF оказались намного более скромными и практически сводятся к секции Pro Performance. +3478.36 3492.00 "Анатолий Кулаков" Конечно, там нашли очень много мест, где был ненужный анбоксинг-анбоксинг, перевели на спаны, там манипулирование со строками, там очень много было строк, все это тоже прооптимизировали. +3492.00 3501.00 "Анатолий Кулаков" Улучшили локацию памяти, а точнее избавились от локации памяти, там где она была не нужна, там где она нужна ее максимально сократили. +3501.00 3510.04 "Анатолий Кулаков" В общем, сильно профайлили память, улучшили потребление и использование памяти, соответственно, у нас DPF стал немножко меньше кушать. +3510.04 3524.84 "Анатолий Кулаков" Улучшили рендеринг шрифтов, рендеринг шрифтов, кажется, это какая-то больная родовая травма, его там улучшают каждый релиз и все еще он как-то хреново иногда в некоторых ситуациях рендерится, но будем надеяться, что что-то наконец докрутили. +3524.84 3542.88 "Анатолий Кулаков" И очень сильно почистили код, что тоже сделало возможность некоторые куски прям повыбрасывать, что положительно сказалось на перформансе, и некоторые плацдарм для будущих фич подготовить, потому что теперь код стал более читабельный, более консистентный, более красивый. +3542.88 3545.08 "Анатолий Кулаков" Ну и там в аксессибилити тоже что-то завезли. +3545.08 3554.92 "Анатолий Кулаков" В общем, как мы видим, такие дежурные исправления, какие-то дежурные работы над перформансом, никакого большого изменения, по сути, WPF не получил. +3554.92 3558.56 "Анатолий Кулаков" Так стал немножко красивее, немножко быстрее и немножко +3558.56 3574.04 "Игорь Лабутин" получше. Там есть еще интересная тема, что, насколько я помню, в прошлом релизе он был, собственно, за open-source, то есть выложен его исходники в open-source, и в него можно контрибьютить, но проблема была в том, что не было выложено suite автоматических тестов для WPF. +3574.04 3581.44 "Игорь Лабутин" То есть вы могли что-нибудь закинуть, pull-request какой-нибудь, но проверить локально, что какой-то набор тестов проходит, вы, в общем-то, не могли. +3581.44 3595.04 "Игорь Лабутин" Вот штука, которую сделали в 7-м дотнете, это этот набор тестов тоже пушили на GitHub, ну или открыли его на GitHub, и настроили в основной репе WPF, насколько я понимаю, пайплайны, чтобы эти самые тесты запускались по pull-request. +3595.04 3605.60 "Игорь Лабутин" Все это выглядит, честно говоря, как то, что типа мы сильно WPF развивать не планируем, вот вам, как бы, наконец-таки тесты, теперь давайте несите ваши pull-requests, дорогой комьюнити. +3605.60 3606.80 "Игорь Лабутин" Мучаетесь с этими самыми. +3606.80 3611.16 "Игорь Лабутин" Ну, как бы, вам что-то надо в WPF, видите, правьте, а мы не хотим. +3611.16 3612.80 "Игорь Лабутин" Вот для меня пока это выглядит так. +3612.80 3614.28 "Игорь Лабутин" Не знаю, как на самом деле внутри. +3614.28 3628.12 "Анатолий Кулаков" Ну, это ожидаемо, если они, в принципе, взяли себе направление на развитие MyUI, то тратиться на старые фреймворки, наверное, никакого смысла нет, кроме вот поддержки, улучшения, перформанса, рендеринга и так далее. +3628.12 3631.16 "Анатолий Кулаков" Удивительно, вот почему они за WinForms взялись в этом +3631.16 3641.20 "Игорь Лабутин" контексте. Ну, тут, возможно, команда как-то, то есть, видимо, WinForms всё ещё действительно жив и популярен, и у команды нашлись ресурсы вот такое попробовать. +3641.20 3643.88 "Игорь Лабутин" Видимо, других улучшений особо не нужно было делать. +3643.88 3646.32 "Игорь Лабутин" Вот, попробовали, получилось что-то прикольное, видимо, +3646.32 3655.12 "Анатолий Кулаков" надо пробовать. Да, в интерпрайзе такого не бывает, что у тебя нашлись ресурсы для того, чтобы принести баннинги, которые люди просили там десятилетиями, они раз и сделали. +3655.12 3659.04 "Анатолий Кулаков" Там должна стоять какая-то более теория заговора. +3659.04 3662.56 "Игорь Лабутин" Может быть, мы что-то узнали, либо пришёл какой-нибудь большой кастер и рассказал нам очень надо. +3662.56 3664.12 "Анатолий Кулаков" Ну да, может быть. +3664.12 3665.12 "Анатолий Кулаков" Ладно, пойдём дальше. +3665.12 3677.36 "Анатолий Кулаков" Вот, как я уже упоминал, всё у Microsoft нацелено на Moyu и вот открывая релиз ноутса Moyu, тут, конечно же, должна была быть огромная-огромная простыня всяких нововведений, но, опять же, нет, нифига. +3677.36 3681.32 "Анатолий Кулаков" Единственное, что впечатляет у Moyu в том, что это General Availability. +3681.32 3683.24 "Анатолий Кулаков" В принципе, и это всё. +3683.24 3690.56 "Игорь Лабутин" Ну, подожди, но он же был полгода назад объявлен, что он уже General Availability, нет? +3690.56 3693.52 "Игорь Лабутин" Или он там был просто, типа, релиз? +3693.52 3705.80 "Анатолий Кулаков" Да, да, там его каким-то просто релизом обозвали, теперь сказали, что нам вот ещё немножко таймфрейм, пока мы подмачимся под наш новый DotNet 7, вот теперь они подмачиваются, теперь они смело кричат, что они наконец-то General Availability. +3705.80 3710.00 "Анатолий Кулаков" В общем, не очень понятно статус, но вроде как зарелизилось. +3710.00 3712.96 "Анатолий Кулаков" Ну, зарелизилось, можно пользоваться, хорошо. +3712.96 3713.96 "Анатолий Кулаков" Типа того. +3713.96 3721.92 "Анатолий Кулаков" Из мелочей улучшен Map Control, теперь, даже не улучшен, а добавлен, потому что раньше его вообще не было. +3721.92 3736.20 "Анатолий Кулаков" Теперь вместе с DotMail.io поставляется Map Control, как всегда, это какой-то обновленный компонент от Xamarin.Forms, то есть это кроссплатформенная абстракция, которая нативно на конкретной операционной системе будет подцеплять нативный контроль. +3736.20 3743.52 "Анатолий Кулаков" И там уже у вас будет и геокодирование, и позиционирование, и локации, и всё в этом духе. +3743.52 3764.40 "Анатолий Кулаков" Улучшения для десктопа сводятся к банальным, типа, улучшили API для изменения размеров окна и его позиционирования, улучшили контекстное меню, тулт-типы, различные подсказки над контроллами, улучшили обработку правого клика. +3764.40 3769.68 "Анатолий Кулаков" Ну, в общем, такие тоже какие-то мелочи, которые больше похожи на отмазки, чем на нормальный фичик релиза. +3769.68 3773.00 "Игорь Лабутин" Тут надо сказать, что слово "улучшили" неправильно. +3773.00 3794.60 "Игорь Лабутин" А если я правильно помню статью, смысл в том, что эти штуки добавили, MAUI настолько сильно концентрировался на всяких мобильных приложениях, ну а собственно с него, я так понимаю, всё начиналось, чтобы эта нативная кроплоформер работала на Android и iOS, что когда выяснилось, что вообще-то он должен работать в том числе на десктопе, оказалось, что, например, невозможно обработать right-click мыши. +3794.60 3796.76 "Игорь Лабутин" Ну нет, в телефоне right-кликов мыши. +3796.76 3798.84 "Игорь Лабутин" И поэтому такого API просто не было. +3798.84 3811.88 "Игорь Лабутин" И вот, поскольку к релизу нужно всё-таки, мы же релизим в том числе для десктопа, пришлось добавлять вот все эти API, про контекстные менюшки, про tooltip и вот всё то, что нужно на десктопе, чтобы с этим можно было в принципе работать. +3811.88 3822.84 "Анатолий Кулаков" Ну, в целом про историю ты прав, единственное, что я не знаю, я не видел, добавили, я увидел везде там "улучшили", "заимпрувили" и "заинхэчмили" и всё в этом духе. +3822.84 3823.84 "Игорь Лабутин" Ну может быть. +3823.84 3827.40 "Игорь Лабутин" Ну не важно, но скорее всего, если оно работало фигово, можно считать, что его не было. +3827.40 3832.40 "Игорь Лабутин" Скорее всего, его действительно сильно не тестировали, потому что ну где ж ты там на телефоне будешь менять размер окна. +3832.40 3835.28 "Игорь Лабутин" Оно у тебя всегда одно и на весь экран. +3835.28 3836.28 "Анатолий Кулаков" Да, да, может это. +3836.28 3850.56 "Анатолий Кулаков" Ну смотри, вот глядя на вот эти три фреймворка, вот три анонса, которые мы сегодня с вами разобрали, у меня сложилось полное впечатление, что самый главный наш передовой UI фреймворк это WinForms, потому что во всех остальных это какие-то нелепые оправдания, а не анонсы. +3850.56 3853.16 "Игорь Лабутин" Ну, может тайной, не знаю. +3853.16 3860.12 "Игорь Лабутин" У Microsoft есть три команды, которые соревнуются, и вот WinForms это, вырывается вперёд, там долго сидели в засаде. +3860.12 3867.04 "Анатолий Кулаков" Ну может быть, для нас, как для обычных разработчиков это вносит ещё больше путаницы, не более, не менее. +3867.04 3868.52 "Анатолий Кулаков" А потом придёт Аполлония и всех победит. +3868.52 3878.24 "Анатолий Кулаков" Да, скорее бы уже, может Microsoft наконец-то бы её купил там или задоптил, или ещё что-то с ней сделал, и наконец-то у нас был бы нормальный какой-то фреймворк, вместо десятка ненормальных. +3878.24 3883.00 "Анатолий Кулаков" Ладно, хватит фантазировать и пойдём дальше, что у нас там есть. +3883.00 3884.68 "Анатолий Кулаков" Машинное обучение, кажется, ещё рассказывали интересное. +3884.68 3885.68 "Игорь Лабутин" Ох, машинное обучение. +3885.68 3898.08 "Игорь Лабутин" Машинное обучение действительно рассказывали, я, честно говоря, не знаю, кто занимается машинным обучением прямо на дотнете, именно прямо не использованием сеточек, а созданием нейросеток, да, там типа вот это всё. +3898.08 3899.08 "Игорь Лабутин" Таксошников же. +3899.08 3908.96 "Игорь Лабутин" Нет, подожди, он занимается, конечно, в демо-примерах, но я не слышал ни разу, что этим занимались прямо в промышленном смысле. +3908.96 3911.44 "Игорь Лабутин" Но, может, действительно такие люди есть. +3911.44 3935.00 "Игорь Лабутин" Ну короче, есть ML.net, если кто не знает, это такая умотнученная штука, точнее это framework, кроссплатформенный для машин-лёрнинга, для дотнет-разработчиков, который, соответственно, позволяет вам вписать в ваше дотнет-приложение любые, в общем-то, какие-то модели, да, ML-ные, для их использования. +3935.00 3941.04 "Игорь Лабутин" Для этого есть ещё Extend, для Visual Studio 2022 есть Extension Model Builder, который позволяет, собственно, создавать эти штуки. +3941.04 3952.40 "Игорь Лабутин" И в этом релизе в 2.0 завезли новые API для работы с текстами, то есть теперь там есть classification поиск, по подобию, то, что они называют similarity API. +3952.40 3958.16 "Игорь Лабутин" И есть улучшение в штуке, которая называется AutoML, automated machine learning. +3958.16 3969.80 "Игорь Лабутин" Теперь вы можете автоматически перепроцессить нужные данные, как-то автоматически тренить всякие классификаторы, мультикласс классификаторы, регрессионные модели. +3969.80 3981.72 "Игорь Лабутин" Ну вот, кастомизировать гиперпараметры, это я сейчас вот прям статью читаю, тюнить алгоритмы для поиска оптимальных гиперпараметров, ты знаешь? +3981.72 3982.72 "Игорь Лабутин" Нет, к сожалению, не приходилось делать. +3982.72 3985.72 "Игорь Лабутин" И после того, как вы всё это закастомизируете, заоптимизируете, затюните, можно всё это заперсистить и, видимо, потом впихнуть в ваше дотнет-приложение, и оно будет оптимально работать. +3985.72 4009.36 "Игорь Лабутин" То есть, грубо говоря, вы действительно, видимо, можете на основе каких-то входных данных, например, включить какие-то модели, например, в какой-то модели, и из дотнет-приложения заиспользовать. +4009.36 4025.12 "Игорь Лабутин" Я не знаю практических применений этого, я не слышал, но я не интересуюсь особо этой областью, поэтому, если вы вдруг работаете на ML-дотнете и что-то про это знаете, на самом деле, напишите нам, мы вас позовём и с вами это обсудим, нам это тоже интересно. +4025.12 4035.96 "Игорь Лабутин" А если вы этим интересовались и вам интересно, вдруг что-то новенькое есть, ну загляните в ML-дотнет 2.0, может быть, вы там найдёте что-то интересное для вас. +4035.96 4040.40 "Игорь Лабутин" Наверное, вот это всё, что я могу рассказать про ML-дотнет, учитывая, что я им не занимаюсь. +4040.40 4041.40 "Анатолий Кулаков" Ну, отлично. +4041.40 4046.44 "Анатолий Кулаков" Я думаю, что если кто-то действительно занимается, приходите, пообсудим и поговорим. +4046.44 4055.12 "Анатолий Кулаков" Я тоже не знаю ни одного живого человека, который на практике с этим сталкивался, поэтому даже представления не имею, как оно там всё живёт. +4055.12 4057.24 "Анатолий Кулаков" Но, судя по анонсам, развиваются довольно бодренько. +4057.24 4063.80 "Анатолий Кулаков" То есть, я бы сказал, что там какие-то громкие названия, громкие пункты и громкие импрувменты, они всё время встречаются. +4063.80 4070.00 "Анатолий Кулаков" Не сказать бы, что оно мертво, наверное, где-то в какой-то индустрии, в какой-то стране кто-то этим пользуется. +4070.00 4074.64 "Игорь Лабутин" Давай про следующую технологию, которую тоже очень активно все пользуются, в кавычках. +4074.64 4078.72 "Анатолий Кулаков" Да ничего не в кавычках, нормальная технология, чего ты наезжаешь. +4078.72 4081.76 "Анатолий Кулаков" Речь у нас сейчас пойдёт про Microsoft Orleans. +4081.76 4093.68 "Анатолий Кулаков" Это, для тех, кто не знает, Microsoft Orleans – это кроссплатформенный фреймворк для того, чтобы создавать различные сложные, масштабируемые, распределённые приложения. +4093.68 4095.52 "Анатолий Кулаков" Звучит нормально, да? +4095.52 4097.20 "Анатолий Кулаков" Возможно, многое насобирали. +4097.20 4100.88 "Анатолий Кулаков" На самом деле, довольно популярная штука, довольно уже устоявшаяся. +4100.88 4108.00 "Анатолий Кулаков" То есть, это не какой-то там молодняк, а это уже хорошо тестированное на больших продакшн-системах, в том числе внутри самого Microsoft. +4108.00 4112.00 "Анатолий Кулаков" И много микрософтовских игр его используют, и Microsoft Bing его используют. +4112.00 4124.20 "Анатолий Кулаков" Фреймворк построен на так называемой концепции акторов, на модели акторов, но у него есть свой собственный подход, своё собственное видение на модель, так называемые виртуальные акторы. +4124.20 4129.24 "Анатолий Кулаков" В общем, если кто-то знаком с ACO.NET, то это, наверное, самое близкое, что можно представить. +4129.24 4134.40 "Анатолий Кулаков" То есть, ACO.NET – это примерно примерный конкурент Orleans. +4134.40 4140.04 "Анатолий Кулаков" У них есть общие концепции, у них есть концепции, которые расходятся. +4140.04 4142.88 "Анатолий Кулаков" В общем, примерно это про одно и то же. +4142.88 4147.32 "Анатолий Кулаков" Хороший фреймворк, как я уже сказал, интересный. +4147.32 4149.76 "Анатолий Кулаков" Microsoft решила сделать следующий фильм душами. +4149.76 4153.40 "Анатолий Кулаков" Она решила объединить команды Microsoft Orleans и ISP.NET Core. +4153.40 4156.48 "Анатолий Кулаков" Ну и там даже не ISP.NET, а прямо самого .NET. +4156.48 4163.56 "Анатолий Кулаков" В общем, там команда Orleans рассыпалась и по .NET, и по ISP.NET, или, может быть, это неправильно назвать, влилась. +4163.56 4167.16 "Анатолий Кулаков" В общем, теперь они стали взаимодействовать намного ближе. +4167.16 4182.08 "Анатолий Кулаков" И в результате этого взаимодействия появился новый релиз Microsoft Orleans 7.0, который прежде всего рассказывает нам про огромное число импрувментов, которые произошли в результате вот этого корпоративного слияния. +4182.08 4184.72 "Анатолий Кулаков" Что же у нас там за импрувменты? +4184.72 4185.72 "Анатолий Кулаков" Давайте посмотрим. +4185.72 4192.48 "Анатолий Кулаков" Во-первых, нужно отметить, что в самом Orleans, прямо в его репозитории на GitHub есть огромное число клевых тестов. +4192.48 4200.24 "Анатолий Кулаков" Прекрасны они тем, что тестируют очень различные сценарии, там сило-то сило, клиент-то сило. +4200.24 4210.60 "Анатолий Кулаков" И у них есть различные симуляции различных инвайорментов на лэптопе, на десктопе, на виртуальных машинах, на различных серверах с различной масштабированностью, с различным количеством клиентов. +4210.60 4223.04 "Анатолий Кулаков" В общем, все вот эти разнообразные сценарии и разнообразные взаимодействия, разнообразные инвайорменты, они очень плотно покрыты тестами и это прекрасно. +4223.04 4238.24 "Анатолий Кулаков" Так вот, в результате того, что Orleans что-то там поимпрувили, заулучшили, у них по некоторым тестам производительность увеличилась от 40% до 170%. +4238.24 4249.08 "Анатолий Кулаков" Такие хорошие, довольно качественные цифры, особенно с учетом того, что никаких глубоких примеров большого рефакторинга и чего-то такого они не приводят. +4249.08 4255.82 "Анатолий Кулаков" То есть кажется, что это просто взаимодействие, плотное взаимодействие действительно с Untamed и прочими командами. +4255.82 4266.96 "Анатолий Кулаков" И соответственно в результате Microsoft Orleans 7 может через себя пропускать 4,5 миллиона сообщений в секунду, что довольно-таки приличные цифры. +4266.96 4268.68 "Анатолий Кулаков" 4,5 миллиона – это прямо хорошо. +4268.68 4275.40 "Анатолий Кулаков" Вот в принципе вот такими вот примерными понятиями оперируют данные фреймворки. +4275.40 4290.04 "Анатолий Кулаков" Еще из-за того, что они стали взаимодействовать больше с людьми, с нормальными людьми, с нормальными потребителями, у них немножко изменился подход к тому, как они распространяют Nuget пакеты и в общем как организуют свой API. +4290.04 4300.20 "Анатолий Кулаков" Например, в третьем Orleans для того, чтобы вам сделать какую-то кастомную штуку, вам нужно было подключить пакет, называющийся Orleans Code Generator MS Build. +4300.20 4306.76 "Анатолий Кулаков" В общем, это довольно неочевидная вещь, которую в памяти держать сложно, но она вам нужна для практической генерации там силосовых клиентов. +4306.76 4318.00 "Анатолий Кулаков" В новом 7 Orleans все это упростили, теперь вам достаточно подключить к вашему проекту просто MicrosoftOrleans.client пакет и вы получите клиента. +4318.00 4322.60 "Анатолий Кулаков" Если вы подключите MicrosoftOrleans.server, не поверите, но вы получите сервер. +4322.60 4327.92 "Анатолий Кулаков" И все это довольно стало таким человеческим языком, с человеческим лицом, теперь заработало. +4327.92 4345.04 "Анатолий Кулаков" Вот в принципе все такие нововведения, которые стоит упомянуть для того, чтобы рассказать, что Orleans тоже примкнул к релизам .NET, к команде .NET, и теперь, скорее всего, будет как-то рядышком вместе с ним развиваться и тоже как-то улучшать свою общую инфраструктуру. +4345.04 4347.96 "Игорь Лабутин" Ну, неплохо. +4347.96 4360.52 "Игорь Лабутин" Наверное, это не тот фреймворк, который там прям широко распространен с точки зрения там среднего проекта, наверное, его не используют, но есть наверняка те, кому он нужен и интересен. +4360.52 4368.08 "Игорь Лабутин" И если вы уже его вдруг используете, то как раз обновиться на 7, кажется, однозначно нужно, получите бесплатный буст в перформансе. +4368.08 4375.24 "Игорь Лабутин" Давай пойдем дальше, мы много чего проговорили про всякие нововведения во фреймворках, теперь пора поговорить про тулы. +4375.24 4378.32 "Игорь Лабутин" А как же всем этим пользоваться? +4378.32 4389.36 "Игорь Лабутин" Понятное дело, что у нас есть SDK, который можно скачать и поставить, и вам ничего не нужно будет больше делать, но код где-то редактировать надо, и для этого у нас есть и DE. +4389.36 4399.60 "Игорь Лабутин" Для начала это Visual Studio 2022.17.4, официальная студия от Microsoft, последний стейбл-релиз, он поддерживает как раз .NET 7. +4399.60 4410.24 "Игорь Лабутин" Там есть много всяких разных улучшений помимо, собственно, самой поддержки .NET 7, мы про них рассказывали раньше, я на них не буду сильно прям останавливаться, хотя быстренько пробежимся. +4410.24 4422.76 "Игорь Лабутин" Мы говорили про то, что у нас теперь в студии появились звуки, то есть всякие штуки, которые срабатывают, когда происходят деленные события в студии, там когда у вас breakpoint сработал, или когда вы в поиске что-то сделали, или когда у вас билд закончился. +4422.76 4424.24 "Игорь Лабутин" Можно теперь настроить разные звуки. +4424.24 4425.24 "Игорь Лабутин" Датабейс визуал... +4425.24 4426.24 "Игорь Лабутин" Датабейс, дататейбл визуалайзер. +4426.24 4433.96 "Игорь Лабутин" Если у вас есть айнумерабл, либо что-то подобное, вы теперь в дебайгере можете посмотреть содержимое в красивом табличном виде. +4433.96 4439.52 "Игорь Лабутин" Ну и если у вас есть эксепшн, то у него появляется окошко, там теперь можно нормально посмотреть call stack. +4439.52 4440.52 "Игорь Лабутин" Прям удобно. +4440.52 4449.28 "Игорь Лабутин" Это те штуки, которые мы рассказывали до этого, там понятно, что перформанс улучшился, всячески разные тесты быстрее запускаются, вот это все. +4449.28 4458.56 "Игорь Лабутин" Помимо этого в последний, так сказать, вагон релиза успела запрыгнуть новая фича, которой не было в превьюшках, про которую мы не говорили, называется multi-repo-support, ну multi-repository-support. +4458.56 4465.36 "Игорь Лабутин" Эта штука позволяет вам иметь до 10 активных гид-репозиториев одновременно. +4466.24 4473.04 "Игорь Лабутин" То есть у вас, Microsoft говорит, например, если у вас есть солюшен, в котором есть больше, чем один репозиторий. +4473.04 4480.60 "Игорь Лабутин" Мне сложно представить, как у меня так есть солюшен, который распилен на много репозиторий, но наверное у Microsoft есть или у каких-то кастеров есть. +4480.60 4485.20 "Анатолий Кулаков" То есть у тебя как репозиторий будут внутри репозиторий или рядом с репозиториями? +4485.20 4487.04 "Анатолий Кулаков" Как это вообще технически это организовать? +4487.04 4500.40 "Игорь Лабутин" Ну у меня есть репозиторий, в котором лежит солюшен, который нужно склонировать, рядом склонировать репозиторий, допустим, с какими-то другими частями, а из солюшена, через какие-нибудь, знаешь, относительные пути, у меня будут ссылочки на CS Project. +4500.40 4504.56 "Анатолий Кулаков" Да, но тогда у тебя получается, что структура не очень стандартная, да? +4504.56 4508.76 "Анатолий Кулаков" Не когда у тебя солюшен лежит на верхнем уровне, а под низом там всякие папочки с проектами. +4508.76 4521.36 "Игорь Лабутин" И я согласен, поэтому фича выглядит немножко странной для солюшена, но написано, что можно это делать не только на солюшенах, но и просто открыть несколько гид-репозиторий из фолдера. +4521.36 4528.72 "Игорь Лабутин" Они приводят пример, что, ну например, вы работаете над каким-нибудь веб-проектом, и у вас часто там frontend и backend лежат в разных репозиториях. +4528.72 4532.04 "Игорь Лабутин" Но обычно это разные солюшены. +4532.04 4535.20 "Игорь Лабутин" Ну frontend это иногда вообще не солюшен. +4535.20 4536.20 "Игорь Лабутин" Давай начнем с этого. +4536.20 4540.80 "Анатолий Кулаков" Ну в терминах нормальных людей, конечно же, это не солюшен, но скорее всего у них там есть какой-нибудь файл проекта. +4540.80 4555.72 "Игорь Лабутин" Ну вот, короче, по мнению Microsoft, теперь вы можете открыть одновременно и там, и там, и смысл фичи заключается в том, что когда вы будете говорить create branch, он будет создаваться одновременно во всех гид-репозиториях, когда вы будете говорить push, он будет вас спрашивать там в каком порядке запушить и пушить во все репозитории. +4555.72 4559.80 "Игорь Лабутин" Когда вы будете переключать branch, он будет переключаться во всех репозиториях одновременно. +4559.80 4569.52 "Игорь Лабутин" Что-то в этом есть, то есть мне иногда полезна фича, когда на нескольких гид-репозиториях нужно одновременно переключиться на мой какой-нибудь branch, на котором я работаю. +4569.52 4574.36 "Игорь Лабутин" Но как это будет работать в реальной жизни, пока непонятно. +4574.36 4579.60 "Анатолий Кулаков" Ну да, с несколькими репозиториями это как-то выглядит довольно пока непонятно. +4579.60 4590.64 "Игорь Лабутин" Ну то есть у нас был кейс, у нас был проект, как-то действительно, ну там по сути получалось, что у тебя несколько сервисов живут, каждый в своем solution и каждый в своем репозитории. +4590.64 4598.12 "Игорь Лабутин" Плюс еще библиотечка какая-то была, которая тоже живет, ну типа Nuget свой, он тоже с отдельной solution, но в отдельном репозитории. +4598.12 4604.08 "Игорь Лабутин" Была необходимость работать с ними со всеми одновременно, создав везде один и тот же branch. +4604.08 4608.28 "Анатолий Кулаков" Не, ну это окей, но скорее всего для этого используются обычно сабмодули. +4608.28 4610.12 "Анатолий Кулаков" Нет, зачем сабмодули, почему? +4610.12 4615.76 "Игорь Лабутин" Я Nuget же solution собираю, он пабличится в Nuget, какой мне сабмодуль, зачем мне сабмодуль для Nuget? +4615.76 4620.48 "Анатолий Кулаков" Нет, здесь же проблема не в Nuget solution, а именно в его физическом расположении. +4620.48 4630.96 "Анатолий Кулаков" Nuget или не Nuget, это не важно, что ты соберешь, главное как ты его расположишь у себя на диске, то есть каким образом ты на диске себе сделаешь 10 репозиторий рядом и на них натравишь один solution. +4630.96 4639.00 "Игорь Лабутин" Вот у меня это были разные solution, это было 3 разных solution в 3 разных репозиториях, но мне хотелось с ними работать как бы одновременно, везде создавать один и тот же +4639.00 4641.00 "Анатолий Кулаков" branch. Ну это окей, но кажется, что это не твой кейс. +4641.00 4642.00 "Анатолий Кулаков" Вот непонятно. +4642.00 4645.92 "Анатолий Кулаков" Они так смотрят, что у тебя обязан быть один solution, иначе студия его не откроет, она не поймет, что открывать. +4645.92 4651.08 "Игорь Лабутин" Я согласен, непонятно пока, как это работает и как это будет выглядеть, но я не пробовал ещё. +4651.08 4659.92 "Игорь Лабутин" У меня стоит, кстати, по-моему, 17.4 по идее, я обновлялся сразу после релиза, так что теоретически у меня это есть, можно проверить, надо будет попробовать, может быть проверю, расскажу. +4659.92 4664.72 "Анатолий Кулаков" Ну проверить ты можешь, что оно работает, просто непонятно, как это применять на практике. +4664.72 4670.76 "Игорь Лабутин" Ну вот, может быть мы последим, если появятся статьи про то, что вау, как это круто, мы не знали. +4670.76 4674.20 "Игорь Лабутин" Или если такую штуку завезут в райдер, потому что в райдере по-моему такого нету. +4674.20 4676.60 "Игорь Лабутин" Значит, эта штука действительно полезная. +4676.60 4684.36 "Игорь Лабутин" Так, параллельно с 17.4 релизом, естественно, зарелизился 17.5, превью 1. +4684.36 4686.80 "Игорь Лабутин" Там появились интересные штуки. +4686.80 4692.04 "Игорь Лабутин" Это понятно, что это превью 1, там ничего супер крутого обычно не завозят, но тем не менее. +4692.04 4699.04 "Игорь Лабутин" У нас теперь можно расцвечивать табы через RegEx, вы можете взять RegEx для матчинга соответствующих цветов. +4699.04 4703.12 "Игорь Лабутин" Я не знаю, опять же, зачем, но нужно, видимо, кому-то. +4703.12 4705.24 "Игорь Лабутин" Markdown поддержку улучшили. +4705.24 4724.88 "Игорь Лабутин" Если вам надоело, что при запуске вашего ASP.NET-приложения у вас открывается консолька, отдельная, в которой output пишется, то начиная с Visual Studio 17.5 превью 1 этот output будет перехватываться и писаться в терминалке, что-то внутри, в Tool Window в студии, без отдельной консольки. +4724.88 4730.24 "Анатолий Кулаков" Блин, это самая большая фишка, которая меня бесит в райдере, и вот и они тут даже. +4730.24 4731.24 "Анатолий Кулаков" Ну что это такое? +4731.24 4732.24 "Игорь Лабутин" Возможно, это отключаемо, посмотрим. +4732.24 4733.24 "Игорь Лабутин" Ну, будем надеяться. +4733.24 4737.56 "Игорь Лабутин" Когда доберемся, я надеюсь, у нас будет какая-нибудь отдельная статья про превью 1, где мы подробно это рассмотрим. +4737.56 4746.04 "Игорь Лабутин" И еще в дебагере, я вот не знаю, эта фича появилась уже в 17.4, в дебагере есть такая штука под названием Managed Memory. +4746.04 4751.56 "Игорь Лабутин" Не, ну по идее она была и раньше, наверное, всегда можно было посмотреть memory по определенному адресу. +4751.56 4766.80 "Игорь Лабутин" Но здесь это именно фишка под названием Managed Memory, в которой есть Duplicate String Visualizer, то есть теперь есть таблочка, в которой можно посмотреть все аллоцированные за время приложения работы строки, со статистикой, какие строки, в каком количестве были зааллоцированы, и есть ли там повторение. +4766.80 4771.44 "Игорь Лабутин" То есть прямо вот конкретно про Duplicate String. +4771.44 4782.60 "Игорь Лабутин" Скорее всего они будут, видимо, эту штуку развивать дальше, и там полноценной dot memory, наверное, не получится, но может быть что-то близкое потихонечку начнет вырисовываться. +4782.60 4785.96 "Игорь Лабутин" Надо сказать, что про студию, наверное, это все. +4785.96 4793.32 "Игорь Лабутин" В райдере, соответственно, используйте YAPK, и только YAPK полноценно поддерживает седьмой .NET. +4793.32 4801.00 "Игорь Лабутин" Надо сказать, что за время, собственно, подкаста с момента прошлого релиза на шестого .NET мы все время про студию говорили в трех ключах. +4801.00 4808.52 "Игорь Лабутин" У нас была просто студия, у нас была студия для Mac'а, и у нас была студия для ARM64. +4808.52 4814.76 "Игорь Лабутин" Сейчас студия для ARM64 это уже, собственно, никакая не отдельная студия, это просто студия. +4814.76 4820.16 "Игорь Лабутин" Она есть, она вышла тоже в том числе, то есть версия 17.4 доступна для ARM. +4820.16 4826.36 "Игорь Лабутин" Там есть не все workloads, которые вы, может быть, хотели бы там видеть. +4826.36 4831.28 "Игорь Лабутин" Там есть поддержка .NET, Desktop Development, причем как .NET и так плюсов. +4831.28 4840.52 "Игорь Лабутин" Там есть ASP.NET, понятное дело, Web Development, UVP, экстенджеры можно девелопить, игрушки можно девелопить на C++ и на Node.js можно девелопить. +4840.52 4844.48 "Игорь Лабутин" Вот это только те workloads, которые поддержаны на студии на ARM64. +4844.48 4853.24 "Игорь Лабутин" Собирать при этом их можно, используя седьмой или шестой .NET и .NET Framework 481, которые, как мы помним, обновились для поддержки ARM64. +4853.24 4860.68 "Игорь Лабутин" MAUI не поддержана, так что если вы планируете работать с MAUI, то пока не используйте ARM64 в Visual Studio. +4860.68 4863.28 "Игорь Лабутин" В общем, это все, что можно сказать про ARM64. +4863.28 4871.64 "Игорь Лабутин" Я не думаю, что какие-то будут отдельные дальше у нас упоминания конкретно про ARM64, кроме если каких-то отдельных кейсов. +4871.64 4874.92 "Игорь Лабутин" Что же там такое интересное завезли про Mac? +4874.92 4878.28 "Игорь Лабутин" Кстати, тишина и ничего не сказали в момент релиза. +4878.28 4884.68 "Игорь Лабутин" Я, по крайней мере, не видел нигде в анонсах никаких упоминаний про Visual Studio for Mac. +4884.68 4896.64 "Игорь Лабутин" Зато в версии 17.4 появилась фича под названием Visual Studio for Mac Rollback, которая позволяет откатить Visual Studio к предыдущему состоянию. +4896.64 4904.04 "Игорь Лабутин" Но единственное, что она позволяет сделать, это откатить версию к предыдущей заинсталированной версии, которая у вас была до этого. +4904.04 4906.92 "Игорь Лабутин" Дальше там есть тонкости с тем, что останется, что будет удалено. +4906.92 4917.68 "Игорь Лабутин" Если у вас были всякие там темы, фонты, клавиатурные сокращения, которые вы настроили, или положение окон, это все будет сохранено. +4917.68 4932.48 "Игорь Лабутин" Если у вас были какие-то профайлы специальные или юзер-сеттинги, которые не входят в набор синхронизируемых сеттингов, я не знаю, как это сходу понять, входит или не входит, то такие штуки будут заресторены в дефолт. +4932.48 4946.76 "Игорь Лабутин" И при этом, если вы делаете роллбэк на прошлую версию, то всяческие компоненты, которые входят в Visual Studio, там всякие SDK, вот это все, все, что оунится в самой Visual Studio, они будут зароллбэтчены. +4946.76 4959.68 "Игорь Лабутин" Если же какие-то есть системные компоненты, ну как пример это Ease, который в студии может быть поставлен, но Ease это такая системная компонента, которой может быть только одна и соответственно ее роллбэтчить не будут. +4959.68 4967.80 "Игорь Лабутин" Экстенджены могут быть тоже заанинсталлены, которые юзер инсталлил, и нельзя откатываться совсем уж назад. +4967.80 4977.70 "Игорь Лабутин" То есть для версии 17.4 вы можете откатиться максимум на 17.0.10 или 17.1.7, а для превью ченнелы только на 17.2 превью один. +4977.70 4981.24 "Игорь Лабутин" Зароллбэтчиться можно через UI или через command line. +4981.24 4989.20 "Игорь Лабутин" Дальше, в общем звучит в принципе норм, хотя есть несколько интересных моментов. +4989.20 4999.96 "Игорь Лабутин" В обсуждении этой статьи, ну в комментах к этой статье про анонс, там написано типа "Ооо, кажется студию 17.4 ставить нельзя, если они вписали туда такую фичу, значит они не уверены в качестве студии". +4999.96 5005.20 "Игорь Лабутин" Вот, типа надо ждать превьюшек, ну не превьюшек, а типа сервиспака в дальнейших. +5005.20 5014.36 "Игорь Лабутин" Второй момент, что, представьте, у вас стояло там не знаю 17, кто у нас там был в прошлом, ну 3 видимо, или там 17.2. +5014.36 5017.00 "Игорь Лабутин" Вы поставили 17.4, попробовать. +5017.00 5019.44 "Игорь Лабутин" Ну релиз, там все дела, дот над 7 хочется. +5019.44 5022.40 "Игорь Лабутин" Там например что-то не работает. +5022.40 5032.80 "Игорь Лабутин" Вы подумали, интересно, а не исправлено ли это в последнем каком-нибудь хотфиксе, и ну вот пока вы там пробовали и ждали, вышел хотфикс какой-нибудь, да, 17.4.1. +5032.80 5038.48 "Игорь Лабутин" Вы поставили 17.4.1, выяснили, что ваш баг не пофикшен, который вам там мешает в содалей поведении. +5038.48 5040.12 "Игорь Лабутин" Вы хотите сделать роллбэк? +5040.12 5042.56 "Игорь Лабутин" Куда вы сможете сделать роллбэк? +5042.56 5046.08 "Анатолий Кулаков" Ну зависит от того, сколько версий там она хранит и как она их хранит. +5046.08 5052.92 "Игорь Лабутин" Хранит она ровно одну, поэтому вы сможете сделать откат только на 17.4, хотя хотелось бы на 17.2. +5052.92 5055.00 "Игорь Лабутин" Понятное дело, на ту, которая была стабильная. +5055.00 5066.52 "Игорь Лабутин" На самом деле там тоже был вопрос, хранит ли она что-то, она не хранит, она хранит только мета-данные, то есть непосредственно бинарников ничего не хранится, она их заново из интернета скачает и как бы поставит. +5066.52 5069.68 "Игорь Лабутин" Просто она это сделает с восстановлением каких-то сеттингов. +5069.68 5070.68 "Игорь Лабутин" Ну смысл в том… +5070.68 5074.96 "Анатолий Кулаков" Не, ну твои-то шоткаты и вот эти положения окон, как ты говорила, они уже все, наверняка должны +5074.96 5080.92 "Игорь Лабутин" охранить локально. Не-не-не, это-то понятно, она хранит, ну в смысле, что она это возьмет из вот текущей студии. +5080.92 5090.60 "Игорь Лабутин" Не в смысле, что она… если вы поставили, не знаю, использовали 17.2, там настроили окна, поставили 17.4, перенастроили окна, откатились на 17.2, настройки окон останутся новыми от 17.4. +5090.60 5094.80 "Анатолий Кулаков" А, я как раз думал, что она в том числе сохраняет и старые настройки окон. +5094.80 5100.76 "Игорь Лабутин" Не-не-не, она именно в смысле, что она чисто обновит, ну бинарники, но постарается сохранить настройки. +5100.76 5113.52 "Игорь Лабутин" То есть, грубо говоря, ну как, я не знаю, винда с апдейтами, то есть ты типа от того, что ты перенастроил чуть-чуть винду, постольку накатились апдейты, если ты снесешь апдейт, если этот апдейт не касался конкретной настройки, ну ничего не поменяется, настройки-то сохранятся. +5113.52 5120.80 "Анатолий Кулаков" Слушай, а какая разница, если я вот снесу 17.4 и поставлю, ну, себе дезербитива, поставлю ручками 17.2, 17.3, какая разница? +5120.80 5124.32 "Игорь Лабутин" Там, я так понимаю, что скорее всего с настройками будет, не все так хорошо. +5124.32 5128.40 "Игорь Лабутин" Хотя, если они синхронизируются и через какую-нибудь облако синхронизируются, то должно быть пофигу. +5128.40 5129.40 "Игорь Лабутин" Не знаю. +5129.40 5130.40 "Игорь Лабутин" Типа да. +5130.40 5146.16 "Игорь Лабутин" Ну вот народ написал в таких комментах, что ну блин, если вот в том сценарии, что я перечислил, да, попробовали поставить hotfix, не помогло, хочу теперь откатиться, а откатиться я теперь не могу, потому что я поставил hotfix, я могу откатиться только на основную версию, а на предыдущую безбажную не могу, кажется, проще снести и поставить. +5146.16 5152.56 "Игорь Лабутин" В общем, странная фича, непонятно зачем сделана, непонятно зачем именно в таком виде сделана. +5152.56 5160.36 "Игорь Лабутин" С другой стороны, ну то есть, тот же, допустим, тулбокс от JetBrains, он тоже позволяет делать rollback, но там можно настроить сколько старых версий ты хранишь. +5160.36 5164.12 "Игорь Лабутин" Одну, две, три, пять, я не помню, есть ли там лимит, ну понятно. +5164.12 5171.84 "Игорь Лабутин" Но там все понятно, там они каждый ставят свою папочку, ну вот он просто переключит вас на старую папочку и все будет работать. +5171.84 5175.64 "Анатолий Кулаков" Ну, может быть, эту штуку тоже допилят, будет тебе 10 версий хранить. +5175.64 5180.28 "Анатолий Кулаков" Теперь мы чистим свой диск, не только от JetBrains будем чистить, а будем чистить свой диск еще от Visual Studio. +5180.28 5181.28 "Игорь Лабутин" А почему нет? +5181.28 5182.28 "Игорь Лабутин" Вот. +5182.28 5183.28 "Игорь Лабутин" Действительно. +5183.28 5187.56 "Игорь Лабутин" Это Visual Studio, давай теперь поговорим про NuGet, там тоже есть что новенького. +5187.56 5197.00 "Анатолий Кулаков" Да, давай, не то чтобы прям много всего интересного, но такие концептуальные вещи, которых мы, опять же, упоминали в течение года, в NuGet и новом тоже зарелизились. +5197.00 5205.84 "Анатолий Кулаков" NuGet вышел 6.4, и самым главным лейтмотивом этой версии – это, конечно же, Central Package Manager. +5205.84 5217.16 "Анатолий Кулаков" Это специальный файлик, который можно положить в вашем солюшене, и он способен обрабатывать информацию для нескольких проектов, ну то есть для всех проектов, которые есть в вашем солюшене. +5217.16 5230.00 "Анатолий Кулаков" Файлик называется directory.package.props, и он внутри себя содержит наименование пакетов и версии этих пакетов, которые приняты в вашем солюшене. +5230.00 5240.12 "Анатолий Кулаков" Это значит, что теперь непосредственно в проектах вы можете указывать только наименования, которые нужны, те пакеты, которые нужны вашему проекту, и без указания версий. +5240.12 5244.76 "Анатолий Кулаков" Версии он возьмет из вот этого глобального package management файла. +5244.76 5248.48 "Анатолий Кулаков" Прелесть этого подхода в том, что вам больше не нужно консолидировать версии. +5248.48 5253.32 "Анатолий Кулаков" То есть во всех проектах у вас в Сибибиблиотеке будут одно и то же версии. +5253.32 5260.04 "Анатолий Кулаков" Это позволяет избежать кучи ошибок, это хорошо, это правильно, и плюсов у этого громадное количество. +5260.04 5268.84 "Анатолий Кулаков" Но в принципе такую штуку вы могли сделать и раньше ручками с помощью сложной системы props и target файлов. +5268.84 5272.08 "Анатолий Кулаков" Плюс вот этого подхода в том, что он поддерживается инструментарием. +5272.08 5288.48 "Анатолий Кулаков" То есть там всякие Visual Studio, Riders, Nuget консольные приложения, все они понимают этот файлик, и в отличие от того кастомного подхода с костылями, они будут нормально обновлять здесь эти пакеты, нормально везде пробрасывать, нормально интеллисенсом подхватывать, и в общем дело нужное. +5288.48 5296.76 "Анатолий Кулаков" В качестве велосипеда она живет давно и наконец-то прекрасно, что она теперь поддерживается официально и инструментарий соответственно тоже подхватил всю эту штуку. +5296.76 5307.20 "Анатолий Кулаков" Еще одно интересное нововведение, это возможность указать элемент в наших props файлах, который называется Global Package Reference. +5307.20 5316.20 "Анатолий Кулаков" Это штука, которая позволяет вам указать имя и версию пакета, которая автоматически подключится во все другие проекты. +5316.20 5320.20 "Анатолий Кулаков" Типичным примером есть у нас анализаторы. +5320.20 5324.04 "Анатолий Кулаков" Анализаторы обычно подключают просто ко всем проектам, которые есть в Solution. +5324.04 5332.88 "Анатолий Кулаков" Опять же, это можно было добиться с помощью старых props файлов, но здесь поддержка инструментария, интеллисенсов и прочие вещи тоже часто хромали. +5332.88 5345.04 "Анатолий Кулаков" Теперь у нас есть официальные директивы, официальные файли, как это можно сделать, и можно соответственно подключить любую библиотеку с любой версией прозрачно и однако всем проектам, которые в вашем Solution есть. +5345.04 5351.72 "Анатолий Кулаков" Естественно, вы можете обновлять теперь ее в одном месте, можете контролировать использование, можете ее подменять в одном месте. +5351.72 5353.72 "Анатолий Кулаков" Тоже довольно удобная штука. +5353.72 5355.40 "Анатолий Кулаков" Будем пользоваться. +5355.40 5362.40 "Анатолий Кулаков" Из мелочей увеличили производительность отображения и загрузки списка пакетов в Visual Studio. +5362.40 5376.92 "Анатолий Кулаков" Наверняка многие из вас заходили в Visual Studio на вкладку Management Nugget Packages и долгие минуты и часы ждали, пока прогрузятся все пакеты, пока обновятся их версии, пока проверятся и сигнатуры, подтянутся ряды. +5376.92 5381.24 "Анатолий Кулаков" Вот это все увеличили, говорят, обещают, что на 66%. +5381.24 5386.12 "Анатолий Кулаков" Циферка небольшая, но довольно приятная, особенно если для тех, кто часто заходит в это визуальное окошко. +5386.12 5389.44 "Игорь Лабутин" Да, действительно штука удобная. +5389.44 5396.88 "Игорь Лабутин" Мы такое костыляли с помощью директории, как там это называлось, что там тоже, Props, не помню что. +5396.88 5409.68 "Игорь Лабутин" И действительно там была проблема в том, что не было возможности, ну или по крайней мере мы не нашли каких-то простых костылей, как ограничить, ну как убедиться, что в конкретных проектах ты таки не указал случайно нужную версию. +5409.68 5415.56 "Игорь Лабутин" И если указал, то она использовалась вместо той, которая указана в центральном версии. +5415.56 5424.44 "Игорь Лабутин" Здесь это все контролируется, там теперь можно контролировать, можно ли оверрайдить версии, и они оверрайдятся специальным прям атрибутом, version override. +5424.44 5426.76 "Игорь Лабутин" Поэтому здесь действительно все будет удобно и хорошо. +5426.76 5434.60 "Анатолий Кулаков" Да, старый подход, он там основывался на какой-то концепции, главное не чихайте на этот файл, иначе все развалится. +5434.60 5437.76 "Анатолий Кулаков" В общем, с новым все довольно более стабильно. +5437.76 5445.48 "Игорь Лабутин" Ну и давай поговорим то, про что я обещал в самой первой новости, в самом начале этого выпуска, про поддержку контейнеров. +5445.48 5452.08 "Анатолий Кулаков" Да, давай, в принципе это кажется единственной нашей статьей, которой нет Microsoft за весь сегодняшний выпуск. +5452.08 5467.00 "Анатолий Кулаков" Но статья грамотная, она еще покрывает несколько интересных смежных тем, делает это правильно, с хорошими цифрами, поэтому мы решили ее добавить в выпуск, и поговорим мы как раз-таки о поддержке контейнеров, и что интересного на этой поприще есть в Дотэнт 7. +5467.00 5470.72 "Анатолий Кулаков" Прежде всего хочется вас познакомить с таким понятием, как числт убунту контейнер. +5470.72 5477.32 "Анатолий Кулаков" Это специальный контейнер, который очень маленький и очень секурный. +5477.32 5479.48 "Анатолий Кулаков" Он поставляется официальным каноникалом. +5479.48 5487.20 "Анатолий Кулаков" И его преимущество в том, что он где-то на 100% меньше обычной стандартной убунты. +5487.20 5494.24 "Анатолий Кулаков" Если стандартная убунта у нас занимает 219 Мб, то числт контейнер занимает где-то 116 Мб. +5494.24 5498.52 "Анатолий Кулаков" И так как он маленький, у этого есть много преимуществ. +5498.52 5503.48 "Анатолий Кулаков" В частности, у нас очень сильно уменьшается площадь атаки. +5503.48 5510.24 "Анатолий Кулаков" То есть у нас намного меньше инструментов, намного меньше утилит внутри контейнера содержится, намного меньше пакетов, которые могут быть атакованы. +5510.24 5516.00 "Анатолий Кулаков" В которых могут найти баги, в которых могут найти уязвимости, какие-нибудь бэкдоры вам затянуть или еще что-то. +5516.00 5519.68 "Анатолий Кулаков" В общем, чем меньше у вас зависимости, тем всегда это лучше. +5519.68 5525.24 "Анатолий Кулаков" И вот это пример, когда попытались сделать вот такой минимальный контейнер по зависимости. +5525.24 5532.96 "Анатолий Кулаков" Там нет пакетдж менеджера, там нет популярных пакетов предустановленных, которые обычно вы видите в своих контейнерах. +5532.96 5535.52 "Анатолий Кулаков" Там вообще даже нет шела. +5535.52 5537.96 "Анатолий Кулаков" И там нет рутового пользователя. +5537.96 5541.16 "Анатолий Кулаков" Там обычный юзер без рута. +5541.16 5547.92 "Анатолий Кулаков" Специфика этого контейнера заключается в том, что вы там даже не сможете выполнить баши, потому что там нет баши. +5547.92 5552.00 "Анатолий Кулаков" Вы там не сможете даже выполнить команду ls, там показать список файлов, потому что там нет команды ls. +5552.00 5560.56 "Анатолий Кулаков" То есть даже таких элементарных базовых утилит, с помощью которых вы обычно там навигируетесь по контейнеру и там ищите какие-нибудь проблемы, их там нет. +5560.56 5568.32 "Анатолий Кулаков" Поэтому отлаживать, возможно, вам будет его немножко сложнее на первом этапе, но зато размер и, соответственно, площадь атаки очень сильно уменьшена. +5568.32 5575.56 "Анатолий Кулаков" Вот такой контейнер, он сейчас официально поддерживается Майкрософтом, он лежит в репозитории Майкрософта с контейнерами. +5575.56 5579.84 "Анатолий Кулаков" Соответственно, его можно легко и непринужденно завязать в ваших приложениях. +5579.84 5586.24 "Игорь Лабутин" Тут надо сказать, что он не то чтобы поддерживается Майкрософтом, он еще поддерживается Каноникалом, что тоже важно. +5586.24 5589.24 "Игорь Лабутин" То есть Каноникал это тот, кто дистрибьютирует и производит Ubuntu. +5589.24 5594.84 "Игорь Лабутин" То есть это не просто Майкрософт решила взять и что-нибудь там урезать, это прям Каноникал. +5594.84 5597.44 "Игорь Лабутин" Вместе с Майкрософтом сделали такую штуку совместную. +5597.44 5607.16 "Анатолий Кулаков" Ну да, я подозреваю, что Каноникал сделал числот образ, а Майкрософт просто добавил туда зависимости для того, чтобы запускать там Дотнет. +5607.16 5608.16 "Анатолий Кулаков" Скорее всего. +5608.16 5613.48 "Анатолий Кулаков" Как всегда они, в принципе, на таком уровне взаимодействия у них идет. +5613.48 5623.84 "Анатолий Кулаков" Вот, и еще одно нововведение, то есть это не еще одно нововведение, это нововведение, которое было сделано в Дотнет 7, которое мы уже тоже упоминали, это возможность генерировать докер-файлы. +5623.84 5631.36 "Анатолий Кулаков" Как вы, наверное, все уже знаете, чтобы упаковать приложение в докер-контейнер, у нас есть так называемые докер-файлы. +5631.36 5636.08 "Анатолий Кулаков" У них там свой синдекс, если они там каким-то образом описываются, думаю, что с этим вы уже все знакомы. +5636.08 5651.80 "Анатолий Кулаков" Вот, и, соответственно, новинка Дотнет 7 SDK заключается в том, что теперь вам не обязательно делать отдельный рядышком стоящий докер-файл для того, чтобы сделать имидж, в котором лежит ваше приложение. +5651.80 5665.64 "Анатолий Кулаков" Микрософт изобрел новый output type, то есть достаточно в Дотнет паблише указать специальные магические ключи и у вас в результате вашего паблиша получится уже полноценный докер-имидж без всякого докер-файла. +5665.64 5682.92 "Анатолий Кулаков" Единственное, что вам нужно сделать, это подключить к вашему проекту специальный пакет, ну, get-пакет, который называется Microsoft.NET Build Containers, но это все на уровне пока разработки, и в будущем этого пакета тоже подключать не нужно будет, он будет входить в стандартные SDK Дотнета. +5682.92 5684.84 "Анатолий Кулаков" Пока это так. +5684.84 5688.48 "Анатолий Кулаков" В общем, если не нужно будет подключать никаких пакетов, это совсем прекрасно. +5688.48 5698.32 "Анатолий Кулаков" Вот вы делаете команду dotnet-publish, указываете ей там, что хотите, опясываете систему Linux и передаете ее в специальный флажок, который называется publish-para-file и равняется он дефолт-контейнеру. +5698.32 5707.84 "Анатолий Кулаков" И в результате чего в вашем распоряжении получается, как я уже сказал, докер-имидж, по дефолту его размер 216 или около того мегабайт. +5707.84 5714.00 "Анатолий Кулаков" И этот имидж, его можно настраивать. +5714.00 5721.32 "Анатолий Кулаков" Обычно мы настраиваем докер-контейнеры через докер-файл, так как у нас докер-файла нет, то мы можем настраивать через MS Build свойства. +5721.32 5734.12 "Анатолий Кулаков" Через свойства наших MS-publish-файлов, props-файлов, targets-файлов, там можно указать имя контейнера, там можно указать теги и кучу-кучу других разных параметров, которые обычно вы указываете в дотнет-файле. +5734.12 5737.12 "Анатолий Кулаков" В докер-файле. +5737.12 5738.12 "Анатолий Кулаков" Извините. +5738.12 5739.12 "Анатолий Кулаков" Вот. +5739.12 5742.64 "Анатолий Кулаков" Это то нововведение, которое у нас есть в дотнет-7 SDK. +5742.64 5747.72 "Анатолий Кулаков" Теперь, каким же образом нам теперь свести вместе два этих интересных новости? +5747.72 5748.72 "Анатолий Кулаков" Свести их довольно просто. +5748.72 5753.40 "Анатолий Кулаков" Как я уже сказал, в MS Build файле мы можем настраивать докер-контейнеры. +5753.40 5757.00 "Анатолий Кулаков" Там есть специальный ключевой элемент, который называется container-base-image. +5757.00 5761.72 "Анатолий Кулаков" И в качестве базового имиджа мы можем указать вот этот числт-образ. +5761.72 5776.04 "Анатолий Кулаков" В результате чего мы набираем команду dotnet-publish и у нас уже появляется докер-имидж размером 112 мегабайт против наших 216, которые были буквально одну команду назад. +5776.04 5779.42 "Анатолий Кулаков" Мы всего лишь навсего что и сделали, это поменяли базовый образ. +5779.42 5783.26 "Анатолий Кулаков" То есть мы выиграли 104 мегабайта на пустом месте. +5783.26 5787.88 "Анатолий Кулаков" Довольно неплохой результат, но в принципе можно сделать еще лучше и еще больше. +5787.88 5791.52 "Анатолий Кулаков" В частности, мы можем сделать self-content. +5791.52 5799.48 "Анатолий Кулаков" Насколько вы, наверное, уже в курсе, у нас дотнет умеет поставляться без дотнет-рантайма. +5799.48 5802.28 "Анатолий Кулаков" Дотнет-рантайм ему не обязателен. +5802.28 5807.44 "Анатолий Кулаков" Он может включить все библиотеки, которые нужны вашему приложению внутрь этого приложения. +5807.44 5813.64 "Анатолий Кулаков" То есть тут вообще скопировать все ассембли, все дейдельки и все, что ему нужно, просто в одну папочку. +5813.64 5820.72 "Анатолий Кулаков" Вот если мы воспользуемся этой функциональностью, сделаем self-content, тогда у нас появится такая возможность, как затримить наше приложение. +5820.72 5822.56 "Анатолий Кулаков" То есть убрать все ненужное. +5822.56 5826.88 "Анатолий Кулаков" То есть мы не должны тащить с собой весь огромный SDK, весь огромный рантайм. +5826.88 5835.76 "Анатолий Кулаков" Мы можем проанализировать наше приложение и сказать, какие сборки нужны, какие не нужны. +5835.76 5839.12 "Анатолий Кулаков" И вот флажок Trimton как раз это и делает. +5839.12 5855.72 "Анатолий Кулаков" Если мы запустим теперь нашу сборку, наш паблиш вместе с усечением и вместе с self-content, то результирующий образ у нас будет всего лишь на 56 Мб. +5855.72 5864.72 "Анатолий Кулаков" То есть сравнивая с предыдущими 112 Мб, мы сэкономили еще 55 Мб, что тоже довольно крутецкая оптимизация. +5864.72 5869.24 "Анатолий Кулаков" Можно сделать еще немножко поменьше. +5869.24 5878.56 "Анатолий Кулаков" Секрет заключается в том, что self-content приложение, которое внутри себя включает все, что ему нужно для запуска, его еще можно собрать в один единственный файлик. +5878.56 5885.84 "Анатолий Кулаков" То есть у нас есть папочка, в которой было много сборок до этого, а теперь у нас будет папочка, в которой лежит всего лишь один единственный файл. +5885.84 5889.84 "Анатолий Кулаков" Один бинарник и внутри этого бинарника зашиты все множество-множество сборок. +5889.84 5899.00 "Анатолий Кулаков" Тут нужно уточнить, что у этого подхода есть некоторые ограничения и существует специальный сценарий, где такая штука работать не будет, где она не поддерживается. +5899.00 5905.04 "Анатолий Кулаков" Но в общем, как потенциально возможная оптимизация, он существует. +5905.04 5912.68 "Анатолий Кулаков" В результате такой махинации, в результате сингл-файла у нас появится один единственный файл размером 48 мегабайт. +5912.68 5918.64 "Анатолий Кулаков" Сравнивая с предыдущими пятью, десятью, шестью, мы выиграли 8 мегабайт. +5918.64 5927.00 "Анатолий Кулаков" Не то чтобы много, но в принципе на размерах, на размерах которых мы уже работаем, там в размерах 50 мегабайт, 8 мегабайт, это в принципе существенная часть. +5927.00 5930.76 "Анатолий Кулаков" Поэтому тоже хорошая качественная оптимизация. +5930.76 5939.24 "Анатолий Кулаков" Еще одна интересная оптимизация, которая существует в Дотнете, это штука, которая называется invariant globalization. +5939.24 5963.64 "Анатолий Кулаков" То есть если в вашем приложении вы не используете никаким образом различные культуры, вы не форматируете, допустим, даты на русском языке, вы не сравниваете строки на греческом языке, в общем все вот эти штуки вам не нужны, а эта вероятность довольно большая, потому что большинство Дотнет-приложений это все-таки какие-нибудь серверные бэкэнды. +5963.64 5970.12 "Анатолий Кулаков" И на серверных бэкэндах существует такая best practice, что вам там ни в коем случае не нужна никакая локализация. +5970.12 5973.00 "Анатолий Кулаков" Там все должно быть в invariant и в UTC. +5973.00 5977.44 "Анатолий Кулаков" То есть ни времен, ни локализации быть не должно и в помине. +5977.44 5986.00 "Анатолий Кулаков" Локализация и времена, всякие часовые зоны вам нужны только там, где вы представляете уже непосредственно пользователя. +5986.00 5993.60 "Анатолий Кулаков" То есть это или UI, или какие-нибудь отчеты, или какие-нибудь письма, то есть какое-нибудь уже конечное представление для пользователя. +5993.60 6003.56 "Анатолий Кулаков" Если у вас чистый бэкэнд, который суровый, письма не шлет, с пользователем не взаимодействует, а чисто что-то там у себя крутит, вы вполне легко, скорее всего, можете этот флажок использовать. +6003.56 6016.04 "Анатолий Кулаков" И это очень крутой флажок, когда вы говорите «удали мне все культуры, которые там у тебя есть, все транслейшн, которые у тебя есть, все ресурсы с переводами, которые у тебя есть, оставь только invariant globalization». +6016.04 6026.20 "Анатолий Кулаков" Если вы такой флажок задаете, то обычно у вас тоже… у вас тоже огромный прирост в месте, то есть очень много места освобождается. +6026.20 6032.00 "Анатолий Кулаков" В данном же случае автор попробовал сделать проверную такую штуку, и у него практически ничего не получилось. +6032.00 6038.32 "Анатолий Кулаков" Из 48,4 мегабайта у него стало 48,3 мегабайта. +6038.32 6045.92 "Анатолий Кулаков" То есть он удалил глобализацию только из своего конкретного приложения, которых и так было немного. +6045.92 6049.40 "Анатолий Кулаков" А с фреймворка ничего не случилось. +6049.40 6050.68 "Анатолий Кулаков" Секрет очень простой. +6050.68 6057.44 "Анатолий Кулаков" Дело в том, что вот этот числ имидж, он уже внутри себя содержит вот эту функциональность. +6057.44 6065.60 "Анатолий Кулаков" Он уже внутри себя, по сути, удалил всю глобализацию, все вот эти ресурсы, которые нужны для использования различных языков, ее там уже нет. +6065.60 6069.16 "Анатолий Кулаков" Поэтому он такой компактный, большой и красивый. +6069.16 6074.16 "Анатолий Кулаков" Проделав все эти возможные на данный момент оптимизации, которые у нас получились, давайте подведем итог. +6074.16 6077.00 "Анатолий Кулаков" Изначальный имидж у нас был 216 мегабайт. +6077.00 6084.04 "Анатолий Кулаков" Это, скорее всего, то, что имеет каждое дотальное приложение в ваших проектах. +6084.04 6097.60 "Анатолий Кулаков" Это тот размер, который у вас будет по дефолту, если вы используете все дефолтные настройки, дефолтные контейнеры, дефолтные паблиши, вы примерно получите ваше приложение примерно в контейнере 216 мегабайт. +6097.60 6104.20 "Анатолий Кулаков" И довольно элементарно, простыми действиями, его можно довести всего лишь навсего до 48 мегабайт. +6104.20 6109.12 "Анатолий Кулаков" То есть, по факту, это 77% удалось нам ужать. +6109.12 6120.08 "Анатолий Кулаков" Вот такими незамысловатыми способами, используя знания от, даже не знания, а имидж от Canonical с Microsoft и небольшие знания по оптимизации, по отримингу нашего приложения. +6120.08 6124.08 "Анатолий Кулаков" То есть, сейчас у нас примерный имидж, минимальный имидж дотлнет приложения. +6124.08 6130.92 "Анатолий Кулаков" Опять же, мы сейчас говорим не про какой-то экстремальный минимализм, а такой вполне бытовой, вполне рабочий, вполне повседневный. +6130.92 6133.52 "Анатолий Кулаков" И это 48 мегабайт. +6133.52 6136.60 "Игорь Лабутин" Все было бы хорошо, если бы... +6136.60 6141.96 "Игорь Лабутин" Нет, ну все-таки мне кажется, что self-contained и trimming это пока еще не настолько популярная штука. +6141.96 6148.20 "Игорь Лабутин" Ну, self-contained популярная, а вот trimming, по-моему, пока еще не настолько популярная штука, тем более и паблишинг сингл файл. +6148.20 6159.16 "Игорь Лабутин" Это тоже отдельный вопрос, поэтому я бы сказал, что ну, наверное, справедливость ради не 48, а все-таки 56, если мы уберем сингл файл паблишинг. +6159.16 6167.12 "Игорь Лабутин" Ну и опять же, то, что мы уменьшили с 216, это если мы использовали стандартный ubuntu-овский обычный базовый имидж. +6167.12 6182.96 "Игорь Лабутин" Я же, например, ну у нас практически все живет на alpine, alpine поменьше, но с alpine есть как бы проблема, ну не то чтобы проблема, alpine это все-таки не distroless, насколько я помню, то есть там есть root, там есть вот все те самые баши и все такое прочее, то есть секьюрность у него все-таки поменьше. +6182.96 6190.56 "Игорь Лабутин" Поэтому тут надо выбирать, надо посмотреть, нельзя ли из alpine получить такую конструкцию урезанную, тут вот не знаю. +6190.56 6199.16 "Анатолий Кулаков" Да, да, да, ты во всем прав, действительно хотелось бы от alpine тоже все отсечь ненужное и посмотреть, сколько он сможет выдать на таких размерах. +6199.16 6213.96 "Игорь Лабутин" Ну может кто-то где-то это уже сделал, если вдруг вы знаете какие-нибудь там правильные distroless базовые имиджи для дотонета и майкрософта, и alpine, расскажите нам в комментариях где-нибудь, мы это дело попробуем проверим, посмотрим. +6213.96 6218.20 "Игорь Лабутин" Может быть даже попробуем собрать какое-нибудь такое же приложение и посмотреть какого размера оно получается. +6218.20 6221.00 "Игорь Лабутин" Ну а на этом я думаю, что надо завершать. +6221.00 6228.32 "Игорь Лабутин" Мы собственно обозрели по-моему практически все, что было хоть как-то упомянуто на dotnet.conf. +6228.32 6235.32 "Игорь Лабутин" Понятно, что там был еще большой кусок, ну кстати не такой большой, как я ожидал, который был посвящен ажуру и прочим облакам. +6235.32 6238.80 "Игорь Лабутин" Там есть некоторое количество видео про эту тему, но не такое большое. +6238.80 6246.32 "Игорь Лабутин" Основное все-таки внимание было уделено действительно дотонету и всяким таким более фреймворк-ориентированным вещам. +6246.32 6265.84 "Анатолий Кулаков" Как всегда в наших заметках к выпуску будет куча разных ссылок, в том числе ссылки на доклады, которые были непосредственно на dotnet.conf, поэтому проходите, читайте, смотрите, пробуйте сами, углубляйтесь в каждой темы, ходите по ссылкам глубже, переслушивайте наши выпуски, в общем тут поле для изучения довольно большое. +6265.84 6287.52 "Игорь Лабутин" Да, и часть ссылок ведет на learn.microsoft.com, который раньше был docs.com.msd, там прямо действительно сейчас очень хорошая документация, отличные статьи, которые не просто там описание класса и апишка, а именно прям вот хорошие учебные статьи, которые помогают очень сильно понять, как же все это работает вместе. +6287.52 6291.32 "Игорь Лабутин" Ну а на сегодня, наверное, будем завершаться. +6291.32 6311.20 "Игорь Лабутин" Мы отсмотрели все, мы отсмотрели dotnet.7, dotnet.conf, c#, f#, dotnet.conf, f#, f#, spanet, entity framework, ui, потрогали windows.forms, wpf, dotmall, потрогали экзотические вещи типа ml.net и arlinz, ну и посмотрели на tooling, visual studio в разных ее видах, nuget и поддержка контейнеров. +6311.20 6340.08 "Игорь Лабутин" В dotnet.7 новостей много, новости разные, будем следить теперь, что будет происходить, как будет адоптиться dotnet.7, какие будут выходить статьи на эту тему, и возможно какие-то ранние уже dotnet.8 штучки будут так или иначе появляться даже до первого превью, может быть нам что-нибудь попадется на глаза, мы начнем уже смотреть какие-то ранние, подсматривать я бы даже сказал, в ранние эксперименты команды на тему 8-го дотнета. +6340.08 6345.68 "Анатолий Кулаков" Ну а на сегодня это достаточно, всем спасибо, кто дослушал до конца и до новых встреч, всем пока. +6345.68 6346.04 "Игорь Лабутин" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-63.txt b/input/Radio/Transcriptions/RadioDotNet-63.txt index f8b5d92..4ac013a 100644 --- a/input/Radio/Transcriptions/RadioDotNet-63.txt +++ b/input/Radio/Transcriptions/RadioDotNet-63.txt @@ -1,772 +1,771 @@ -0.00 11.52 SPEAKER_00 Здравствуйте, дорогие друзья, в эфире Radio.net, выпуск номер 63. -11.52 13.84 SPEAKER_00 В эфире, как всегда, Анатолий Кулаков. -13.84 15.60 SPEAKER_00 И Игорь Лопутин, всем привет. -15.60 22.16 SPEAKER_00 В самом начале хотелось бы поблагодарить наших друзей, тем, кто у нас помогает на нашем сайте Boosty. -22.16 27.72 SPEAKER_00 Это Александр, Сергей, Владислав, Алексей, Шевченко Антон, Илья и Горький Самарин. -27.72 31.92 SPEAKER_00 Спасибо большое, что помогаете, и всем другим, кто поддерживает нас на Boosty. -31.92 35.12 SPEAKER_00 Ну что ж, прогремел у нас .NET Conf. -35.12 39.88 SPEAKER_00 Надеюсь, вам понравились все те новинки, которые были анонсированы. -39.88 42.28 SPEAKER_00 Надеюсь, вам понравился выпуск, который мы записали. -42.28 47.52 SPEAKER_00 Получился довольно такой плотненький, тем у нас там просто было рекордное количество, очень много. -47.52 61.20 SPEAKER_00 Ну и естественно, всего мы не охватили, и может быть вот какие-то отголоски, какие-то инструменты, какие-то еще те ответвления будем постепенно догонять до тех пор, пока нас Microsoft не начнет нарадовать какими-то новыми релизами. -61.20 68.80 SPEAKER_00 И наверное вот сегодня несколько даже таких статейчиков, которые можно было бы отнести к выпуску .NET. -68.80 78.00 SPEAKER_00 Мы сегодня тоже вспомним, но они будут как раз-таки не новостные, а уже какие-то осмысленные, там про перформанс, про настройку, может быть, про сравнение, про еще что-то. -78.00 83.80 SPEAKER_00 Ну что ж, у нас официальная часть закончена, давай посмотрим, что у нас из статей сегодня есть. -83.80 103.28 SPEAKER_02 Да, как ты правильно сказал, сразу после релиза у нас у Microsoft не так много, так сказать, чего обсуждать с точки зрения новостей, но после релиза осталось какое-то количество статей, которые можно обсудить, или такие, точнее, не статей, а того, чего происходило в момент релиза или на презентации, которые были показаны. -103.28 112.00 SPEAKER_02 И одна из статей как раз называется "How fast is SP.NET Core?", то есть насколько вообще он быстр, SP.NET Core. -112.00 133.44 SPEAKER_02 Если вы смотрели .NET Conf презентейшн и прошлого года, и вообще говоря этого года, то в обоих презентациях было сказано, что .NET у нас очень супербыстрый, он стал еще быстрее, и в 2021 году был слайдик, где было написано, что .NET в 10 раз быстрее Node.js, ну и заодно быстрее, чем Java, Go и плюсы. -133.44 134.44 SPEAKER_02 Вместе взятые. -134.44 138.80 SPEAKER_02 Не уточнялось, но возможно, да, было бы очень здорово, если бы вместе взятые. -138.80 151.48 SPEAKER_02 В 2022 году слайдик, по-моему, был какой-то похожий, там может быть был не 10x, а 7x, я вот сейчас не помню, но смысл в том, что тоже было прям супербыстро и все такое. -151.48 173.68 SPEAKER_02 И товарищ по имени Себастин Рос, это представитель команды SP.NET, который как раз-таки занимается в том числе перформансом, сказал или написал такую фразу, что даже с самым быстрым вебфреймворком на Go, .NET все равно быстрее, при том, что он использует высокоуровневый стэк, то есть middleware, minimal API, вот это все. -173.68 194.88 SPEAKER_02 И такой товарищ, как Дастин Моррис Горский, это довольно известный, я бы сказал, ф-шарпер, который поддерживает штуку под названием Giraffe, это микровебфреймворк для ф-шарпа, он решил проверить, правда ли это, ну потому что слайдик - это слайдики, но слайдики - это менеджерская штука, давайте посмотрим, что там на самом деле, тем более, что все бенчмарки, они открыты. +0.00 11.52 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Radio.net, выпуск номер 63. +11.52 13.84 "Анатолий Кулаков" В эфире, как всегда, Анатолий Кулаков. +13.84 15.60 "Анатолий Кулаков" И Игорь Лабутин, всем привет. +15.60 22.16 "Анатолий Кулаков" В самом начале хотелось бы поблагодарить наших друзей, тем, кто у нас помогает на нашем сайте Boosty. +22.16 27.72 "Анатолий Кулаков" Это Александр, Сергей, Владислав, Алексей, Шевченко Антон, Илья и Гурий Самарин. +27.72 31.92 "Анатолий Кулаков" Спасибо большое, что помогаете, и всем другим, кто поддерживает нас на Boosty. +31.92 35.12 "Анатолий Кулаков" Ну что ж, прогремел у нас .NET Conf. +35.12 39.88 "Анатолий Кулаков" Надеюсь, вам понравились все те новинки, которые были анонсированы. +39.88 42.28 "Анатолий Кулаков" Надеюсь, вам понравился выпуск, который мы записали. +42.28 47.52 "Анатолий Кулаков" Получился довольно такой плотненький, тем у нас там просто было рекордное количество, очень много. +47.52 61.20 "Анатолий Кулаков" Ну и естественно, всего мы не охватили, и может быть вот какие-то отголоски, какие-то инструменты, какие-то еще те ответвления будем постепенно догонять до тех пор, пока нас Microsoft не начнет нарадовать какими-то новыми релизами. +61.20 68.80 "Анатолий Кулаков" И наверное вот сегодня несколько даже таких статейчиков, которые можно было бы отнести к выпуску .NET. +68.80 78.00 "Анатолий Кулаков" Мы сегодня тоже вспомним, но они будут как раз-таки не новостные, а уже какие-то осмысленные, там про перформанс, про настройку, может быть, про сравнение, про еще что-то. +78.00 83.80 "Анатолий Кулаков" Ну что ж, у нас официальная часть закончена, давай посмотрим, что у нас из статей сегодня есть. +83.80 103.28 "Игорь Лабутин" Да, как ты правильно сказал, сразу после релиза у нас у Microsoft не так много, так сказать, чего обсуждать с точки зрения новостей, но после релиза осталось какое-то количество статей, которые можно обсудить, или такие, точнее, не статей, а того, чего происходило в момент релиза или на презентации, которые были показаны. +103.28 112.00 "Игорь Лабутин" И одна из статей как раз называется "How fast is SP.NET Core?", то есть насколько вообще он быстр, SP.NET Core. +112.00 133.44 "Игорь Лабутин" Если вы смотрели .NET Conf презентейшн и прошлого года, и вообще говоря этого года, то в обоих презентациях было сказано, что .NET у нас очень супербыстрый, он стал еще быстрее, и в 2021 году был слайдик, где было написано, что .NET в 10 раз быстрее Node.js, ну и заодно быстрее, чем Java, Go и плюсы. +133.44 134.44 "Игорь Лабутин" Вместе взятые. +134.44 138.80 "Игорь Лабутин" Не уточнялось, но возможно, да, было бы очень здорово, если бы вместе взятые. +138.80 151.48 "Игорь Лабутин" В 2022 году слайдик, по-моему, был какой-то похожий, там может быть был не 10x, а 7x, я вот сейчас не помню, но смысл в том, что тоже было прям супербыстро и все такое. +151.48 173.68 "Игорь Лабутин" И товарищ по имени Себастин Рос, это представитель команды SP.NET, который как раз-таки занимается в том числе перформансом, сказал или написал такую фразу, что даже с самым быстрым вебфреймворком на Go, .NET все равно быстрее, при том, что он использует высокоуровневый стэк, то есть middleware, minimal API, вот это все. +173.68 194.88 "Игорь Лабутин" И такой товарищ, как Дастин Моррис Горский, это довольно известный, я бы сказал, ф-шарпер, который поддерживает штуку под названием Giraffe, это микровебфреймворк для ф-шарпа, он решил проверить, правда ли это, ну потому что слайдик - это слайдики, но слайдики - это менеджерская штука, давайте посмотрим, что там на самом деле, тем более, что все бенчмарки, они открыты. 194.88 197.28 None Код открыт и доступен. -197.28 226.76 SPEAKER_02 Мы говорим про бенчмарки, которые называются Tech Empower, довольно известная штука, там есть огромное количество всяких разных бенчмарков, которые проверяют и то, и это, и смысл в том, что они запускают эти самые бенчмарки у себя на серверах, то есть регулярно, но регулярность у них, она такая как бы непонятная, последний официальный раунд 21-й был в июле 22-го года, а до этого в феврале 21-го, ну не то, чтобы очень регулярно, но будем считать, что так. -226.76 283.64 SPEAKER_02 Конкретно про бенчмарки, которые нас интересуют, даже не которые нас интересуют, а которые хоть как-то могут относиться к SPNetCore, они относятся к куче категорий, есть там бенчмарки про JSON Serializers, про Single Query, Multiple Query, Caching Query, бенчмарк под названием Fortune's, ну и там несколько других, и вот как раз-таки Fortune's - это то, что является более-менее таким, то, что он называет Gold Standard в бенчмарках, именно в веб-фреймворках, потому что он более-менее пытается воспроизвести, что происходит в реальной жизни с вашим приложением, то есть в этом бенчмарке мы читаем из базы данных, сортируем данные, потом добавляем какой-то там заголовочек для всяких XSS, предотвращения XSS, и даже делаем небольшой сервер-сайт, значит, HTML-рендеринг на основе шаблонов, ну вроде как такое, обычное веб-приложение более-менее. -283.64 296.92 SPEAKER_02 Понятно, что там не гигантские данные, поскольку это бенчмарк, то он запускается там много-много-много раз, поэтому из базы данных по-моему там читается типа 12 записей или около того, но смысл в том, что все равно тестируются какие-то кусочки фреймворка. -296.92 302.00 SPEAKER_02 Итак, давайте, говорит автор, посмотрим на результаты SPNetCore. -302.00 319.92 SPEAKER_02 Находит он, если мы берем, значит, рейтинг топ всяких фреймворков, он находит там три записи с названием SPNetCore, это ASP.Core.ado, Postgres, ASP.Core.mw, Postgres и ASP.NetCore. -319.92 320.92 SPEAKER_02 Ну вроде как три. -320.92 324.52 SPEAKER_02 Они занимают, соответственно, 9, 13 и 14 места, ну вроде неплохо. -324.52 330.84 SPEAKER_02 Но если посмотреть полную таблицу, выясняется, что всего существует 15 разных ASP.NetCore бенчмарков. -330.84 338.52 SPEAKER_02 Они основаны, поскольку мы читаем из базы данных, то они основаны некоторые на Postgres, некоторые на MySQL. -338.52 343.16 SPEAKER_02 Мы выкидываем те, которые про MySQL, потому что они точно медленнее, чем те, которые Postgres, видно по результатам. -343.16 345.28 SPEAKER_02 Некоторые из них основаны на Mono. -345.28 349.44 SPEAKER_02 Mono мы тоже сейчас выкидываем, потому что мы же говорим про релиз 7-го дотнета. -349.44 358.44 SPEAKER_02 И остается у нас 7 штук, то есть 7 бенчмарков, которые все используют Postgres, и они классифицируются дальше на еще несколько категорий. -358.44 363.20 SPEAKER_02 Самый топовый, который самый крутой, он классифицирован как Platform. -363.20 371.68 SPEAKER_02 Следующие 3 классифицированы как Micro, и еще 3 более медленных классифицированы как Full. -371.68 379.60 SPEAKER_02 Причем эта классификация не является каким-то стандартом, который техэмпауэр, это просто некоторые теги, которые автор бенчмарка может навесить. -379.60 383.88 SPEAKER_02 Ну вот так оно классифицируется, почему нет. -383.88 392.48 SPEAKER_02 Если посмотреть на топовый бенчмарк, он говорит, ну давайте мы разберем, что же там в этом топовом бенчмарке, как мы так всех уделываем в 10 и больше раз. -392.48 401.84 SPEAKER_02 Сама дотнетим, команда дотнетком, считает этот бенчмарк, точнее один из тегов, который навешан на этот бенчмарк, называется реалистик. -401.84 413.44 SPEAKER_02 И он говорит, ну автор говорит, давайте, открываем код, смотрим, и приводит в структуру проекта, и в том числе скриншотик кода из программ ЦС. -413.44 418.56 SPEAKER_02 Он говорит, ну что тут, из знакомого из PanadCore тут только слово kestrel, ну типа use kestrel. -418.56 421.68 SPEAKER_02 Больше там нет ничего знакомого из ISP-PanadCore. -421.68 431.24 SPEAKER_02 Для того, чтобы этот бенчмарк был таким супер быстрым, там применено огромное количество оптимизаций. -431.24 441.84 SPEAKER_02 Там нету строчек вообще, ну точнее, строчки вы в коде увидите, но они сразу передаются в класс под названием ASCIIString, который внутри их тут же конвертит первым делом в момент инстализации в byte array. -441.84 450.60 SPEAKER_02 То есть это делается один раз за жизнь программы, и дальше эти строчки все собираются в ответы HTTP, без, понятно, конвертации, дальше в байты. -450.60 452.12 SPEAKER_02 Сразу из byte array собираются ответы. -452.12 465.84 SPEAKER_02 Все части заголовков HTTP-шных тоже сразу вычисляются в байтах и записываются, значит, грубо говоря, в переменные, которые живут все время жизни программы. -465.84 467.80 SPEAKER_02 Раутинг сделан очень круто. -467.80 469.20 SPEAKER_02 Раутинг сделан следующим образом. -469.20 472.48 SPEAKER_02 Мы получаем реквест напрямую от kestrel. -472.48 484.72 SPEAKER_02 Мы берем path в url и проверяем, условно говоря, если девятый символ в рауте равен c, то это точно не fortunes. -484.72 487.64 SPEAKER_02 Там есть несколько стандартных endpoint, по которым должны отвечать бенчмарки. -487.64 499.40 SPEAKER_02 Ну и понятно, что если учитывать, что их конечное количество, то можно написать довольно оптимальный алгоритм, который, проверяя 1-2 символа всего лишь, точно узнает, какой из этих стандартных endpoint был вызван. -499.40 507.16 SPEAKER_02 То есть это нифига не полноценный раутинг, это вот такой очень специфически заточенный под это benchmark раутинг. -507.16 512.16 SPEAKER_02 Никакого там html контекста, вообще из span-add-core только kestrel, больше ничего нет. -512.16 520.88 SPEAKER_02 Пишем мы все это напрямую в pipewriter, то есть это тоже, опять же, ну если не socket, то очень близко с kestrel. -520.88 526.44 SPEAKER_02 Никаких html-темплейтов, напоминаю, что бенчмарки подразумевают какой-то сервер-сайт html-темплейт-рендеринг. -526.44 531.48 SPEAKER_02 Никаких там html-темплейтов, типа rather-pages или rather-views нет. -531.48 536.24 SPEAKER_02 Зато мы с stringbuilder собираем строчку ответа и ее фигачим в ответ. -536.24 540.52 SPEAKER_02 И самая крутая оптимизация это с датой. -540.52 546.72 SPEAKER_02 По стандарту этого бенчмарка, по описанию, мы обязаны отправить в ответ хедер с датой. -546.72 549.72 SPEAKER_02 Ну типа там, текущая дата такая-то. -549.72 557.76 SPEAKER_02 По стандарту, опять же, http, эта дата отправляется без миллисекунд, то есть там точность секунда в этой дате. -557.76 564.44 SPEAKER_02 Поэтому команда span-add-core, точнее, команда, которая писала этот бенчмарк, сделала следующую прекрасную штуку. -564.44 573.68 SPEAKER_02 У нас есть код, который заполняет значение этого заголовка, даты текущие, в ответ, в response-header. -573.68 576.84 SPEAKER_02 Он туда берет значение статической переменной. -576.84 586.60 SPEAKER_02 И есть отдельный тред, который эту статическую переменную, там строчка, сразу, периодически раз в секунду обновляет новым значением текущего даты времени. -586.60 591.28 SPEAKER_02 Ну вызывает dateTime.utcNow.toString один раз в секунду в багграундном треде. -591.28 602.40 SPEAKER_02 И это прям сильно повышает производительность, потому что понятно, что мы за секунду обслуживаем, не знаю, тысячи реквестов, и даже сотни тысяч реквестов. -602.40 609.20 SPEAKER_02 И понятно, что вместо того, чтобы вызывать utcNow.toString на каждом, мы это делаем один раз в секунду всего лишь и кэшируем это значение. -609.20 611.92 SPEAKER_00 Ну действительно реалистик, что уж говорить, каждый -611.92 615.24 SPEAKER_02 день так и пишу. Да, реалистик, так реалистик. -615.24 624.56 SPEAKER_02 Если посмотреть на код микробенчмарков, вот три следующих, которые чуть более тормозные, они уже ну поближе к SPNetCore. -624.56 643.40 SPEAKER_02 Там все еще нет раутинга полноценного, и не то, что ML-темплейтов, там все еще StringBuilder, но там уже нормальная типа middleware, которая просто, ну по сути там все сделано на одной middleware, то есть middleware проверяет, что если путь содержит fortunes, то надо в shtp-контекст.response послать соответствующую строчку ответа. -643.40 650.08 SPEAKER_02 То есть там уже есть shtp-контекст, все дела, но никакого там контроллеров, фразеров, вот этого всего нет. -650.08 664.60 SPEAKER_02 Ну и полный benchmark, да там все как положено, все как мы знаем и любим, это контроллеры, reserview, все такое прочее, но он уже не 9, там 13 или 14, а он 109 в рейтинге. -664.60 674.68 SPEAKER_02 И он успевает обслуживать, тем не менее, 109 эта штука обслуживает 184 тысячи реквестов в секунду. -674.68 681.52 SPEAKER_02 То есть вообще говоря, числа, в абсолютном понимании числа неплохие, мы все равно все еще достаточно быстрые. -681.52 689.48 SPEAKER_02 Но далеко не на первом месте, ну и там не в десятке, назовем это так, а всего лишь 109. -689.48 696.68 SPEAKER_02 Он говорит, окей, давайте посмотрим на другие языки, может быть другие языки тоже там все четерят и делают неправильно. -696.68 724.64 SPEAKER_02 Он говорит, ну берем java, там, ну там конечно не spring, там где-то в тормозах, где-то глубоко внизу, но у java есть более легковесный раутинг и прочее, что такое, значит, такие сервера, и он на нормальном, как бы одном из таких серверов, он 12 из 400 тысяч реквестов в секунду, тут напоминаю 184, то есть типа в 2 раза быстрее на java можно написать. -724.64 739.72 SPEAKER_02 В go тоже 22 место и 381 тысяча, ну плюсы на первом месте 616 тысяч реквестов в секунду, как бы их сложно побить, поэтому говорить, что мы там быстрее c++, ну это как-то странно, мы не быстрее c++. -739.72 754.52 SPEAKER_02 Вот, а остальные языки тоже на самом деле не так все плохо, то есть и Rust, и Kotlin, и Node.js, и PHP, они все есть, Node.js только помедленнее на 100% в любом варианте, а остальные языки в разумной реализации вроде есть выше нас. -754.52 789.20 SPEAKER_02 И вывод из статьи такой, что ну блин, короче, полная фигня, как бы это все маркетологи врут, сп.netcore не такой быстрый, при том, что товарищ на самом деле пишет очень хорошо, он говорит, что типа при этом не надо винить в этом команду, ну в смысле это не команда такая плохая, что они вот так вот рекламируются, это как бы маркетинг увидел такие чиселки и решил, что да, скажем, что .net такой быстрый, хотя цель команды была в том, чтобы показать, на что способна платформа, если написать, ну если грубо говоря вы захотите написать там, не знаю, фреймворк новый поверх кестрила, то что вам может дать кестрил? -789.20 796.28 SPEAKER_02 Именно поэтому он обозван как платформ, то он реалистик, но он платформ, то есть типа на что способна вот платформ в смысле кестрила? -796.28 798.40 SPEAKER_02 И все ни жили раще. -798.40 820.84 SPEAKER_02 Вот Дэвид Фаулер в твиттере отреагировал на все это дело и как раз сказал, что ну да, типа вот мы вот так хотели, это как раз были его слова про то, что мы хотели показать, насколько быстро вы можете построить что-нибудь поверх собственно основной платформы, ну а маркетингу понравились чиселки, поэтому они сказали, что в принципе дотнет такой быстрый, хотя как бы не вчитываясь в то, кто же там быстрый. -820.84 821.84 SPEAKER_02 Вот. -821.84 858.84 SPEAKER_02 В целом, как бы вроде все более-менее остались, ну назовем это довольны, в том смысле, что вроде и статья по делу разбор и дотнет команда как бы сказала, что ну да, типа окей, вот, но дальше эта статья еще была опубликована на рейтите, ну ссылка на нее, и там в комментах пришел товарищ, который написал прям шикарнейший коммент, который говорит, ну хорошо, как бы спасибо автору, он действительно прав, что дотнет как бы чедерит, а давайте посмотрим внимательно на другие языки. -858.84 867.40 SPEAKER_02 Ну то есть как бы Go, например, который действительно использует раутинг, действительно использует темплейты, зато делает другие штуки. -867.40 906.76 SPEAKER_02 Например, он предполагает, что записи в банке, например, в базе данных, помните, я говорил, что там типа 12 штук запрашивается из BD, вот он приаллокейтит, грубо говоря, там 15 или сколько-то структур и их переиспользует на каждый запрос, ну то есть типа заполняет их заново каждый раз, из BD не аллокейти новые, то есть фактически у него не работает garbage collector вообще, а дотнет честно делает new list, ну со всей логикой удвоения размеров внутри, пока мы туда запихиваем 12 записей, он там 2 раза, по-моему, успевает удвоиться, ну то есть надо было тогда у нас тоже писать new list от 15 и желательно в статическом поле его переиспользовать. -906.76 930.08 SPEAKER_02 Потом опять же, в go template, вот этот механизм шаблонов, который там использован, библиотека, она в compile time превращает шаблон в исполняемый код, то есть по сути некоторый аналог string builder, то есть ты пишешь, конечно, шаблон, но в результате в runtime делается исполняемый код, это неплохо, почему нет, если такой язык шаблонов в дотнете, наверное, тоже можно такое написать. -930.08 936.08 SPEAKER_00 Ну t4 так делает, например, он может, в design time ты пишешь template, а во время компиляции он прямо из него код генерирует. -936.08 941.44 SPEAKER_02 Да, то есть как бы, но там условия benchmark соблюдены, template engine используется. -941.44 952.24 SPEAKER_02 Там раутер, который они используют, fastrtpt, он там типа не полностью rstpt compliant, он там на некоторые заголовки реагирует неправильно, ну и че, цель достигнута. -952.24 962.80 SPEAKER_02 Там высокие результаты Python и PHP объясняются тем, что почти все там работает на стандартной библиотеке, на сях на самом деле, и на питоне ты пишешь там типа это, вызов этой библиотеки и все. -962.80 974.12 SPEAKER_02 То есть фактически на самом деле во всех этих бенчмарках, на любой платформе есть куча читинга, ну такого как бы, не то чтобы читинга, но непонятно на самом деле в чем и мере, в общем-то. -974.12 985.80 SPEAKER_02 То есть это как бы хорошее упражнение попробовать соптимизировать те или иные сценарии, но они очень нишевые и фактически в реальной жизни таких чисел вы, конечно, не получите. -985.80 990.24 SPEAKER_02 Ну и на Java вы пишете на Springeo скорее всего, который не такой что бы быстрый. -990.24 991.24 SPEAKER_02 Вот. -991.24 1007.68 SPEAKER_02 Так же как и на дотнете вы пишете, да, на полноценном большом фреймворке и только если у вас совсем большие требования по производительности, например, вы пишете какой-нибудь proxy, тогда, наверное, вы, конечно, все сделаете на middleware и не будете контроллеры дергать, они вам там не нужны и только все замедлит. +197.28 226.76 "Игорь Лабутин" Мы говорим про бенчмарки, которые называются Tech Empower, довольно известная штука, там есть огромное количество всяких разных бенчмарков, которые проверяют и то, и это, и смысл в том, что они запускают эти самые бенчмарки у себя на серверах, то есть регулярно, но регулярность у них, она такая как бы непонятная, последний официальный раунд 21-й был в июле 22-го года, а до этого в феврале 21-го, ну не то, чтобы очень регулярно, но будем считать, что так. +226.76 283.64 "Игорь Лабутин" Конкретно про бенчмарки, которые нас интересуют, даже не которые нас интересуют, а которые хоть как-то могут относиться к SPNetCore, они относятся к куче категорий, есть там бенчмарки про JSON Serializers, про Single Query, Multiple Query, Caching Query, бенчмарк под названием Fortune's, ну и там несколько других, и вот как раз-таки Fortune's - это то, что является более-менее таким, то, что он называет Gold Standard в бенчмарках, именно в веб-фреймворках, потому что он более-менее пытается воспроизвести, что происходит в реальной жизни с вашим приложением, то есть в этом бенчмарке мы читаем из базы данных, сортируем данные, потом добавляем какой-то там заголовочек для всяких XSS, предотвращения XSS, и даже делаем небольшой сервер-сайт, значит, HTML-рендеринг на основе шаблонов, ну вроде как такое, обычное веб-приложение более-менее. +283.64 296.92 "Игорь Лабутин" Понятно, что там не гигантские данные, поскольку это бенчмарк, то он запускается там много-много-много раз, поэтому из базы данных по-моему там читается типа 12 записей или около того, но смысл в том, что все равно тестируются какие-то кусочки фреймворка. +296.92 302.00 "Игорь Лабутин" Итак, давайте, говорит автор, посмотрим на результаты SPNetCore. +302.00 319.92 "Игорь Лабутин" Находит он, если мы берем, значит, рейтинг топ всяких фреймворков, он находит там три записи с названием SPNetCore, это ASP.Core.ado, Postgres, ASP.Core.mw, Postgres и ASP.NetCore. +319.92 320.92 "Игорь Лабутин" Ну вроде как три. +320.92 324.52 "Игорь Лабутин" Они занимают, соответственно, 9, 13 и 14 места, ну вроде неплохо. +324.52 330.84 "Игорь Лабутин" Но если посмотреть полную таблицу, выясняется, что всего существует 15 разных ASP.NetCore бенчмарков. +330.84 338.52 "Игорь Лабутин" Они основаны, поскольку мы читаем из базы данных, то они основаны некоторые на Postgres, некоторые на MySQL. +338.52 343.16 "Игорь Лабутин" Мы выкидываем те, которые про MySQL, потому что они точно медленнее, чем те, которые Postgres, видно по результатам. +343.16 345.28 "Игорь Лабутин" Некоторые из них основаны на Mono. +345.28 349.44 "Игорь Лабутин" Mono мы тоже сейчас выкидываем, потому что мы же говорим про релиз 7-го дотнета. +349.44 358.44 "Игорь Лабутин" И остается у нас 7 штук, то есть 7 бенчмарков, которые все используют Postgres, и они классифицируются дальше на еще несколько категорий. +358.44 363.20 "Игорь Лабутин" Самый топовый, который самый крутой, он классифицирован как Platform. +363.20 371.68 "Игорь Лабутин" Следующие 3 классифицированы как Micro, и еще 3 более медленных классифицированы как Full. +371.68 379.60 "Игорь Лабутин" Причем эта классификация не является каким-то стандартом, который техэмпауэр, это просто некоторые теги, которые автор бенчмарка может навесить. +379.60 383.88 "Игорь Лабутин" Ну вот так оно классифицируется, почему нет. +383.88 392.48 "Игорь Лабутин" Если посмотреть на топовый бенчмарк, он говорит, ну давайте мы разберем, что же там в этом топовом бенчмарке, как мы так всех уделываем в 10 и больше раз. +392.48 401.84 "Игорь Лабутин" Сама дотнетим, команда дотнетком, считает этот бенчмарк, точнее один из тегов, который навешан на этот бенчмарк, называется реалистик. +401.84 413.44 "Игорь Лабутин" И он говорит, ну автор говорит, давайте, открываем код, смотрим, и приводит в структуру проекта, и в том числе скриншотик кода из программ ЦС. +413.44 418.56 "Игорь Лабутин" Он говорит, ну что тут, из знакомого из PanadCore тут только слово kestrel, ну типа use kestrel. +418.56 421.68 "Игорь Лабутин" Больше там нет ничего знакомого из ISP-PanadCore. +421.68 431.24 "Игорь Лабутин" Для того, чтобы этот бенчмарк был таким супер быстрым, там применено огромное количество оптимизаций. +431.24 441.84 "Игорь Лабутин" Там нету строчек вообще, ну точнее, строчки вы в коде увидите, но они сразу передаются в класс под названием ASCIIString, который внутри их тут же конвертит первым делом в момент инстализации в byte array. +441.84 450.60 "Игорь Лабутин" То есть это делается один раз за жизнь программы, и дальше эти строчки все собираются в ответы HTTP, без, понятно, конвертации, дальше в байты. +450.60 452.12 "Игорь Лабутин" Сразу из byte array собираются ответы. +452.12 465.84 "Игорь Лабутин" Все части заголовков HTTP-шных тоже сразу вычисляются в байтах и записываются, значит, грубо говоря, в переменные, которые живут все время жизни программы. +465.84 467.80 "Игорь Лабутин" Раутинг сделан очень круто. +467.80 469.20 "Игорь Лабутин" Раутинг сделан следующим образом. +469.20 472.48 "Игорь Лабутин" Мы получаем реквест напрямую от kestrel. +472.48 484.72 "Игорь Лабутин" Мы берем path в url и проверяем, условно говоря, если девятый символ в рауте равен c, то это точно не fortunes. +484.72 487.64 "Игорь Лабутин" Там есть несколько стандартных endpoint, по которым должны отвечать бенчмарки. +487.64 499.40 "Игорь Лабутин" Ну и понятно, что если учитывать, что их конечное количество, то можно написать довольно оптимальный алгоритм, который, проверяя 1-2 символа всего лишь, точно узнает, какой из этих стандартных endpoint был вызван. +499.40 507.16 "Игорь Лабутин" То есть это нифига не полноценный раутинг, это вот такой очень специфически заточенный под это benchmark раутинг. +507.16 512.16 "Игорь Лабутин" Никакого там html контекста, вообще из span-add-core только kestrel, больше ничего нет. +512.16 520.88 "Игорь Лабутин" Пишем мы все это напрямую в pipewriter, то есть это тоже, опять же, ну если не socket, то очень близко с kestrel. +520.88 526.44 "Игорь Лабутин" Никаких html-темплейтов, напоминаю, что бенчмарки подразумевают какой-то сервер-сайт html-темплейт-рендеринг. +526.44 531.48 "Игорь Лабутин" Никаких там html-темплейтов, типа rather-pages или rather-views нет. +531.48 536.24 "Игорь Лабутин" Зато мы с stringbuilder собираем строчку ответа и ее фигачим в ответ. +536.24 540.52 "Игорь Лабутин" И самая крутая оптимизация это с датой. +540.52 546.72 "Игорь Лабутин" По стандарту этого бенчмарка, по описанию, мы обязаны отправить в ответ хедер с датой. +546.72 549.72 "Игорь Лабутин" Ну типа там, текущая дата такая-то. +549.72 557.76 "Игорь Лабутин" По стандарту, опять же, http, эта дата отправляется без миллисекунд, то есть там точность секунда в этой дате. +557.76 564.44 "Игорь Лабутин" Поэтому команда span-add-core, точнее, команда, которая писала этот бенчмарк, сделала следующую прекрасную штуку. +564.44 573.68 "Игорь Лабутин" У нас есть код, который заполняет значение этого заголовка, даты текущие, в ответ, в response-header. +573.68 576.84 "Игорь Лабутин" Он туда берет значение статической переменной. +576.84 586.60 "Игорь Лабутин" И есть отдельный тред, который эту статическую переменную, там строчка, сразу, периодически раз в секунду обновляет новым значением текущего даты времени. +586.60 591.28 "Игорь Лабутин" Ну вызывает dateTime.utcNow.toString один раз в секунду в багграундном треде. +591.28 602.40 "Игорь Лабутин" И это прям сильно повышает производительность, потому что понятно, что мы за секунду обслуживаем, не знаю, тысячи реквестов, и даже сотни тысяч реквестов. +602.40 609.20 "Игорь Лабутин" И понятно, что вместо того, чтобы вызывать utcNow.toString на каждом, мы это делаем один раз в секунду всего лишь и кэшируем это значение. +609.20 611.92 "Анатолий Кулаков" Ну действительно реалистик, что уж говорить, каждый +611.92 615.24 "Игорь Лабутин" день так и пишу. Да, реалистик, так реалистик. +615.24 624.56 "Игорь Лабутин" Если посмотреть на код микробенчмарков, вот три следующих, которые чуть более тормозные, они уже ну поближе к SPNetCore. +624.56 643.40 "Игорь Лабутин" Там все еще нет раутинга полноценного, и не то, что ML-темплейтов, там все еще StringBuilder, но там уже нормальная типа middleware, которая просто, ну по сути там все сделано на одной middleware, то есть middleware проверяет, что если путь содержит fortunes, то надо в shtp-контекст.response послать соответствующую строчку ответа. +643.40 650.08 "Игорь Лабутин" То есть там уже есть shtp-контекст, все дела, но никакого там контроллеров, фразеров, вот этого всего нет. +650.08 664.60 "Игорь Лабутин" Ну и полный benchmark, да там все как положено, все как мы знаем и любим, это контроллеры, reserview, все такое прочее, но он уже не 9, там 13 или 14, а он 109 в рейтинге. +664.60 674.68 "Игорь Лабутин" И он успевает обслуживать, тем не менее, 109 эта штука обслуживает 184 тысячи реквестов в секунду. +674.68 681.52 "Игорь Лабутин" То есть вообще говоря, числа, в абсолютном понимании числа неплохие, мы все равно все еще достаточно быстрые. +681.52 689.48 "Игорь Лабутин" Но далеко не на первом месте, ну и там не в десятке, назовем это так, а всего лишь 109. +689.48 696.68 "Игорь Лабутин" Он говорит, окей, давайте посмотрим на другие языки, может быть другие языки тоже там все четерят и делают неправильно. +696.68 724.64 "Игорь Лабутин" Он говорит, ну берем java, там, ну там конечно не spring, там где-то в тормозах, где-то глубоко внизу, но у java есть более легковесный раутинг и прочее, что такое, значит, такие сервера, и он на нормальном, как бы одном из таких серверов, он 12 из 400 тысяч реквестов в секунду, тут напоминаю 184, то есть типа в 2 раза быстрее на java можно написать. +724.64 739.72 "Игорь Лабутин" В go тоже 22 место и 381 тысяча, ну плюсы на первом месте 616 тысяч реквестов в секунду, как бы их сложно побить, поэтому говорить, что мы там быстрее c++, ну это как-то странно, мы не быстрее c++. +739.72 754.52 "Игорь Лабутин" Вот, а остальные языки тоже на самом деле не так все плохо, то есть и Rust, и Kotlin, и Node.js, и PHP, они все есть, Node.js только помедленнее на 100% в любом варианте, а остальные языки в разумной реализации вроде есть выше нас. +754.52 789.20 "Игорь Лабутин" И вывод из статьи такой, что ну блин, короче, полная фигня, как бы это все маркетологи врут, сп.netcore не такой быстрый, при том, что товарищ на самом деле пишет очень хорошо, он говорит, что типа при этом не надо винить в этом команду, ну в смысле это не команда такая плохая, что они вот так вот рекламируются, это как бы маркетинг увидел такие чиселки и решил, что да, скажем, что .net такой быстрый, хотя цель команды была в том, чтобы показать, на что способна платформа, если написать, ну если грубо говоря вы захотите написать там, не знаю, фреймворк новый поверх кестрила, то что вам может дать кестрил? +789.20 796.28 "Игорь Лабутин" Именно поэтому он обозван как платформ, то он реалистик, но он платформ, то есть типа на что способна вот платформ в смысле кестрила? +796.28 798.40 "Игорь Лабутин" И все ни жили раще. +798.40 820.84 "Игорь Лабутин" Вот Дэвид Фаулер в твиттере отреагировал на все это дело и как раз сказал, что ну да, типа вот мы вот так хотели, это как раз были его слова про то, что мы хотели показать, насколько быстро вы можете построить что-нибудь поверх собственно основной платформы, ну а маркетингу понравились чиселки, поэтому они сказали, что в принципе дотнет такой быстрый, хотя как бы не вчитываясь в то, кто же там быстрый. +820.84 821.84 "Игорь Лабутин" Вот. +821.84 858.84 "Игорь Лабутин" В целом, как бы вроде все более-менее остались, ну назовем это довольны, в том смысле, что вроде и статья по делу разбор и дотнет команда как бы сказала, что ну да, типа окей, вот, но дальше эта статья еще была опубликована на рейтите, ну ссылка на нее, и там в комментах пришел товарищ, который написал прям шикарнейший коммент, который говорит, ну хорошо, как бы спасибо автору, он действительно прав, что дотнет как бы чедерит, а давайте посмотрим внимательно на другие языки. +858.84 867.40 "Игорь Лабутин" Ну то есть как бы Go, например, который действительно использует раутинг, действительно использует темплейты, зато делает другие штуки. +867.40 906.76 "Игорь Лабутин" Например, он предполагает, что записи в банке, например, в базе данных, помните, я говорил, что там типа 12 штук запрашивается из BD, вот он приаллокейтит, грубо говоря, там 15 или сколько-то структур и их переиспользует на каждый запрос, ну то есть типа заполняет их заново каждый раз, из BD не аллокейти новые, то есть фактически у него не работает garbage collector вообще, а дотнет честно делает new list, ну со всей логикой удвоения размеров внутри, пока мы туда запихиваем 12 записей, он там 2 раза, по-моему, успевает удвоиться, ну то есть надо было тогда у нас тоже писать new list от 15 и желательно в статическом поле его переиспользовать. +906.76 930.08 "Игорь Лабутин" Потом опять же, в go template, вот этот механизм шаблонов, который там использован, библиотека, она в compile time превращает шаблон в исполняемый код, то есть по сути некоторый аналог string builder, то есть ты пишешь, конечно, шаблон, но в результате в runtime делается исполняемый код, это неплохо, почему нет, если такой язык шаблонов в дотнете, наверное, тоже можно такое написать. +930.08 936.08 "Анатолий Кулаков" Ну t4 так делает, например, он может, в design time ты пишешь template, а во время компиляции он прямо из него код генерирует. +936.08 941.44 "Игорь Лабутин" Да, то есть как бы, но там условия benchmark соблюдены, template engine используется. +941.44 952.24 "Игорь Лабутин" Там раутер, который они используют, fastrtpt, он там типа не полностью rstpt compliant, он там на некоторые заголовки реагирует неправильно, ну и че, цель достигнута. +952.24 962.80 "Игорь Лабутин" Там высокие результаты Python и PHP объясняются тем, что почти все там работает на стандартной библиотеке, на сях на самом деле, и на питоне ты пишешь там типа это, вызов этой библиотеки и все. +962.80 974.12 "Игорь Лабутин" То есть фактически на самом деле во всех этих бенчмарках, на любой платформе есть куча читинга, ну такого как бы, не то чтобы читинга, но непонятно на самом деле в чем и мере, в общем-то. +974.12 985.80 "Игорь Лабутин" То есть это как бы хорошее упражнение попробовать соптимизировать те или иные сценарии, но они очень нишевые и фактически в реальной жизни таких чисел вы, конечно, не получите. +985.80 990.24 "Игорь Лабутин" Ну и на Java вы пишете на Springeo скорее всего, который не такой что бы быстрый. +990.24 991.24 "Игорь Лабутин" Вот. +991.24 1007.68 "Игорь Лабутин" Так же как и на дотнете вы пишете, да, на полноценном большом фреймворке и только если у вас совсем большие требования по производительности, например, вы пишете какой-нибудь proxy, тогда, наверное, вы, конечно, все сделаете на middleware и не будете контроллеры дергать, они вам там не нужны и только все замедлит. 1007.68 1008.68 None Вот. -1008.68 1031.72 SPEAKER_02 Так что для каждой, для каждого подхода к своей задачке, но интересно вот так вот почитать, что народ думает и что же вот тот самый техэмпауэр, в который все верят и говорят, о, техэмпауэр, мы заняли какое-то n-ное место, на самом деле надо внимательно смотреть, с каким бенчмарком вы заняли и какое из 15 мест, какое из 15 ваших бенчмарков. -1031.72 1038.56 SPEAKER_00 И что в это время еще там делали другие и как читерили они и вообще все вместе как это юзабельно. -1038.56 1052.16 SPEAKER_00 Да, действительно, когда начинаешь работать ради цифр, когда в твоих метриках устанавливаются какие-то критерии, какие-то чиселки, то начинаешь работать на чиселке, а не на то, чтобы сделать хорошо свою работу. -1052.16 1061.24 SPEAKER_00 Так вот типичное доказательство и здесь, когда тебе выставили какой-то бенчмарк, то ты делаешь фреймворк для того, чтобы пройти бенчмарк, а не для того, чтобы сделать быстрый фреймворк. -1061.24 1063.80 SPEAKER_00 Это грустно, конечно, друзья. -1063.80 1070.52 SPEAKER_00 Надеюсь, что все-таки мы дойдем до каких-нибудь нормальных циферок с нормальным реалистик кодом, чтобы было не стыдно. -1070.52 1074.64 SPEAKER_02 Ну слушай, 184 тысячи реквестов в секунду, мне кажется, -1074.64 1075.64 SPEAKER_01 не так, чтобы стыдно. -1075.64 1088.80 SPEAKER_00 Это неплохо, да, безусловно, неплохо, но опять же, хотелось бы точно такой же подход сравнить и на других языках, то есть с точно таким же уровнем плейнинга, таким же уровнем роутинга, в общем, как-то научиться это все хотя бы близко подгонять по функциональности. -1088.80 1093.42 SPEAKER_02 Ну языки настолько разные, что боюсь, что прям идеально подогнать не сможем. -1093.66 1097.90 SPEAKER_00 Да ладно, для Java странно скомпилируется один в один просто. -1097.90 1105.06 SPEAKER_02 Нет, Java, да, я согласен, то есть там, грубо говоря, ну там спринговая есть наверняка реализация, я не смотрел, где она там находится, но наверняка есть. -1105.06 1109.94 SPEAKER_02 То есть понятно, что нужно сравнивать, грубо говоря, мейнстрим, там, дотнета с мейнстримом Java, но… -1109.94 1112.82 SPEAKER_00 Да, то есть действительно, что люди переиспользуют каждый день. -1112.82 1118.22 SPEAKER_00 Вот взять прям по процентам, и мы видим, что там 90% всех ASP приложений, то есть всех веб-приложений – это ASP.NET. -1118.22 1124.10 SPEAKER_00 Вот значит, и в Java берем там 100% всех веб-приложений – это Spring, и погнали значит их сравнивать. -1124.10 1127.98 SPEAKER_00 И вот это должно более-менее дать какую-то реалистику картину. -1127.98 1129.98 SPEAKER_02 Ну, наверное, да. -1129.98 1131.98 SPEAKER_02 Ладно, давай дальше. -1131.98 1132.98 SPEAKER_02 Да, давай. -1132.98 1134.58 SPEAKER_00 У нас сегодня много тем. -1134.58 1144.14 SPEAKER_00 Не отходя далеко от веба, интересная статья тут есть про рассуждение немножко про Minimal API, нафига он вообще нужен, и зачем он появился, и как его можно использовать. -1144.14 1150.82 SPEAKER_00 Вот ты как думаешь, Minimal API нам все еще нужен, или это была неудачная попытка, и можно его закапывать? -1150.82 1164.30 SPEAKER_02 Знаешь, я в работе им, так скажем, не пользуюсь, а в целом я вполне, наверное, одобряю, что он есть, но я пока не понимаю, как я его буду использовать. -1164.30 1171.54 SPEAKER_02 То есть вот я, это должны быть совсем минимальные какие-то компоненты, а я небольшой любитель прямо микро-микросервисов. -1171.54 1174.30 SPEAKER_02 То есть я скорее любитель просто сервисов. -1174.30 1175.30 SPEAKER_02 Трех рутов, да? -1175.30 1176.30 SPEAKER_02 Да-да-да. -1176.30 1185.22 SPEAKER_02 То есть нет, если по какой-то логике деление, мне понадобится сделать сильно маленький сервис с одним endpoint, то наверное да, я возьму Minimal API. -1185.22 1186.22 SPEAKER_02 Почему нет? -1186.22 1187.22 SPEAKER_02 Вот. -1187.22 1202.14 SPEAKER_02 И я так понимаю, что одна из целей вот этого Minimal API была попытка собрать что-то, что не так завязано нам огромную магию рефлексии контроллеров, и вот этого всего огромного хозяйства под названием MVC. -1202.14 1212.54 SPEAKER_00 Может быть, но видишь, смотря на развитие Minimal API, особенно в последнем дотнете, который недавно зарелизался, невольно начинаешь наблюдать, что вся эта магия рефлексии проникает туда. -1212.54 1221.38 SPEAKER_00 То есть ты легко можешь заинжектировать туда любой сервис в скобочке какой захочешь, а логерю можно засунуть те же самые тайп-мароты, http-контексты и это все. -1221.38 1226.10 SPEAKER_00 То есть точно такая же рефлексия, только не через контроллер к тебе придет, а через делегат. -1226.10 1227.10 SPEAKER_00 Ну кажется, какая разница. -1227.10 1229.02 SPEAKER_02 Ну может быть, может быть. -1229.02 1238.02 SPEAKER_02 В общем, для чего-то это точно делается, есть какие-то use-case, я пока для себя их не нашел, но у меня, видимо, и сценарий пока не подходящий. -1238.02 1249.02 SPEAKER_00 Ну да, тема мутная, вот чтобы ее немножко прояснить, давайте попробуем обратиться к одному из авторов, который примерно понимает, как это использовать, зачем это нужно и как это применить. -1249.02 1256.02 SPEAKER_00 Самое главное, не в каких-то hello world, которые вы хотите показать студенту в одном файлике, а в более-менее нормальных продакшн-системах. -1256.02 1265.82 SPEAKER_00 И статья как раз-таки называется тоже довольно интересно, а не пора ли нам передумать структуру наших проектов с новым дотнетом. -1265.82 1268.58 SPEAKER_00 Давайте посмотрим, что же здесь можно передумать. -1268.58 1270.58 SPEAKER_00 Для тех, кто пропустил, начнем с начала. -1270.58 1278.14 SPEAKER_00 Во времена дотнет 6 вышла такая прекрасная штука, новый API, который называется minimal web API. -1278.14 1289.42 SPEAKER_00 Этот специальный способ, назовем его так, позволяет вам писать, обрабатывать web-реквесты, возвращать web-респонсы и все это делать абсолютно без контроллеров. -1289.42 1292.46 SPEAKER_00 Кажется, что это единственная фишка избежать контроллеров. -1292.46 1300.66 SPEAKER_00 Почему они захотели этого избежать, то есть действительно ли контроллеры такие медленные, или такие большие, или такие некрасивые, то есть вот это никакой предпосылки не было. -1300.66 1303.90 SPEAKER_00 Просто команда села и сказала, вот смотрите, как мы умеем миленько писать. -1303.90 1321.50 SPEAKER_00 С тех самых пор вкладывается огромное количество усилий в minimal API, добавляются различные методы расширения, подключается там аутентификация, авторизация, подключается dependency injection, прочие там навешиваются свагерские атрибуты и в общем он превращается в полноценную замену подхода с контроллерами. -1321.50 1332.82 SPEAKER_00 А разница казалось бы практически минимальная, та же самая однострочка с кучей атрибутов и с кучей fluent интерфейсов заменялась бы просто-напросто одним контроллером с теми же самыми атрибутами. -1332.82 1335.50 SPEAKER_00 То есть разница чисто техническая. -1335.50 1337.46 SPEAKER_00 Другой пока нам не приводили. -1337.46 1339.50 SPEAKER_00 Ну будем работать с тем, что есть. -1339.50 1351.10 SPEAKER_00 И даже если новый шаблон раньше создавали в бета-версиях первых .NET, то по умолчанию он использовал minimal API, ISP.NET template использовал minimal API. -1351.10 1360.94 SPEAKER_00 Сам от этой идеи откатились, вроде начали генерить большой нормальный стандартный, но периодически возвращаются и может быть даже официально вернутся к этому подходу. -1360.94 1381.66 SPEAKER_00 Если же мы используем minimal API template ISP.NET, в то же самое время к нам прилетает сразу top-level statement, то есть у нас нет никакого program, класса program, у нас сразу файл начинается с того, что у нас появляется application builder и мы погнали там строить web application и мапить ему всякие роуты. -1381.66 1386.42 SPEAKER_00 И буквально там из пяти строчек мы можем собрать полноценный веб-сервер. -1386.42 1392.54 SPEAKER_00 И самое интересное в этом minimal API будет, это как раз маппинг этих роутов. -1392.54 1401.10 SPEAKER_00 То есть мы там можем писать map get, передать туда роут, по которому мы хотим, чтобы наш делегат вызывался и передать непосредственно сам делегат. -1401.10 1405.58 SPEAKER_00 То есть что будет происходить, когда к нам придет запрос, например, вернуть фразу hello world. -1405.58 1407.82 SPEAKER_00 Этого в принципе вполне достаточно. -1407.82 1419.06 SPEAKER_00 Вот из таких вот делегатиков, даже я бы сказал пар, роут плюс делегатик, плюс обработчик входящего запроса и состоит minimal API. -1419.06 1427.30 SPEAKER_00 Дальше идут небольшие усложнения, там навешивается, как я уже сказал, интерфейсом или атрибутом всяким возможностям, но суть его остается на месте. -1427.30 1440.90 SPEAKER_00 При этом с новым подходом, с minimal API и top-level statement у нас нет program.cs, у нас нет startup.cs, у нас нет методов, которые конфигурируют сервисы, у нас нет папочки с контроллерами, в которых лежит куча контроллеров. -1440.90 1444.86 SPEAKER_00 У нас там есть один единственный файлик, в который можно войти и все это написать. -1444.86 1447.14 SPEAKER_00 Кажется красиво, мило и прекрасно. -1447.14 1453.90 SPEAKER_00 Но теперь давайте рассуждать в терминах как раз-таки нормальной реалистичной разработки. -1453.90 1457.22 SPEAKER_00 Что будет, если мы захотим добавить туда новую функциональность? -1457.22 1462.30 SPEAKER_00 Допустим, мы хотим добавить новый контроллер, новый обработчик, новый роут. -1462.30 1476.06 SPEAKER_00 По идее самый легкий способ, самый очевидный способ, который нас все подталкивает, это просто-напросто пойти в файлик program.cs, найти там вот этот наш web-аппликейшен и добавить к нему еще один map.get. -1476.06 1480.90 SPEAKER_00 Передать туда еще один роут и передать туда еще один делегат и вот таким образом накидывать новые фичи. -1480.90 1492.70 SPEAKER_00 Это очень просто, это очень понятно, но легко представить, что если у нас там будет большое число уже роутов, если их там будет десятки и может быть сотни, то этот файлик превратится в жуткое месиво. -1492.70 1500.94 SPEAKER_00 Он будет мега грязным, он будет очень неподдержанным, он будет абсолютно неразборчивым и ничего там разобрать будет невозможно и работать с этим, поддерживать это никак нельзя будет. -1500.94 1509.86 SPEAKER_00 В то же самое время, если бы у нас были контроллеры, то у нас там было бы 10 контроллеров по 10 методов и вполне реально такие проекты живут и даже намного больше. -1509.86 1521.06 SPEAKER_00 И поэтому люди, смотрящие после настоящего production кода на вот это издевательство, они туда не очень лезут, в этот minimal API. -1521.06 1526.34 SPEAKER_00 Другой подход, если нам нужно добавить новую кейт-фичу, это все-таки вернуться к нашим старым контроллерам. -1526.34 1532.78 SPEAKER_00 Для этого нам понадобится в билдере всего лишь на все вызвать метод addControllers, который наверняка во многих ваших проектах уже есть. -1532.78 1538.22 SPEAKER_00 И все, контроллеры будут знакомые, интересные и ими можно будет продолжать пользоваться так же, как и раньше. -1538.22 1544.14 SPEAKER_00 Но у контроллеров автор выделяет две очень большие проблемы, которые он видит. -1544.14 1554.02 SPEAKER_00 Во-первых, это то, что контроллеры группируются по техническому уровню абстракции, то есть так называемому не feature concern, а technical concern. -1554.02 1572.50 SPEAKER_00 Когда мы в папочке с контроллерами храним отдельно контроллеры, в папочке с бизнес-моделями храним бизнес-модели, может быть даже вы видели, что у некоторых есть папочка интерфейс, они там хранят интерфейсы, в папочке с enum'ами - enum'чики, в папочке с делегатиками - делегатики и прочие вот такие глупости. -1572.50 1578.38 SPEAKER_00 И в этом есть проблема, мы ее осмотрим немножко попозже. -1578.38 1595.26 SPEAKER_00 И вторая проблема это в том, что несмотря на то, что ваш запрос может быть очень простым, допустим по какому-то простому роту вернуть hello world или более приземленный пример, это по статическому, то есть по понятному константному url health-чека, вернуть ответ, что да, сервис жив. -1595.26 1608.42 SPEAKER_00 В общем, очень простая ситуация, очень элементарная, но для того, чтобы ее реализовать, вам нужно будет добавить в контроллер, вам нужно добавить action-метод, навесить там каких-то атрибутов, сделать там какой-нибудь return action result, еще что-то. -1608.42 1612.34 SPEAKER_00 В общем, слишком много действий приходится делать для каких-то примитивных случаев. -1612.34 1621.50 SPEAKER_00 То есть сложные вещи в контроллерах делаются сложно, это нормально, но легкие вещи там тоже делаются сложно, и вот это уже не очень нормально. -1621.50 1625.62 SPEAKER_00 В этом заключается вторая проблема, которую автор видит как раз-таки в контроллерах. -1625.62 1630.94 SPEAKER_00 А теперь давайте посмотрим, что же он предлагает, как он предлагает все эти дилеммы, все эти проблемы решить. -1630.94 1634.98 SPEAKER_00 Итак, прежде всего вернемся к нашему technical concern. -1634.98 1648.54 SPEAKER_00 Автор предлагает забросить традиционную модель директорий, про которую я уже чуть выше упоминал, и перевести ее из технологического аспекта более в структуру доменного моделирования. -1648.54 1661.06 SPEAKER_00 То есть сгруппировать наши папочки не по той функции, которую они выполняют, не по интерфейсам, контроллерам и моделям, а сгруппировать их по доменам. -1661.06 1677.70 SPEAKER_00 Группировка по доменам очень распространена, когда вы пишете domain layer, особенно если вы придерживаетесь DDD, вот там всегда domain layer обычно внутри себя содержит папочки именно с тем контекстом, который конкретно используется для определенных бизнес-моделей. -1677.70 1679.74 SPEAKER_00 Также можно сделать и здесь. -1679.74 1687.34 SPEAKER_00 То есть когда различные домены приложения превращаются в некую структуру папок. -1687.34 1692.26 SPEAKER_00 И эти папки обычно называют фичами или также можно их назвать модулями. -1692.26 1693.26 SPEAKER_00 Приведем пример. -1693.26 1699.58 SPEAKER_00 Вместо контроллеров в вашем приложении появляется папочка, которая называется modulus. -1699.58 1713.26 SPEAKER_00 И внутри этого модуля папочки, которые, например, для магазина могут называться корзина, могут называться заказы, какой-нибудь чек-аут, какой-нибудь юзер менеджмент или кабинет пользователя. -1713.26 1717.10 SPEAKER_00 В общем, эти папочки делятся как раз по функциональности, что они делают. -1717.10 1721.02 SPEAKER_00 И внутри этой папочки уже находится абсолютно все, что нужно. -1721.02 1730.50 SPEAKER_00 Например, для того, чтобы работала корзина, нам нужен какой-нибудь модель этой корзины, нам нужны какие-то валидаторы этой корзины, какие-нибудь серилизаторы этой корзины и так далее. -1730.50 1732.18 SPEAKER_00 Все это находится внутри одной папочки. -1732.18 1741.46 SPEAKER_00 Вот именно в этом и заключается вся суть этого фичи фолдеров или модуль фолдеров. -1741.46 1745.18 SPEAKER_00 Внутри такая папочка, как я уже сказал, называется в этих терминах модуль. -1745.18 1747.38 SPEAKER_00 Давайте же посмотрим, из чего состоит модуль. -1747.38 1753.30 SPEAKER_00 Прежде всего модуль состоит из файла, который регистрирует все зависимости, которые здесь есть. -1753.30 1760.06 SPEAKER_00 В этом файле добавляются необходимые классы в DI контейнер. -1760.06 1762.02 SPEAKER_00 То есть у него в этом файле есть два метода. -1762.02 1772.62 SPEAKER_00 Первый метод добавляет все классы в DI контейнер, а второй метод как раз прописывает руты у нашего минималпиа, то есть маппит все эти руты с делегатиками. -1772.62 1788.14 SPEAKER_00 То есть обзаведясь одним этим файлом, мы таким образом разделили все наши сотни делегатов, которые я приводил в начале, мы их разделили на 10 таких модулей, которые относятся к своему домену. -1788.14 1789.82 SPEAKER_00 У каждого модуля будет всего-навсего 10 маппингов. -1789.82 1797.22 SPEAKER_00 Это уже более чисто, это уже легко поддерживать, а само деление на модули дает нам очень хорошую например тестируемость. -1797.22 1804.50 SPEAKER_00 Для того, чтобы протестировать какой-то класс корзины, мы уже не должны потаскивать все приложения, регистрировать там какие-то непонятные зависимости. -1804.50 1813.62 SPEAKER_00 Мы просто берем вот этот классик с регистрацией корзины, вызываем у него метод зарегистрировать DI контейнер, вызываем метод зарегистрировать руты и все. -1813.62 1816.66 SPEAKER_00 И мы можем уже полноценно взаимодействовать с рутами корзины. -1816.66 1820.62 SPEAKER_00 Независимо от ничего другого, потому что он самодостаточен и полноценный. -1820.62 1826.22 SPEAKER_00 И также в этом модуле очень легко удалять ненужные вещи. -1826.22 1829.38 SPEAKER_00 Понадобился нам какой-то рут, мы его туда добавили в одном индейценном понятном месте. -1829.38 1831.50 SPEAKER_00 Не понадобился - удалили. -1831.50 1844.50 SPEAKER_00 Далее мы идем в наш программ.cs, в билдере подключаем эти модули с помощью метода register module, в аппликейшене подключаем все маппинги с помощью mapping points. -1844.50 1856.14 SPEAKER_00 И мы получаем как раз таки довольно чистый, хороший, понятный программ.cs, который просто-напросто подключает вот эти доменные модули, а в каждом отдельном модуле у нас уже распространена какая-то логика. -1856.14 1868.42 SPEAKER_00 Если у нас есть какая-то функциональность, которая нужна всем модулям, там логирование, аутентификация, какие-то middleware, те же самые свагеры, их можно для начала вставить в программ.cs, если будет нужно, просто вынести в какой-то отдельный классик. -1868.42 1873.78 SPEAKER_00 Не суть важна, у нас сейчас самая главная тема понять это вот эти вот самые модули. -1873.78 1882.46 SPEAKER_00 Естественно эти модули элементарно регистрировать автоматически, чтобы не ходить, не вызывать определенные методы, di-контейнера, mapping-routes. -1882.46 1890.26 SPEAKER_00 Мы просто можем Reflection просканировать текущую assembly, выяснить все классы, которые наследуются от маркеров, от специального интерфейса imodule. -1890.26 1902.90 SPEAKER_00 У этого интерфейса можно два метода те же самые сделать, зарегистрировать классики, зарегистрировать роуты, вызвать эти методы автоматически, и у нас появляется очень легкая и приятная модель регистрации. -1902.90 1909.42 SPEAKER_00 Нам уже не нужно менять код в нескольких местах для того, чтобы завести нам, допустим, вообще новый домен. -1909.42 1916.74 SPEAKER_00 Нам не нужно бежать в папочку с контроллером, дописывать контроллеры, в папочку с моделями дописывать какую-то модель, с валидаторами дописывать валидатор. -1916.74 1936.82 SPEAKER_00 То есть мы уже не бегаем по всему Solution, мы всего лишь навсего заходим в один модуль, добавляем туда класс, реализующий imodule, подключаем ему необходимые модельки, валидаторы, хендлеры, все подряд, и Reflection автоматически, без изменения чего-то еще снаружи, нам подхватывает эту реализацию и предоставляет все необходимые endpoints для работы приложения. -1936.82 1945.90 SPEAKER_00 Очень получается удобно, гибко и самое приятное, что в одном месте все меняется, не нужно никуда больше ходить. -1945.90 1950.94 SPEAKER_00 Модуль получается, как я уже сказал, самодостаточной единицей. -1950.94 1957.78 SPEAKER_00 И более того, он получается более гибкий, чем стандартные подходы с контроллерами и с моделями. -1957.78 1967.86 SPEAKER_00 Потому что если вы хотите сделать что-то простое, допустим, тоже самый холсчек, то внутри этого модуля вам даже не нужно выделять отдельные хендлеры. -1967.86 1976.30 SPEAKER_00 Вы просто можете с помощью minimal API смапить один единственный делегатик с холсчека, и все, и ваша функциональность реализована просто одной строчкой. -1976.30 1978.30 SPEAKER_00 Вам не нужно загоняться чем-то больше. -1978.30 1997.06 SPEAKER_00 Если у вас есть сложная функциональность, та же самая корзина, у которой есть какие-то валидаторы, какой-нибудь походок в базе данных, перемаппинг моделей, то вы можете внутри этой папочки корзина создать себе под папочки какие-то, создать себе дополнительные классики, создать себе те же самые модели. -1997.06 2003.06 SPEAKER_00 В общем, организовать полностью ту структуру, которая позволит вот эту сложность нивелировать с помощью разделения. -2003.06 2014.78 SPEAKER_00 Также модули можно, например, выделять, если у вас там завелся какой-то сабмодуль, и потом его функциональность стала настолько большой, что вы понимаете, что его нужно перенести на какой-то уровень выше. -2014.78 2015.78 SPEAKER_00 То же самое элементарно. -2015.78 2023.02 SPEAKER_00 Вы его выделяете, всего лишь на все добавляете регистрационную часть i-модуль, и все, он уже живет как полноценный модуль. -2023.02 2040.82 SPEAKER_00 Также данный подход с модулями, он более понятен, потому что, когда новый разработчик приходит в ваш проект, ему не нужно уже бегать по 50 папочкам для того, чтобы осознать, где лежат контроллеры, где лежат слои доступа к базе данных для корзины, где лежат валидаторы. -2040.82 2044.54 SPEAKER_00 Он просто идет в модуль, и в этом модуле содержится абсолютно все. -2044.54 2047.22 SPEAKER_00 Все, что ему нужно, это вот перед глазами преследовать одну папочку. -2047.22 2054.94 SPEAKER_00 Это гораздо легче, чем бегать по всему приложению и искать, где там что регистрируется, и что происходит. -2054.94 2057.66 SPEAKER_00 Следующий аспект, что по модулям легче навигироваться. -2057.66 2061.18 SPEAKER_00 То есть, довольно понятно становится, где что лежит. -2061.18 2069.10 SPEAKER_00 Это может быть вывод из предыдущего пункта, где что лежит, куда идти и что делать. -2069.10 2073.66 SPEAKER_00 Также автор рекомендует придерживаться вот этого понятия, что держать модули нужно как можно проще. -2073.66 2080.38 SPEAKER_00 То есть, если у вас есть какая-то простая функциональность, не выпендривайтесь, напишите ее в одном делегате и забудьте. -2080.38 2085.06 SPEAKER_00 Если она начинает разрастаться, тогда уже можно подумать об отдельном методе. -2085.06 2089.82 SPEAKER_00 Если она уж слишком большая, смотрите на отдельные классы или может быть даже уже потом на отдельной папочке. -2089.82 2097.38 SPEAKER_00 Но начинать всегда стоит с одного и единственного файла, вот этого модуля регистрации. -2097.38 2104.54 SPEAKER_00 Дальше его уже можно бить на различные части и усложнять по мере усложнений вашей логики. -2104.54 2110.14 SPEAKER_00 То есть, нужно держать как можно проще то, что у вас есть. -2110.14 2117.26 SPEAKER_00 И соответственно, ваша структура проектов таким образом тоже будет отражать сложность этих модулей. -2117.26 2129.62 SPEAKER_00 То есть, вы можете прям открыть проект и посмотреть, что если папочка с корзиной там наворочена, у нее там много подпапок, много каких-то файлов, вы понимаете, что это сложная доменная область и туда нужно как-то больше сил, чтобы погрузиться. -2129.62 2132.10 SPEAKER_00 То есть, вы отражается реальная доменная область. -2132.10 2147.22 SPEAKER_00 Если вы заходите в папочку в кабинет пользователя и там нет практически ничего, кроме одного файлика с парочкой роутов, который перенаправляет на какой-нибудь третий сторонний сайт, вы сразу визуально понимаете, что в вашем приложении вот эта доменная область, она довольно простая. -2147.22 2156.02 SPEAKER_00 И таким образом у вас структура проекта отражается с тем доменом, который вы используете на работе. -2156.02 2157.02 SPEAKER_00 Это тоже довольно приятно. -2157.02 2161.90 SPEAKER_00 И сами модули, они получаются довольно гибкие. -2161.90 2165.90 SPEAKER_00 Как я уже сказал, их можно прям отдельно тестировать, так как у вас это отдельная самодостаточная папочка. -2165.90 2170.78 SPEAKER_00 Их можно передвигать между друг другом, можно выделять какой-то сабмодуль, если он разросся. -2170.78 2177.66 SPEAKER_00 Можно наоборот, вкладывать их в сабмодуль, удалять элементарно, так как у нас динамическая регистрация, никто об этом даже не узнает. -2177.66 2182.22 SPEAKER_00 Комбинировать несколько модулей в одну штуку, какой-то один большой модуль. -2182.22 2188.82 SPEAKER_00 В общем, всего это данная структура каталогов, данная структура проектов позволяет очень гибко и легко делать. -2188.82 2192.22 SPEAKER_00 Автор находит очень много примеров, где такая структура давно используется. -2192.22 2215.34 SPEAKER_00 И контроллеры там как раз-таки и казались вот этой избыточной штукой, которая вырождалась всегда в класс с контроллером, и экшен-методы, просто состоящие из одного-единственного метода, который вызывает там сервис или дальше, или может быть бросает в медиатор какую-нибудь команду или какую-нибудь query, и все, и больше ничего не делает. -2215.34 2218.58 SPEAKER_00 То есть там вырождение уже было давно и было очевидно. -2218.58 2232.90 SPEAKER_00 И вот такая структура с минимал-апиаем, она как раз-таки позволяет вот этот ненужный слой, который уже эволюционно начал отмирать, вот она позволяет его вообще убрать и дальше уже подумать, что мы можем сделать на основании тех возможностей, которые у нас есть. -2232.90 2234.50 SPEAKER_00 Вот такое интересное предложение. -2234.50 2238.94 SPEAKER_00 Как ты думаешь, Игорь, достойно того, чтобы попробовать? -2238.94 2252.70 SPEAKER_02 Ну по крайней мере это выглядит как логичный способ объединить вот эти самые разрозненные, ну точнее простыню действительно этих вызовов map-get-map-get во что-то новое и хорошее. -2252.70 2259.74 SPEAKER_02 Кроме того, есть же в седьмом дотнете теперь группы, то есть теперь можно еще сказать map-group с общим префиксом. -2259.74 2268.14 SPEAKER_02 И потом ты получаешь билдер, который можешь передать, например, в какой-нибудь модуль для дальнейшей настройки endpoints. -2268.14 2270.30 SPEAKER_02 То есть возможно группы тут еще помогут дополнительно. -2270.30 2278.90 SPEAKER_00 Да, мне кажется они вот точно отражают сущность модуля, что у тебя одна группа получается, это ровно на один модуль, ты его там полностью, этот домен описываешь. -2278.90 2284.46 SPEAKER_02 Ну единственное, что если тебе дать только самый групп билдер, ты не сможешь добавлять новые сервисы. -2284.46 2293.26 SPEAKER_02 То есть от сервисов тоже, ну от модуля тоже нужен тот самый интерфейсик, который сможет добавить тебе нужные модули сервисы до того, как ты пошел определять endpoints. -2293.26 2300.10 SPEAKER_02 Но в целом для endpoints возможно группы будут как-то тоже более интересны и добавят возможностей. -2300.10 2301.94 SPEAKER_00 Там именно поэтому выделено два метода. -2301.94 2304.94 SPEAKER_00 Один метод регистрирует сервисы в DA, а второй только маппет роуты. -2304.94 2305.94 SPEAKER_00 Ну да. -2305.94 2306.94 SPEAKER_00 То есть там они именно разнесены во времени специально. -2306.94 2322.58 SPEAKER_02 Ну в общем надо посмотреть, я пока не видел ни одного такого прям большого хорошего жирного проекта на minimal api, в основном так всякие модельные штуки, но я, наверное по open source, если пошариться, то можно найти. -2322.58 2324.78 SPEAKER_02 Посмотрим, подождем, может на работе появится. -2324.78 2335.42 SPEAKER_02 А пока пойдем дальше, и следующая штука, которая я не знаю насколько она появится на работе, я пока не готов такую штуку брать в работу, это новый сериализатор. -2335.42 2340.22 SPEAKER_00 Подожди, подожди, это самый быстрый сериализатор на свете, его надо брать в работу, он же самый быстрый, -2340.22 2349.98 SPEAKER_02 он же за перформанс. У него есть некоторые но, которые мне, например, не то чтобы не позволяют его взять, но я буду сильно сомневаться брать его или нет. -2349.98 2366.74 SPEAKER_02 Смотрите, в общем, был у нас message pack такой формат, формат в принципе он написан отдельно, у него есть спецификация, и у нас была реализация message pack для C# написанная человеком по имени Yoshifumi Kawai, который возможно вам известен по нику NewCC. -2366.74 2377.82 SPEAKER_00 Я думаю, что если вы сталкивались с быстрой сериализацией, с бинарной сериализацией, искали самый клевый, самый крутой сериализатор, то вы обязательно с ним сталкивались, потому что этот просто гений сериализации. -2377.82 2389.46 SPEAKER_02 Да, у него был UTF-8 Jason сериализатор, который быстрее всех, у него был Zero Formatter, по-моему, это называлось, который тоже там как-то очень быстро все сериализовывал, десериализовывал, но они были очень специфичные и узкие. -2389.46 2410.70 SPEAKER_02 А здесь он, соответственно, да, message pack никуда не делся, message pack живет, он используется в SignalARIA, туда пришли ребята из Microsoft, помогли все это оптимизировать, переписать, дописать на Span и вот это все, но этого показалось мало, и поэтому этот самый товарищ Yoshifumi, он написал новый сериализатор, назвал его Memory Pack. -2410.70 2423.66 SPEAKER_02 Он еще в несколько раз быстрее message pack, лучше всего он работает на семерке, на седьмом дотнете, но также поддерживает пятый и шестой дотнеты, то есть если вы на чем-то более раннем, забудьте, он не будет работать. -2423.66 2430.46 SPEAKER_02 Еще он поддерживает Unity и он поддерживает TypeScript, про TypeScript отдельно расскажу чуть позднее. -2430.46 2450.90 SPEAKER_02 Причем он такой как бы, сериализатор прикольный, он там поддерживает полиморфизм, умеет быть version tolerant, циклические ссылки и все возможные современные способы ввода-вывода, это интерфейсы iBufferWriter, это работа с ReadOnlySequence, с системой iOPipelines, вот это все. -2450.90 2455.46 SPEAKER_02 Короче звучит, я статью начал читать, звучало прям вообще зашибенно. -2455.46 2456.94 SPEAKER_02 Плюс он использует SourceGenerator. -2456.94 2459.78 SPEAKER_01 Обязательно, какой же сериализатор без SourceGenerator? -2459.78 2460.78 SPEAKER_00 Да. -2460.78 2462.42 SPEAKER_02 Вообще красавчик, заверните два, я уже беру. -2462.42 2481.94 SPEAKER_02 Да, поэтому теперь во-первых, для того чтобы его использовать, вы должны сделать следующее, вы должны ваш класс, который вы хотите сериализовывать, ну и вы его объявляете partial, ну чтобы к нему можно было, понятно, накрутить сериализатор, нагенерить собственно сериализатор, и помечаете его атрибутом memory-packable. -2481.94 2484.14 SPEAKER_02 Ну и все, вы готовы. -2484.14 2500.66 SPEAKER_02 В смысле, все нормально, поскольку он от SourceGenerator, то это все там AOT-friendly, плюс в CompileTime у вас проверят, что внутри вашего класса или структуры, которую вы сериализуете, лежат только те классы либо структуры, которые он умеет сериализовывать. -2500.66 2507.02 SPEAKER_02 Тут возникают тонкости, он сериализует далеко не все, есть некоторые но. -2507.02 2516.54 SPEAKER_02 Во-первых, статья дальше продолжает говорить следующее, возьмем самый простой тип, это int, ну int-ов у нас много, их сериализовать надо. -2516.54 2519.14 SPEAKER_02 Какие у нас есть варианты сериализации int-а? -2519.14 2532.26 SPEAKER_02 Мы можем его сериализовывать как бы как 4 байта, ну просто вот взять 4 байта и записать, а можем сериализовывать по технологии, которая называется, ну или спецификации, которая называется var int, которая как раз используется в MessagePack. -2532.26 2545.62 SPEAKER_02 Идея там в том, что для маленьких чисел, которых у нас вообще говоря довольно много, используется тогда минимум 1 байт, то есть 1 битик из байта на самом деле просто используется для признака, есть ли там еще следующий байт за этим числом. -2545.62 2550.02 SPEAKER_02 И по сути у вас 32 бита этого числа размазывается уже не по 4, а по 5 байтам максимум. -2550.02 2558.02 SPEAKER_02 Плюс это, ну то есть во-первых, большие числа потребуют больше байт, ну очень большие, да. -2558.02 2567.62 SPEAKER_02 А во-вторых, это все-таки требует некоторых ресурсов CPU на предмет, значит декодировать это все, потому что битовые операции, вот это все, ну короче, какая-то работа требуется. -2567.62 2575.02 SPEAKER_02 Но если вы фигачите по int-ы прям как они есть, то сериализация будет быстрее, особенно если это массивы. -2575.02 2583.14 SPEAKER_02 Понятное дело, что вы просто можете скопировать целиком весь массив в выходной поток или наоборот, и у вас все гораздо быстрее. -2583.14 2590.34 SPEAKER_02 Вот, значит здесь в этом новом сериализаторе используется fixed сериализация, то есть int-ы сериализуются как 4 байта. -2590.34 2597.54 SPEAKER_02 В massage-паке использовался varint, поэтому он компактнее, но зато помедленнее. -2597.54 2598.54 SPEAKER_02 Дальше строки. -2598.54 2600.98 SPEAKER_02 Со строками ситуация в каком-то смысле похожа. -2600.98 2604.90 SPEAKER_02 В тотнете внутри они хранятся в utf-16, как вы может быть знаете. -2604.90 2620.90 SPEAKER_02 Если мы в основном работаем со строками, которые у нас влезают в utf-8, то есть английский и прочие не очень экзотические языки, то по сути сериализованная строчка в utf-16 будет занимать в 2 раза больше места. -2620.90 2633.14 SPEAKER_02 В данном случае у него был сделан выбор в пользу сериализации в utf-8, хотя можно настроить, чтобы он сериализовывал прям в utf-16, если вам важна скорость и не важен размер. -2633.14 2637.62 SPEAKER_02 Тогда он будет прям фигачить байтиками из массива чаров изнутри строки. -2637.62 2652.14 SPEAKER_02 При этом, забавный момент, поскольку мы в момент сериализации по строке проходимся, в любом случае, то мы вместе со строкой сериализуем ее длину, причем ее длину и в utf-8 размере и в utf-16 размере. -2652.14 2656.86 SPEAKER_02 Они могут быть разные, поскольку там разные эти уникальные символы. -2656.86 2662.86 SPEAKER_02 И это помогает потом быстро десериализовать, потому что мы сразу можем залокитить нужный размер. -2662.86 2669.74 SPEAKER_02 Ну и есть еще несколько всяких трюков на предмет того, что массив булов он пакуется как массив битов. -2669.74 2671.06 SPEAKER_02 Ну то есть тут понятно. -2671.06 2675.56 SPEAKER_02 А еще у него есть компрессия, но компрессия прям на уровне отдельных байтерей. -2675.56 2687.66 SPEAKER_02 То есть можно на какой-нибудь байтерей, если вы знаете, что в нем прям много всего хранится, прямо на весь атрибут, а вот этот еще пожми, пожалуйста, дополнительно, и он будет использовать алгоритм Бротли, чтобы пожать вот этот байтерей при сериализации. -2687.66 2694.30 SPEAKER_02 По тестам, говорит, выходит это эффективнее, чем сжимать потом итоговый поток. -2694.30 2696.26 SPEAKER_02 Зачем потребовался dotnet 7? -2696.26 2702.10 SPEAKER_02 То есть не то чтобы потребовался, но 7 версия немножко отличается от 5 и 6, она даже немножко быстрее. -2702.10 2706.38 SPEAKER_02 Во-первых, ну она более оптимизирована, поэтому она побыстрее. -2706.38 2709.70 SPEAKER_02 Во-вторых, используются статически абстрактные мемберы в интерфейсах. -2709.70 2728.42 SPEAKER_02 То есть вот вы объявляете вашу модель как partial class, source generator, понятно, дописывает свою часть как свою часть partial class, и в этом месте объявляет, что ваш модель реализует некоторый специальный интерфейс, в котором генерится на самом деле два метода serialize и deserialize статически. -2728.42 2729.42 SPEAKER_02 Чуешь смысл? -2729.42 2731.42 SPEAKER_01 Ну да, нормальный подход. -2731.42 2741.94 SPEAKER_02 То есть у тебя получается на твоей модели волшебным образом появляются два метода serialize и deserialize, которые статически, но они реализованы в стороннем интерфейсе, и за счет этого их не нужно реализовать в твоем методе. -2741.94 2745.14 SPEAKER_02 Ну допустим, почему бы нет. -2745.14 2746.14 SPEAKER_02 Вот. -2746.14 2757.10 SPEAKER_02 Дальше используются reffields, и дальше используются всяческие супер оптимизации для типов, ну, стандартной библиотеки, назовем это так, то есть listt. -2757.10 2765.18 SPEAKER_02 То есть, например, у него есть в коде структурка, которая по набору полей полностью повторяет внутреннее устройство listt. -2765.18 2772.74 SPEAKER_02 И за счет этого он может оптимально, оперируя эту структуркой, оптимально копировать содержимое listt. -2772.74 2776.98 SPEAKER_02 То есть там очень такая low-level магия, сильно завязанная она. -2776.98 2780.38 SPEAKER_02 То есть если сейчас в рантайме взять и поменять порядок полей в listt, этот стерилизатор сломается полностью. -2780.38 2784.50 SPEAKER_00 Я помню, у Стэна Драпкина был похожий хак, у него было еще круче. -2784.50 2787.02 SPEAKER_00 Ну, смысл в том же самом, да. -2787.02 2794.18 SPEAKER_00 И его расчет, как раз я ему задавал этот вопрос, его расчет был на то, что типа listt — это настолько устраивающаяся структура, что никто им не отнимет. -2794.18 2795.18 SPEAKER_00 Да. -2795.18 2796.18 SPEAKER_02 Мы в этом уверены. -2796.18 2797.18 SPEAKER_02 Да, именно поэтому. -2797.18 2813.82 SPEAKER_02 То есть тут тоже есть некоторое количество хаков, то есть, например, он использует новую штуку, по-моему, это в шестом, знаете, появилась, да, вот это вот collection-marshal s-span, по-моему, в шестерке появилась, когда ты можешь получить доступ к, собственно, массиву внутри листа, значит, ну к спану точнее, да, поверх массива внутри листа. -2813.82 2818.50 SPEAKER_02 Но там, например, проблема в том, что этот спан возвращается той длины, сколько у тебя элементов в листе. -2818.50 2821.98 SPEAKER_02 При десерилизации у тебя сколько элементов в листе внутри нового? -2821.98 2824.98 SPEAKER_00 Мы не знаем, если не записали каунт. -2824.98 2829.46 SPEAKER_02 Не-не-не, очевидно ноль, ну в смысле, ты вот взял лист, даже если… Ты хочешь его наполнить, да? -2829.46 2839.78 SPEAKER_02 Да, я хочу наполнить его десерилизацией, он пустой, возможно, массив-то не пустой, потому что, возможно, массив мы там переиспользовали откуда-то, ну в смысле, в этом листе мы ему сказали clear, грубо говоря, перед этим. -2839.78 2846.94 SPEAKER_02 Он там, в нем что-то лежало, то есть он может быть длинный, но если ты скажешь collection_marshal_span, тебе вернется спан нулевой длины. -2846.94 2875.54 SPEAKER_02 Поэтому через вот эту вот типа копию-не копию, значит, структурки, через приведение типов можно внутри листа задать, что у него на самом деле length нужной тебе длины, которую ты взял из десерилизатора, после чего спан тебе вернет нужную длину, ну в смысле, collection_marshal_span вернет спан нужной длины, ты в этот спан запишешь содержимое из, собственно, десерилизованных данных и проставишь эту длину еще раз уже нормально. -2875.54 2880.34 SPEAKER_02 Короче, там такая супермагия, ну значит, от этого он, конечно, -2880.34 2892.02 SPEAKER_00 быстрый. Ну, может, это и звучит как бы страшно, но если разобраться, то все эти ORM-ки, допустим, самые быстрые, все десерилизаторы, которые самые быстрые, они такую магию применяют уже давно и долго, поэтому это нормально. -2892.02 2897.72 SPEAKER_02 Ну да, ну в общем, для десерилизатора такого general purpose звучит немножко страшно. -2897.72 2911.06 SPEAKER_02 Итак, детали, значит, десерилизует он, понятно, все встроенные типы плюс кучу встроенных коллекций, там основные, понятно, листы, дикшн, ремапы, вот это все, стеки очереди и все такое прочее. -2911.06 2923.58 SPEAKER_02 Значит, если вы десерилизуете структуру, то никакие аннотации, вообще десерилизатор позволяет задать всякие аннотации, ну типа вызвать callback до сериализации, после сериализации, вот это все. -2923.58 2934.66 SPEAKER_02 Короче, если это структура, то никаких там конструкторов аннотаций вызываться не будет никогда, она сериализуется просто напрямую из памяти, вот как она лежит, так и сериализуется туда-сюда. -2934.66 2962.62 SPEAKER_02 Поддерживается полиморфизм, для этого нужно либо на базовом классе, либо интерфейсе, разметить атрибутиками, типа вот у этого интерфейса есть там челды такие-то, каждому челду присвоить свой номер, он, видимо, будет сериализован как ключик, чтобы понимать, какой класс создать при десерилизации, но можно эту штуку собрать и в коде тоже, в рантайме прямо определить, сколько у тебя там челдов и как их десериализовать. -2962.62 2967.46 SPEAKER_02 Дальше эта штука поддерживает два режима версионирования. -2967.46 2976.82 SPEAKER_02 Есть так называемый режим limited version tolerance, то есть такой ограниченный режим версионированности, в нем работают следующие ограничения. -2976.82 2991.54 SPEAKER_02 Во-первых, если у вас есть структура, то вы не можете ее менять вообще никак, ну вот совсем, то есть если вы какую-то структуру описали, начали ее сериализовать, все, ее менять больше нельзя никогда, иначе вы десериализовать не сможете, потому что она десериализуется при моем копировании. -2991.54 3006.62 SPEAKER_02 Вы можете добавлять мемберов, но удалять нельзя, а также вы не можете менять у мемберов тип, либо порядок, то есть по сути вы в классы, вы можете просто дописывать поля в конец, больше вы не можете делать ничего. -3006.62 3015.46 SPEAKER_02 Это, понятное дело, довольно ограничивает все, поэтому есть версия, которая называется full version tolerance, точнее режим работы. -3015.46 3030.78 SPEAKER_02 В этом случае структурки все еще не могут быть поменены, там ничего не поменялось, а у классов все мемберы должны обязательно иметь атрибут memory pack order и явно прописанные чиселку, в каком порядке их сериализовать. -3030.78 3049.82 SPEAKER_02 Ну и понятно, в этом случае вы можете добавлять и удалять, но если вы добавляете новые элементы, поля или property, то нужно будет использовать неиспользуемые чиселки, то есть вы дописываете в конец, а если какое-то поле удалили, то больше эту чиселку переиспользовать нельзя в этом классе. -3049.82 3055.74 SPEAKER_02 Но логика понятна, поскольку мы не сериализуем имена, мы сериализуем только значения, но нужно знать точный порядок. -3055.74 3058.70 SPEAKER_02 Поэтому такие дела. -3058.70 3062.30 SPEAKER_02 Тип все еще менять нельзя у мемберов. -3062.30 3072.38 SPEAKER_02 Получается, за счет того, что в отличие от message pack тут не пишется ни имена, ни структура, ничего, получается понятно, очень компактный формат, до некоторой степени вообще похоже на protobuf, в общем-то. -3072.38 3082.02 SPEAKER_02 Там по сути тоже самое, тоже размечается порядок строгий, типы заранее известны в схеме, и вы просто гоняете все только значения. -3082.02 3088.50 SPEAKER_02 Но вот он такой, protobuf, но без явной схемы на основе классов. -3088.50 3101.54 SPEAKER_02 При этом есть опция в compile time, поскольку это все source генератор и вот это все, то в compile time выплюнуть файлик, в котором будет написано, а какая же в итоге псевдосхема какая получается. -3101.54 3116.98 SPEAKER_02 То есть это позволяет, например, во время CI проверить, что эта схема не поменялась, то есть закоммитить предыдущую схему и если схема поменялась, как-нибудь на CI отругаться либо сверить схемы и проверить, что вы там поля не убрали, что-нибудь в таком духе. -3116.98 3140.14 SPEAKER_02 Короче, довольно много ограничений, но если вам нужен прям супербыстрая скорость или у вас довольно такие стабильные типы, ну например вы сериализуете много там, не знаю, каких-нибудь там векторов или матриц, которые строго фиксированы на размеры и никогда меняться не будут, ну потому что что там еще в векторе из трех элементов нужно добавлять, там всегда три элемента, то возможно такой сериализатор имеет место, имеет право на жизнь. -3140.14 3141.14 SPEAKER_02 По перфомансу. -3141.14 3172.02 SPEAKER_02 По перфомансу есть замеры, ну я видел их только в этой статье пока, поэтому не знаю, будут ли еще какие-то независимые когда-нибудь, но смысл в том, что если мы берем JSON, JSON для сериализуется в бенчмарках MessagePack за 23 секунды, ой за 23 миллисекунды видимо, десериализуется за 39, а MemoryPack за 13-25 соответственно, то есть выигрыш где-то раза в 2 на сериализации и в 1,5 на десериализации. -3172.02 3196.18 SPEAKER_02 А вот если мы берем, вот тут для примера сериализовался век, как раз таки массив из векторов, то есть массив из трехмерных векторов, 10 тысяч элементов, то MessagePack на это тратил 10 миллисекунд и 26 на распаковку, а MemoryPack 0.2 и 0.3 соответственно, то есть тут уже разница в, что там, 10, в 50 раз приблизительно. -3196.18 3210.30 SPEAKER_02 То есть ну прям по скорости действительно круто, ну понятно за счет чего, за счет того, что он работает напрямую с памятью во многом старается, то есть положить в сериализованные данные ровно так, как они лежат в памяти объектов, удобно ведь? -3210.30 3227.34 SPEAKER_02 При этом в этой же статье есть вполне частное сравнение с MessagePack с точки зрения функциональности, то есть и он говорит, что MessagePack все еще круче, чем MemoryPack, чем, что во-первых он точно совместим между разными языками, MessagePack вы сможете распаковать на Java, на Python, на чем угодно. -3227.34 3232.78 SPEAKER_02 MessagePack совместим с JSON в том смысле, что в MessagePack пишутся имена, вам не нужно знать схему. -3232.78 3244.42 SPEAKER_02 Он полностью version-tolerant по дефолту, он позволяет там всякие анонимные типы сериализовывать и так далее, ну и он давным-давно работает, так сказать, проверен временем. -3244.42 3257.74 SPEAKER_02 MemoryPack по дефолту, ну как бы, понятно, супербыстрый, но по дефолту limited version-tolerant, то есть вы очень ограничены, что вы можете делать с полями и изменениями ваших моделей. -3257.74 3262.50 SPEAKER_02 Единственный поддерживаемый язык, кроме C#, это TypeScript. -3262.50 3275.26 SPEAKER_02 Для TypeScript там на самом деле в момент компиляции генерятся JS-файлики, которые нужно потом заинклюдить в ваш код TypeScript, и там написан JS-код, который, собственно, может десериализовать и сериализовать то, что вы собрали. -3275.26 3277.74 SPEAKER_02 То есть там тоже код дегенерации, по сути, это делается. -3277.74 3307.46 SPEAKER_02 И он, конечно, MemoryPack лучше, чем MessagePack, если вам нужен performance, если вам нужен AOT, потому что MessagePack все еще на рефлекшене, а не все там работает в AOT, MemoryPack - Strongly Compiled Time, поэтому там AOT, полиморфизм, циклические ссылки, то, что называется Override Deserialization, то есть вы можете подсунуть существующий объект, как мы смотрели с примером, в список, и он в существующий список заново положит новые данные. -3307.46 3310.70 SPEAKER_02 Ну, в общем, примерно так. -3310.70 3330.10 SPEAKER_02 И рекомендация автора, собственно, говорит следующее, что если вы живете только в C#, в C# ни с кем другим не общаетесь, и у вас достаточно стабильные модели, можно использовать MemoryPack, но думайте про вот эту версионность, то есть если вы собираетесь часто менять модели, скорее всего, это не ваш вариант. -3330.10 3332.82 SPEAKER_02 В любом другом случае, используйте MessagePack. -3332.82 3333.82 SPEAKER_02 Как-то так. -3333.82 3336.86 SPEAKER_02 Будешь использовать такую штуку. -3336.86 3360.18 SPEAKER_00 На самом деле я много писал проектов, где скорость и компактность, и Memory Allocation были очень важными вещами, важнее всего, и честно могу сказать, что вот эти все глупости, толерантность к версионированию, меняние порядка полей, еще что-то, ну вообще это не играет никакой роли, если вам нужно выжать максимальный перформанс. -3360.18 3368.70 SPEAKER_00 Я думаю, что здесь даже полиморфизм в дистиллизации появился только потому, что его элементарно поддержать с помощью Source Generator. -3368.70 3372.18 SPEAKER_00 Если бы не было Source Generator, то тут бы и полиморфизма тоже, естественно, никакого бы не было. -3372.18 3373.18 SPEAKER_00 Это слишком затратно. -3373.18 3378.54 SPEAKER_00 Поэтому если, ну то есть люди, которые выжимают перформанс, они не загоняются такими глупостями. -3378.54 3381.06 SPEAKER_00 Для них вот главное перегнать максимально эффективно. -3381.06 3391.22 SPEAKER_00 И поэтому там делаются и отдельные структуры, которые никогда в жизни не меняются, а если меняются, то заводятся полностью другие структуры, постепенно все переезжается руками. -3391.22 3395.70 SPEAKER_00 И полиморфизм там делается руками, если вдруг это почему-то вам нужно в таком случае. -3395.70 3400.22 SPEAKER_00 В общем, там где нужен перформанс, все вот эти минусы, они абсолютно несущественны. -3400.22 3404.74 SPEAKER_00 Там нужно просто гонять Massive Byte, просто как сумасшедший максимально эффективно. -3404.74 3413.18 SPEAKER_00 И если там действительно Memory Pack показывает шикарные результаты, которые обгоняют всех, то конечно, я его использовать буду. -3413.18 3417.90 SPEAKER_00 Я еще хотел подчеркнуть это, что это как раз не General Purpose, а сервизатор, как ты говорил. -3417.90 3422.10 SPEAKER_00 А если мне нужен какой-нибудь General Purpose, то наверное, Message -3422.10 3433.10 SPEAKER_02 Pack, да, наше все. Ну вот авторы, я так понимаю, это все дело, судя по тому, что это что-то поддерживает Unity, как раз это все пилят ради игр, где много однотипных мосилов, так скажем. -3433.10 3434.10 SPEAKER_00 Массивые экстрапов, матрицы. -3434.10 3438.98 SPEAKER_00 Да, где как раз таки не важен ваш JSON compatibility, так наплевать всем на него. -3438.98 3440.30 SPEAKER_02 Да, и там это все нужно. -3440.30 3444.86 SPEAKER_02 Но действительно, наверное, есть такие области в обычном программировании, но скорее всего, я все-таки потащу Message Pack. -3444.86 3448.98 SPEAKER_02 Я пока не вижу, где я такое могу использовать, но опять же, областей есть много разных. -3448.98 3454.86 SPEAKER_02 Давай дальше, у нас еще много тем, поэтому надо не останавливаться. -3454.86 3457.02 SPEAKER_00 Да, да, давай быстрее. -3457.02 3465.70 SPEAKER_00 Чтобы развеять там твой перформанс, интерналс и все такое, хочу немножко стратегическую для начинающих бросить, говорим про GitHub Actions. -3465.70 3486.30 SPEAKER_00 Так вдруг случилось, что я почему-то узнал, что если люди уже начали выходить на GitHub, то есть раньше у нас на GitHub вообще разработчики в России практически не выходили, сейчас уже мы GitHub не боимся, сейчас уже GitHub это как бы стандартная часть нашей жизни, не только там, чтобы посмотреть, но и многие люди уже как бы и даже коммитят, и даже пушат, и даже вообще не боятся. -3486.30 3497.94 SPEAKER_00 Но GitHub Actions это все еще для многих какой-то черный ящик, вот поэтому хотелось бы дать такую вводную про GitHub Actions, зачем он нужен, для чего используется и вообще как он может помочь дотнет-разработчику. -3497.94 3500.62 SPEAKER_00 Давай немножко быстренько в это дело и копнем. -3500.62 3504.10 SPEAKER_00 Соответственно, что такое GitHub Actions? -3504.10 3508.94 SPEAKER_00 Это возможность continuous integration и continuous delivery для GitHub. -3508.94 3521.14 SPEAKER_00 Самое в нем прекрасное в том, что он бесплатный, доступен абсолютно каждому, если у вас есть репозиторий, то в этом репозитории вы можете смело использовать бесплатный CIDI, что в наше время в принципе очень даже хорошо и очень даже щедро. -3521.14 3525.86 SPEAKER_00 У них там довольно нормальный пол агентов, в принципе у меня никогда не было с ними проблем. -3525.86 3532.66 SPEAKER_00 Я раньше сидел на всяких Avera и Travis, и там у меня все время были какие-то очереди, занятости, все такое. -3532.66 3540.42 SPEAKER_00 Здесь же Microsoft вкладывает огромное количество бабла, введено в эту инфраструктуру, и агентов там полно, никаких очередей нет. -3540.42 3543.10 SPEAKER_00 Но давайте поближе, для чего это все? -3543.10 3549.86 SPEAKER_00 Прежде всего, чтобы автоматизированно тестировать, билдить, конечно же, ваш код и может быть даже деплоить. -3549.86 3553.46 SPEAKER_00 GitHub Workflow представляет собой набор YAML файликов. -3553.46 3567.38 SPEAKER_00 Это расширение .yaml какой-нибудь или .yml, и данный файлик просто-напросто складывается внутрь вашего Git репозитория и в специальную папочку, которая называется .git/workflows. -3567.38 3576.06 SPEAKER_00 В этой папочке вы можете сложить несколько различных YAML файликов, в зависимости от того, насколько многообразный Workflow вам требуется. -3576.06 3594.98 SPEAKER_00 Прекрасно здесь то, что нет никакого GUI, не может там какие-нибудь кнопочки утечь, не надо никуда переносить, это всего-навсего настраивается в одном YAML файле, что поддерживает тему Build as Code, то есть мы собираем весь билд и описываем его в виде того же самого кода, если из-за кода считать YAML, и это очень удобно. -3594.98 3610.18 SPEAKER_00 Версионируется, распространяется вместе с бранчами, можно экспериментировать в различных ветках, не мешая основной, есть и история, можно всегда посмотреть, кто это, кто менял какие переменные, в общем все прелести кода у билда здесь появляются. -3610.18 3623.66 SPEAKER_00 Workflow, GitHub Workflow, он как раз-таки использует GitHub Actions, GitHub Actions состоит из инструкций, а вот эти самые непосредственные инструкции, они запускают таски. -3623.66 3627.34 SPEAKER_00 В общем такая иерархия, давайте разберемся подробнее в терминологии, чтобы не запутываться. -3627.34 3629.58 SPEAKER_00 Прежде всего GitHub Actions. -3629.58 3640.50 SPEAKER_00 GitHub Actions это платформа для CI/CD, она позволяет вам запускать такие обычные рутинные вещи для каждого проекта, как сборка, тестирование и развертывание. -3640.50 3648.58 SPEAKER_00 Далее есть такое понятие как Workflow, это как раз-таки настраиваемый автоматический процесс, который умеет запускать джабы. -3648.58 3654.02 SPEAKER_00 Об этом вернемся чуть попозже, а прежде всего мы узнаем, кто их запускает, то есть какое событие их запускает. -3654.02 3655.70 SPEAKER_00 У нас есть такое понятие как Event. -3655.70 3665.38 SPEAKER_00 Event это как раз-таки специальная активность, которая происходит внутри репозитория, которая триггерит, запускает Workflow, и в свою очередь запускает джабы. -3665.38 3677.94 SPEAKER_00 Внутри репозитория что у нас может быть, например, кто-то запушил новое изменение, кто-то создал новый pull request, кто-то создал новый issue даже, на все на это может поджечь триггер, который запустит соответствующий Workflow. -3677.94 3682.30 SPEAKER_00 Как я уже сказал, Workflow для исполнения запускает джабы. -3682.30 3690.30 SPEAKER_00 Джабы это набор шагов, которые будут выполняться на одном раннере, то есть они будут выполняться не параллельно, они будут на одном раннере выполняться последовательно. -3690.30 3705.06 SPEAKER_00 Если вы хотите, чтобы с вашим основным процессом, то есть с вашим основным джабом выполнялись какие-то другие вещи, сканирование кода вполне может, сканирование кода на какие-нибудь security-извимости вполне может идти параллельно с тем, когда вы код билдите и тестируете. -3705.06 3713.68 SPEAKER_00 Это можно сделать двумя джабами, и они будут запускаться параллельно, и друг другу мешать не будут, а билд у вас в общее время будет соответственно намного меньше. -3713.68 3716.66 SPEAKER_00 Дальше есть такое понятие как Actions. -3716.66 3728.42 SPEAKER_00 Actions это специально написанные маленькие приложенницы, которые как раз таки выполняют непосредственно различную работу с различными аспектами. -3728.42 3733.98 SPEAKER_00 Эти приложения, они обычно сложные, но очень часто переиспользуемые. -3733.98 3742.18 SPEAKER_00 Такие как, например, запустить команду, или скачать репозиторий, или пропатчить определенный файлик. -3742.18 3746.62 SPEAKER_00 То есть обычные такие команды, они выполнены, каждая эта команда в виде отдельного приложения. -3746.62 3751.26 SPEAKER_00 И такие приложения называются Actions, что довольно удобно об этом мы посмотрим попозже. -3751.26 3754.54 SPEAKER_00 И еще одно понятие, которое вам пригодится это Runner. -3754.54 3764.26 SPEAKER_00 То есть это непосредственно тот сервер, который запускает ваш workflow в результате, когда триггернуло какое-то событие. -3764.26 3767.74 SPEAKER_00 Теперь давайте разберемся, что же внутри находится этого GitHub workflow. -3767.74 3771.22 SPEAKER_00 Как я уже сказал, workflow это всего лишь навсего ямл файлик. -3771.22 3774.46 SPEAKER_00 И в этом одном единственном ямл файлике описано абсолютно все, что вам нужно. -3774.46 3784.10 SPEAKER_00 Поэтому вы можете пойти, найти в GitHub этот файл, просто визуально его открыть, посмотреть и вытащить оттуда какие-нибудь интересные подходы, интересные хаки. -3784.10 3785.10 SPEAKER_00 Все в одном месте. -3785.10 3787.42 SPEAKER_00 Этот файлик обычно не такой уж и большой. -3787.42 3790.74 SPEAKER_00 Для примитивных проектов он можно в десяток строк вложить. -3790.74 3796.90 SPEAKER_00 Для каких-то более больших, более богатых там уже естественно комментарии, ветвления, параллельности. -3796.90 3799.34 SPEAKER_00 Но до этого нам еще дожить надо. -3799.34 3801.34 SPEAKER_00 Итак, в каждом workflow прежде всего есть имя. -3801.34 3806.34 SPEAKER_00 Это имя будет отображаться в интерфейсе GitHub, когда pipeline будет запускаться. -3806.34 3814.58 SPEAKER_00 У него есть набор триггеров, по которым этот workflow будет триггериться в зависимости от какого-то ивента или от какого-то другого события. -3814.58 3817.10 SPEAKER_00 В общем все это описывается в этом же файле. -3817.10 3825.58 SPEAKER_00 Для того чтобы workflow работал вам нужно указать хотя бы один триггер, иначе его некому будет запускать, никакое событие не произойдет и он никогда не будет работать. -3825.58 3827.86 SPEAKER_00 Очень полезным бывает атрибут ignore. -3827.86 3835.78 SPEAKER_00 Это секция ignore, которая вам рассказывает, что workflow нужно запускать не всегда, а только на определенный шаблон каких-нибудь файликов. -3835.78 3850.70 SPEAKER_00 Допустим, если мы исправляем ошибку в файле readme, то есть в текстном описании нашего проекта, и коммитим такой коммит в нашей репозитории, то естественно не надо запускать никакой билд, то есть не надо запускать workflow, который перезапустит опять наши тесты, начнет это все гонять. -3850.70 3857.58 SPEAKER_00 Мы понимаем, что файл readme никак на наши тесты не повлияет, скорее всего статус останется таким же, каким он был до этого. -3857.58 3870.58 SPEAKER_00 Мы можем задавать какие-то перемены в этом ямле, то есть использовать его более-менее как полноценный более-менее язык, переменные в одном месте объявлять, в одном месте менять, а дальше уже в течение всей жизни в коде его как-то использовать. -3870.58 3874.82 SPEAKER_00 У нас есть список джебов, есть хороший параметр, называется стратегия. -3874.82 3877.02 SPEAKER_00 Стратегия обычно задает матрицу операционных систем. -3877.02 3888.22 SPEAKER_00 Как вы сейчас знаете, дотнет у нас кросс-платформенный, поэтому вы можете написать матрицу операционных систем, на которой вы хотите тестировать ваш код, указать там допустим Ubuntu, Windows и macOS. -3888.22 3898.54 SPEAKER_00 И в результате этого у вас запустится уже не один джоб, а целых три джоба на различных операционных системах и в каждом из джобов будут выполнены определенные шаги. -3898.54 3903.26 SPEAKER_00 Вот давайте как раз таки разберемся, какие например шаги выполняет стандартный дотнет разработчик. -3903.26 3913.90 SPEAKER_00 Прежде всего первым шагом он делает чек-аут, то есть мы забираем из гитхаба тот репозиторий или ту ветку или тот коммит, который мы сейчас хотим протестировать. -3913.90 3929.54 SPEAKER_00 Дальше мы можем настроить переменные окружения дотнета, например выставить версию дотнета, с которой мы будем билдиться, выбрать версию SDK, с которой мы будем билдиться и запускать соответственно тесты. -3929.54 3945.10 SPEAKER_00 Следующим шагом у нас идет обычно рестор пакетов, это запуск стандартной команды dotnet restore, дальше билд, это команда dotnet build и обычно тест, это команда dotnet test, как несложно догадаться, вот из таких там простых шагов и складывается минимальный pipeline. -3945.10 3951.62 SPEAKER_00 И в результате этого весь ваш код будет обязательно собирабельный, тестируемый и ресторабельный. -3951.62 3968.18 SPEAKER_00 Можно добавлять больше, например можно собирать артефакты, NuGet пакеты допустим, Docker images, и отсюда же можно их прям пушить, какой-нибудь NuGet.org или в Docker Hub или куда-то еще в ваш приватный репозиторий, если вам это вдруг нужно. -3968.18 3980.62 SPEAKER_00 Также можно запускать различные уязвимости, сканирование на security уязвимости и анализировать ваш код, насколько там соответствует параметрам различным, которые у вас там приняты. -3980.62 3988.38 SPEAKER_00 Естественно можно запускать не просто security уязвимости, а просто проверку качества кода или проверку стиля, который принят в вашей команде. -3988.38 3996.86 SPEAKER_00 Вот все вот эти проверочки, они тоже сделаны в виде отдельных экшенов, они уже есть, они уже стандартные, все подхватываются, вам нужно добавить просто-напросто одну строчку. -3996.86 4013.82 SPEAKER_00 Ну и естественно разворачивать приложение тоже можно, если у вас площадка, на которой вы хотите развернуть доступно из агентов GitHub, то есть это какое-нибудь стандартное публичное облако, Azure, Yandex, еще что-нибудь в общем, туда тоже можно прямо из GitHub запольнуть ваше свеженькое приложение и оно уже попадет непосредственно на площадку. -4013.82 4022.98 SPEAKER_00 Еще один аспект, о котором часто забывают, а зря, это кэширование, потому что наше дотант приложение очень сильно зависит от различных референсов. -4022.98 4026.54 SPEAKER_00 Таких референсов, ну, get-пакетов, ну, get-референсов, их может быть очень много. -4026.54 4041.30 SPEAKER_00 И у GitHub Actions есть специальная оптимизация, которая позволяет вам указать там папочки, которые будут кэшироваться и указать там маски, к которым файлам нужно кэшировать специальный ключ, когда сбрасывать кэш. -4041.30 4057.02 SPEAKER_00 В общем, там много настроечек, но самый главный смысл, что обычно так случается, что большую часть всего пайплайна занимает именно .NET Restore, потому что пойти там куда-нибудь в интернет и оттуда скачать там 100 тысяч миллионов зависимостей, это довольно долго. -4057.02 4060.82 SPEAKER_00 Это часто бывает дольше, чем забилдить, даже протестировать приложение. -4060.82 4067.66 SPEAKER_00 И вот, если у вас такая ситуация, то как раз кэширование много пакетов – это ваше спасение. -4067.66 4075.46 SPEAKER_00 Один из самых крутых фич, которые вам дает GitHub Actions – это проверка вашего workflow. -4075.46 4090.94 SPEAKER_00 То есть вы можете задать специальные условия, которые проверят статус текущего commit, текущей ветки, которая к вам, например, приходит в виде pull-request, и завалить определенно билд, если вам это нужно, или наоборот, не завалить, а пропустить билд. -4090.94 4106.34 SPEAKER_00 Ну, например, вы можете сконфигурировать, что если ваш pull-request не компилируется, то, естественно, вы не хотите видеть его в мастере, и вы можете такую настройку сделать в workflow, что если данный pull-request не компилируется, то запретить merge в мастер. -4106.34 4108.46 SPEAKER_00 И дальше вы можете наворачивать. -4108.46 4114.82 SPEAKER_00 Соответственно, он должен не только компилироваться, но и проходить, например, style-гайды, должен проходить там качество кода, должен выдавать какой-то артефакт. -4114.82 4119.18 SPEAKER_00 И вообще абсолютно все, что в вашу фантазию может прийти, можно здесь проверить. -4119.18 4129.94 SPEAKER_00 И вот такие вот проверки, вот такие вот quality-гейты, то есть какие-то ворота, которые гарантируют определенное качество в мастере, вы можете строить на основании вот этих GitHub-экшенсов. -4129.94 4139.30 SPEAKER_00 Также существует огромное количество там сторонних экшенов, которые может написать абсолютно каждый разработчик. -4139.30 4144.78 SPEAKER_00 И есть .NET Developer Community, которая поставляет GitHub-экшенсы для .NET. -4144.78 4147.50 SPEAKER_00 И там полно всякого интересного. -4147.50 4159.94 SPEAKER_00 Например, можно взять экшенс, который генерирует вам классные отчеты, показывает покрытие кода, который генерирует классные бейджи, то есть картинки, с помощью которых вы можете нарядить ваш репозиторий. -4159.94 4172.10 SPEAKER_00 В общем, там уйма веселья, уйма всего интересного, но прежде всего, конечно, нужно научиться настраивать экшены вашим конкретным репозиториям под те минимальные шаги, которые обеспечат вам хотя бы тестируемый и валидный мастер. -4172.10 4176.34 SPEAKER_00 А уже все остальное там для вас откроется дальше, там уже много всего интересного. -4176.34 4180.26 SPEAKER_02 Да, технология хорошая. -4180.26 4182.94 SPEAKER_02 Я ее немножечко использовал, на самом деле. -4182.94 4196.98 SPEAKER_02 Ну, на работе мы в GitHub не живем, у меня на GitHub C# практически нет, но когда я куда-то контрабидил в другие проекты, то да, было пару мест, где нужно было поправить GitHub-экшенс, workflow описание, и это было прямо очень приятно. -4196.98 4207.86 SPEAKER_00 Ну, я думаю, на любой работе, естественно, на твоей тоже обязательно будет какой-нибудь CI/CD, и это уже как бы стандарт любой разработки. -4207.86 4215.62 SPEAKER_00 Поэтому то, что у нас open-source проекты некоторые не имеют встроенного CI/CD, это вот грустно, даже не проекты, а репозиторий. -4215.62 4221.58 SPEAKER_00 Хотелось бы, чтобы там тоже это было как бы стандарт, сделать его просто, он бесплатный, поэтому почему бы просто -4221.58 4230.34 SPEAKER_02 не сделать. Давай пойдем дальше, поговорим про CI/CD, но уже немножко другой, ну, то есть не совсем про CI/CD, но тоже про сборку и про код. -4230.34 4235.42 SPEAKER_02 Заанонсили штуку под названием .NET Virtual Monolithic Repository. -4235.42 4241.30 SPEAKER_02 Ну, как заанонсили, анонсмент появился, но там есть куча дисклеймеров, давайте разбираться. -4241.30 4246.86 SPEAKER_00 Слушай, ну звучит прям солидно, да, такой виртуальный монолитик репозиторий, прям очень интересно. -4246.86 4267.86 SPEAKER_02 Да, смысл в том, что если сейчас вы хотите собрать полностью .NET, вот получить, условно говоря, инсталлер .NET SDK или рантайма целиком, то вам нужно это сделать из кучи разных отдельных репозиторий, там у нас как раз рантайм отдельно, спиноткор отдельно, EF отдельно, то отдельно, все отдельно, инсталлеры вообще черти где живут. -4267.86 4272.50 SPEAKER_02 То есть, короче, очень сложный процесс, который в состоянии сделать только Microsoft. -4272.50 4277.26 SPEAKER_02 Сейчас сделали новые репозитории под названием внезапно .NET/.NET. -4277.26 4282.82 SPEAKER_02 Вот, он тоже в организации .NET и репозитории называется .NET. -4282.82 4300.18 SPEAKER_02 Это виртуальный монолитик, монолитный, то есть репозиторий, который включает в себя весь код, который необходим для того, чтобы собрать себе .NET SDK плюс систему под названием Source Build, это та штука, которая, собственно, используется для сборки .NET SDK. -4300.18 4317.94 SPEAKER_02 Причина, ну не причина, одна из целей, которая достигалась, это то, что у нас теперь есть один коммит, то есть как только вы туда, вы можете собрать точнее .NET и ваша сборка будет полностью идентифицироваться одним единственным коммитом. -4317.94 4321.30 SPEAKER_02 Понятное дело, поскольку это один-единый репозиторий. -4321.30 4330.26 SPEAKER_02 Это виртуальные репозитории, это зеркало, куда регулярно синхронизируются изменения из всех оригинальных репозиториев. -4330.26 4339.38 SPEAKER_02 То есть это не сабмодули, это не что-либо другое, это просто нормальные репозитории, куда регулярно коммитятся чинджи автоматически из других репозиториев. -4339.38 4345.78 SPEAKER_02 И эта штука все еще экспериментал, то есть это пока эксперимент, посмотреть, как оно будет жить. -4345.78 4355.42 SPEAKER_02 Майкрософт ожидает, что она станет более-менее нормальной постоянной штукой примерно к моменту первой превьюшки 8-го .NET, которая запланирована на февраль 23-го года. -4355.42 4357.66 SPEAKER_01 Они подразумевают из нее собирать все время или -4357.66 4359.26 SPEAKER_00 зачем она им практически нужна? -4359.26 4362.22 SPEAKER_02 Вот. Значит, цели этой штуки следующие. -4362.22 4371.94 SPEAKER_02 Во-первых, иметь возможность, собственно, иметь весь код в одном репозитории, и чтобы вы могли идентифицировать единым коммитом это все. -4371.94 4377.82 SPEAKER_02 Второе, они собираются релизить и собирать SDK для восьмерки оттуда, в том числе. -4377.82 4389.54 SPEAKER_02 Третье, сейчас очень сложно протестировать, например, если вы пишете какую-то фичу, которая зависит, например, одновременно и от рантайма, и от какого-нибудь там, не знаю, BCL. -4389.54 4395.62 SPEAKER_02 Это лежит, ну, рантайм с BCL лежат в одной репо, поэтому тут как раз более-менее нормально. -4395.62 4401.34 SPEAKER_02 А вот если вам нужно какое-нибудь изменение там в BCL и в SP над Core вместе протестировать, то это сложнее. -4401.34 4409.42 SPEAKER_02 Нужно собирать сначала BCL, потом использовать этот BCL, собирать SP над Core, ну, то есть там прям, это очень непросто, особенно для внешних контрибьюторов. -4409.42 4413.14 SPEAKER_02 Ну и для внутренних тоже, сути по всему. -4413.14 4435.46 SPEAKER_02 И цель как раз-таки, что в таком репозитории вы можете создать, это, конечно, виртуальный репозиторий, но никто не мешает вам, например, создать в нем бранч, что-нибудь погонять, потестировать, поменять одновременно там и рантайм, и BCL, и SP, и что угодно еще, собрать из этого SDK, попробовать что-нибудь погонять, попроверять, а потом аккуратненько все свои чинжи уже спортировать в оригинальной репозитории, чтобы нормально закоммитить. -4435.46 4471.58 SPEAKER_02 И третье, эээ, третье, четвертое, цель это удовлетворить требованиям ребят под названием Red Hat Economical, например, это Ubuntu, которые, как мы помним, нативно теперь собирают себе дотнеты в свои нативные пакеты, а по требованиям open-source должен быть способ собрать эту самую штуку из единого репозитория, грубо говоря, ну то есть скачать репозиторий, сказать, грубо говоря, git clone, да, build, и у тебя собрался дополнительный дотнет, готовый пакет, или для там Red Hat, например. -4471.58 4473.14 SPEAKER_02 Как реализован SYNC? -4473.14 4506.70 SPEAKER_02 Значит, они думали сделать сабмодули, решили, что не надо, почитав отзывы в интернете, дальше они хотели сделать сабтри, это такая прям очень, как я понимаю, advanced технология, когда ты в git-репозиториях, по сути, коллекция деревьев внутри, в внутреннем представлении, ты технически можешь на самом деле хранить несколько деревьев, не связанных друг с другом, и потом их вмерживать вместе в единый комит, но там были трудности с тулингом вокруг этого, git немножко криво это поддерживает, и, короче, решили, что не будем. -4506.70 4569.94 SPEAKER_02 Поэтому в итоге они пришли к выводу, что мы просто напишем custom.sync решение, которое просто аккуратненько, по-моему, сейчас настроено раз в три часа, идет во все значит репозитории, их там двадцать восемь, да, двадцать шесть штук, то есть дотнет у нас сейчас состоит из двадцати шести разных репозиториев, то есть это решение, программка она идет в двадцать шесть репозиториев, раз в три часа, делает там аккуратно git-create-patch, и потом этот патч, аккуратно делает git-apply-patch на этот репозиторий, они еще этим добиваются крутой штуки, им нужно уметь исключательно исключать некоторые файлы, то есть, например, там есть какие-нибудь, не знаю, огромные бинарники для каких-то очень специфических тестов, там, или performance каких-нибудь, или еще чего-нибудь, которые они не хотят видеть в этом едином большом репозитории, они аккуратно исключают, потому что всякие моменты типа там, submodule, subrep, вот это все, оно бы все вытащило целиком, а так они имеют возможность что-то исключить. -4569.94 4580.98 SPEAKER_02 Вот, сейчас это все поддерживает только восьмой дотнет и выше, и вряд ли это будет поддерживать более раннее, понятное дело, потому что начали делать это только сейчас. -4580.98 4593.22 SPEAKER_02 Полностью билд из сурсов доступен сейчас только на линуксе, потому что первичная цель это видимо была, чтобы Red Hat и Canonical, им было полегче собирать свои версии дотнета. -4593.22 4599.58 SPEAKER_02 Мак и Windows будут готовы только к девятому дотнету, пока ждать не стоит, сейчас пока там все завязано на линуксе. -4599.58 4611.50 SPEAKER_02 И на данный момент пока еще нельзя сделать полностью оффлайновый билд, то есть там сейчас реквизит для того, как все это собрать, оно уже там сейчас есть, выглядит довольно забавно. -4611.50 4615.14 SPEAKER_02 Шаг первый, как ты думаешь, какой, что тебе нужно, чтобы собрать дотнет? -4615.14 4618.18 SPEAKER_01 Ну, наверное, выкачать репозиторий, запустить дотнот билд. -4618.18 4621.10 SPEAKER_02 Ага, сейчас, первым шагом поставить дотнот SDK, вот -4621.10 4623.10 SPEAKER_01 так вот, понимаешь? Ну, да, неплохо. -4623.10 4628.30 SPEAKER_02 Да, то есть типа вот для того, чтобы собрать SDK из сурсов, тебе нужно поставить другой дотнот SDK, ну типа -4628.30 4631.22 SPEAKER_01 это облегчит жизнь канонику, я чувствую. -4631.22 4644.30 SPEAKER_02 Да, ну у них есть цель все это сделать полностью оффлайн, он там еще за какими-то Nuget пакетами пойдет, на самом деле, во время билда, и там это сказано явно, что типа сейчас мы не оффлайн, мы пойдем в интернет за Nuget, но над этим всем они работают, чтобы было полностью оффлайн. -4644.30 4646.22 SPEAKER_00 Как они сделают Nuget пакет оффлайн? -4646.22 4649.94 SPEAKER_00 Не знаю, я не знаю пока, не знаю, будем следить. -4649.94 4650.94 SPEAKER_02 Хорошо, будем посмотреть. -4650.94 4667.06 SPEAKER_02 Вот, именно поэтому, видимо, они говорят, что это все экспериментал, то есть у них прям большими буквами написано, что типа мы в принципе можем решить, что нафиг не нужно и дропнуть, ну в смысле в таком виде, да, не взлетело, и дропнуть вообще весь репозиторий, так что вы там типа на него пока не завязываете сильно, пока все очень экспериментал. -4667.06 4682.98 SPEAKER_02 Но как-то так, так что возможно, возможно, к, не знаю, к релизу девятки, а восьмерки у нас, да, следующий релиз, к релизу восьмерки, соответственно, через год у нас будет возможность собрать свою собственную SDK, но пока на Linux только, а там, глядишь, через пару лет и до Mac с винтой доберемся. -4682.98 4713.38 SPEAKER_00 Не знаю, слушай, выглядит это как какой-то позор, я вот, почитав их цели, я надеялся, что они как раз такие сделают, там, Sub3, SubRep, SubModule, что-нибудь там виртуально изобретут, потому что знаешь, прикольно, вот все большие гиганты там, всякие Facebook, Яндекс, Google, они как раз делают Monorep у себя, а потом для того, чтобы решить все проблемы Monorep, они изобретают собственный инструментарий, который позволяет из этой Monorep кусочки выдёргивать, как бы их изменения туда какие-то делать и обратно потом в Monorep эти кусочки заливать, но так, чтобы они не сломали всю Monorep там. -4713.38 4714.38 SPEAKER_00 Ну правильно. -4714.38 4715.38 SPEAKER_00 Чем такие извращения делают. -4715.38 4717.78 SPEAKER_00 Да, Microsoft такое же делал для своих, для гита. -4717.78 4722.74 SPEAKER_00 Да, у Microsoft же такая же система есть, было бы прекрасно, если бы Microsoft как раз-таки с другой стороны подошёл. -4722.74 4745.62 SPEAKER_00 Вот у нас есть много маленьких репозиториев, а мы сделаем вот такую виртуальную штуку, которая их соединяет в Monorep, а то если они разрабатываются как отдельные репозитории со всеми их плюсами, и если тебе вдруг почему-то надо, вот забери их в отдельную Monorep, и безусловно, как бы вторым плюсом от этого всего было бы обратная картинка, ты можешь в этой Monorep всё поменять, и он должен разлететься по своим репозиториям, все эти изменения. -4745.62 4752.34 SPEAKER_00 Не важно, там в pull-request, ещё каким-то образом, ну то есть тогда бы это вообще геймчейджер был, то есть это какой-то новый подход на рынке. -4752.34 4756.42 SPEAKER_00 А так они нажали F5, как бы в фаре скопировали все дифы, и всё. -4756.42 4759.74 SPEAKER_00 Ну что это такое, я в 90-х этим занимался. -4759.74 4762.42 SPEAKER_02 Ну вот они только сейчас к этому пришли. -4762.42 4763.42 SPEAKER_00 Тормозят. -4763.42 4768.06 SPEAKER_00 Это не уровень технологической компании мирового уровня, ну что это такое. -4768.06 4770.86 SPEAKER_02 Посмотрим, может что новое придумают, ты будешь доволен. -4770.86 4772.82 SPEAKER_02 Но пока ты не доволен, я понял. -4772.82 4773.82 SPEAKER_01 Пойдём дальше. -4773.82 4776.26 SPEAKER_00 Да, будем надеяться, что их эксперименты будут поудачнее. -4776.26 4784.02 SPEAKER_00 Вот кстати, насчёт неудачных экспериментов, ты знал, что Nuget, он как бы не очень удачный эксперимент, несмотря на то, что им как бы пользуются все. -4784.02 4786.02 SPEAKER_00 Да нет, норм эксперимент, нормально. -4786.02 4795.94 SPEAKER_00 Да ладно, вот я нашёл автора, который, ну автор инструмента, который называется Nugetizer, и он вот говорит, что реально у Nuget есть проблемы. -4795.94 4799.22 SPEAKER_02 Проблемы, наверное, есть много где, ну давай. -4799.22 4801.34 SPEAKER_02 Ну погоди, ну автора нет. -4801.34 4802.94 SPEAKER_00 А, окей, давай. -4802.94 4804.74 SPEAKER_00 Вот, короче, инструментик. -4804.74 4807.42 SPEAKER_00 Как я уже сказал, Nugetizer. -4807.42 4813.34 SPEAKER_00 Это простой, гибкий, интуитивно понятный и очень мощный Nuget упаковщик. -4813.34 4818.06 SPEAKER_00 Хороший слово, пакетчинг, упаковщик, пусть будет упаковщик. -4818.06 4827.34 SPEAKER_00 И этот упаковщик был призван для того, чтобы устранить все минусы Nuget, которые у него накопились, т.е. -4827.34 4834.82 SPEAKER_00 он такой взглянул на Nuget формат под новым углом, взглянул на то, что он умеет и решил переделать всё правильно и по-своему. -4834.82 4853.58 SPEAKER_00 В общем, как я уже сказал, стандартный, стандартный вот этот SDK, у него есть встроенная поддержка упаковки, т.е. сборка бинарников различных в какой-то определенном формате и запаковка их в Nuget пакет. -4853.58 4877.62 SPEAKER_00 Но, как говорит автор, что дизайн того, как команды у Nuget работают, т.е. даже не команды, а описание самого пакета, т.е. это команды, которые в msbuild в props файлах у нас вписаны, т.е. как вот эти сами таргеты работают, как у них пропертии работают, как эти айтемы комбайнятся, сделано абсолютно неконсистентно и нелогично. -4877.62 4890.90 SPEAKER_00 Там плохие дефолты, часто различные команды противоречат синтаксис у друг друга, в общем, и это видно, что инструмент развивался многие-многие годы и подошел, т.е. в результате получилось большое такое неконсистентное месиво. -4890.90 4916.82 SPEAKER_00 И когда вы начинаете не просто собирать там какой-то маленький пакетик из одной сборочки, из вашего одного проектика, там все хорошо, а когда вы начинаете собирать какие-то сложные пакеты, когда у вас много проектов, из них вылетает много сборок и в зависимости от различных условий вам нужно насобирать такой пакет под различные платформы с различными файликами под каждую платформу с различными версиями. -4916.82 4922.98 SPEAKER_00 В общем, это все становится очень-очень сложно и самое главное непредсказуемо. -4922.98 4932.74 SPEAKER_00 Т.е. что там получится в результате, а главное, что получится после того, как выйдет новая версия или когда кто-то поменяет там один флажочек, это становится абсолютно непредсказуемо. -4932.74 4942.38 SPEAKER_00 В общем, это все автора абсолютно не устраивало, поэтому он написал свой инструмент, который позволяет вам это все дело паковать по-своему. -4942.38 4953.42 SPEAKER_00 Для того, чтобы использовать Nugetizer вы должны прописать в css-прош файли специальную директиву, которая рассказывает, какие прош-файлы нужно упаковать, какие нет. -4953.42 4971.78 SPEAKER_00 Так же, как и у обычного Nuget, у него есть стандартные какие-то атрибуты, стандартные элементы, которые, например, могут добавить контекст в destination пакет, но делают они это намного умнее, у него есть шаблоны, которые раскрываются поумнее, у него есть дефолты, которые более предсказуемы. -4971.78 4982.42 SPEAKER_00 Например, если вы захотите засунуть сюда в пакет всю папочку, он вам засунет всю папочку, без всяких там магических звездочек и решеточек, которые вам нужно в стандартном Nuget пакере использовать. -4982.42 4997.86 SPEAKER_00 Интересная команда в том, что можно указать директиву пакет-шаппл-патх, и он все пакеты, которые соберет из всех проектов, неважно где они на какой глубине настроены, он их соберет и сложит в отдельную директорию, там где вы укажете. -4997.86 5008.86 SPEAKER_00 В общем, возможности все такие же точно, но детализация как раз заключается в удобстве, в понятных дефолтах, в более умном поведении и прочем. -5008.86 5018.62 SPEAKER_00 На примере Redmi покажу, вот каждый знает, что есть обычно у проектов Redmi файл, в котором описаны основные способы работы с проектом. -5018.62 5024.42 SPEAKER_00 И также недавно Nuget добавил возможность запихивания Redmi как раз в пакет. -5024.42 5026.74 SPEAKER_00 Мы об этом тоже говорили в каком-то выпуске. -5026.74 5043.98 SPEAKER_00 То есть для того, чтобы пользователь мог искать ваш пакет, например, в Visual Studio или в Rider, и когда он найдет пакет, щелкнул на него, у него в этот момент показывается Redmi, в который красиво с форматированием, может быть даже с картинками, с графиками рассказывается про вашу прекрасную библиотеку. -5043.98 5050.10 SPEAKER_00 Вот такие Redmi тоже сейчас добавляют в пакеты. -5050.10 5058.82 SPEAKER_00 И обычно тот Redmi файл, который лежит у вас в GitHub репозитории, он не очень соответствует тому Redmi файлу, который вам хотелось бы видеть в этом пакете. -5058.82 5065.70 SPEAKER_00 Например, в репозитории обычно сначала находятся секции о том, как склонировать репозиторий, как его сбилдить. -5065.70 5073.06 SPEAKER_00 В конце там находится какое-нибудь "Спасибо нашим контрибьюторам" или "Как законтрибьютировать наоборот в этот гид репозитории". -5073.06 5085.06 SPEAKER_00 Когда мы читаем Redmi про Nougat пакет, естественно там не должно быть никакой фразы о том, как склонировать репозиторий или как законтрибьютировать в репозитории, потому что мы находимся в контексте Nougat пакета, нет там никакого репозитория. -5085.06 5098.82 SPEAKER_00 И вот чтобы победить такую некрасивость, Nougatizer поддерживает query к MD файлам, который позволяет достать определенную секцию. -5098.82 5107.14 SPEAKER_00 Например, вы можете сказать "Дай мне Redmi файл", секцию только "Usage", секция это то, что с таким заголовком идет. -5107.14 5120.06 SPEAKER_00 А потом добавим в конце из документов футер для моего пакета, и тогда он добавит какую-то определенную часть, которая будет только в пакете, но не будет в Redmi на очередном гидхаб репозитории. -5120.06 5124.70 SPEAKER_00 В общем, вот такие действия может творить и при этом придавать красивость. -5124.70 5137.02 SPEAKER_00 Как я, наверное, не сказал, Nougatizer распространяется с помощью Global Tools, это позволяет ему легко и быстро кроссплатформенно вписаться в любой ваш проект. -5137.02 5142.38 SPEAKER_00 Его нужно запускать из Project Directory. -5142.38 5152.66 SPEAKER_00 Интересный момент, что если его просто запустить без всяких параметров, он выдаст вам быстрый отчет того, какие пакеты он сделает из этого репозитория, то есть какие пакеты будут сгидлены. -5152.66 5166.40 SPEAKER_00 Он вам удобно покажет там файлы, всю структуру, версию, какую DLL он куда положит, по какому пути, в какой платформе она будет, по каким папочкам он это все разложит. -5166.40 5168.18 SPEAKER_00 И это все будет показано очень быстро. -5168.18 5180.34 SPEAKER_00 Там специально есть оптимизация, которая использует не настоящую компиляцию для того, чтобы понять все эти зависимости, а специальную IDE, Debug Time, по-моему, или Debug Time компиляция, вот как-то так называется. -5180.34 5187.18 SPEAKER_00 То есть это специальный хак, специальная компиляция для IDE, которая используется для того, чтобы быстрее в верхнем уровне понять, что происходит. -5187.18 5198.14 SPEAKER_00 В общем, этот луза тоже это делает для того, чтобы мгновенно выдать вам вот такой красивый большой полноценный отчет с предсказуемым набором пакетов и с предсказуемой структурой, которая у вас там будет в результате. -5198.14 5209.18 SPEAKER_00 В общем, если вы страдаете от того, что у вас очень сложный проект, который упаковывается в очень сложные пакеты, то можно посмотреть на этот инструмент, кажется, что он вам может хорошо помочь. -5209.18 5226.74 SPEAKER_00 Я же, наверное, в своих проектах обычно стараюсь такого не делать, хотя у меня есть очень сложные Get пакеты, но как-то я обходился стандартным форматом, собирал их с помощью специального Nuspec файла, и тоже вроде как так было все хорошо, не вижу причин не меняться. -5226.74 5242.22 SPEAKER_02 Я более того скажу, я, по-моему, ни разу не пользовался возможностью сборки из Cessproj на прямую, я всегда писал Nuspec отдельный, где ты четенько можешь указать прям конкретный список файлов, конкретный там, что куда положить, какой редми взять и вот это все. -5242.22 5244.22 SPEAKER_00 Ну это ты просто старпер же. -5244.22 5245.22 SPEAKER_00 Спасибо. -5245.22 5248.30 SPEAKER_01 Когда появился новый, не знаю, обращайтесь, это -5248.30 5254.74 SPEAKER_00 же когда появился новый SDK формат, то как бы все стали собирать именно из Proj файлов для того, чтобы как раз вот эти Nuspec никому не были нужны. -5254.74 5257.82 SPEAKER_00 Ну это работает, естественно, только когда тебе нужно один к одному. -5257.82 5269.18 SPEAKER_00 Как только ты хочешь из нескольких проектов собрать один пакет, то там мы возвращаемся к нашему Nuspec, и я рад, что они были не забросили, не деприкетили, а до сих пор поддерживают, и это прекрасная мощная штука, которая часто выручает. -5269.18 5276.70 SPEAKER_02 Ну и продолжим пользоваться по старинке, как и пользовались пока не отделят и не забудут. -5276.70 5279.58 SPEAKER_02 Давай дальше, пойдем к теме. -5279.58 5298.98 SPEAKER_02 Я на самом деле не планировал ее исходно включать в этот подкаст, но раз уж вышел райдер 2022.3, и буквально за пару дней, наверное, до записи подкаста или около того, то решил включить, потому что это все очень подходит под те темы, которые мы сегодня обсуждаем. -5298.98 5311.98 SPEAKER_02 Итак, новый райдер 2022.3, там вышло большое количество E-апов, и теперь у нас поддержан .NET 7, то есть если вы хотели попробовать новый SDK, то вот как раз таки ставьте 2022.3, там будет поддержка седьмого .NET. -5311.98 5317.82 SPEAKER_02 Поддержан VSL 2, туда можно заканчиваться для Remote Development прямо из райдера. -5317.82 5328.02 SPEAKER_02 Можно теперь, ну мы про это рассказывали, таскать Tool Window к окошкам, которые вы вытащили из основного окна. -5328.02 5329.58 SPEAKER_02 Ты, кстати, пробовал, это реально работает? -5329.58 5332.42 SPEAKER_02 Я не пробовал еще, я обновился, но я не попробовал еще. -5332.42 5334.18 SPEAKER_02 Блин, клевый фича. -5334.18 5335.18 SPEAKER_02 Надо будет попробовать. -5335.18 5345.66 SPEAKER_02 Но я на самом деле очень редко пользуюсь многомониторной конфигурацией для редактирования кода, у меня всегда райдер, ну то есть если я работаю, то это максимальный расширяющий рендер на основном экране и все. -5345.66 5347.38 SPEAKER_02 Я второй монитор не использую. -5347.38 5350.10 SPEAKER_00 Да-да, это, конечно, для нескольких мониторов. -5350.10 5355.46 SPEAKER_02 Вот, то есть я не умею программировать на двух мониторах, мне нужен один, и по центру. -5355.46 5358.94 SPEAKER_01 Для решения твоей проблемы три монитора. -5358.94 5360.94 SPEAKER_01 Я пробовал, отличная штука. -5360.94 5361.94 SPEAKER_02 Да, возможно, возможно. -5361.94 5366.50 SPEAKER_02 Вопрос, как их подключать, да, ну в общем, там возникают другие вопросы, куда их ставить на стол. -5366.50 5379.42 SPEAKER_02 Так, новый Toolbar, ну вообще новый, немножко такой UI-чик, про который говорили, может быть, вы слышали в других разных EDG'ках, теперь он есть в райдере, там более чистенький и так далее. -5379.42 5384.30 SPEAKER_02 Тоже еще, я буквально сегодня обновился, поэтому не пробовал еще полностью, но так выглядит приятно. -5384.30 5386.34 SPEAKER_02 Посмотрю, как будет в работе. -5386.34 5396.86 SPEAKER_02 Поддержаны всякие новые C# фичи, там UTF-8 литералы, файл local type, статик abstract member, rostering literals, ref field, scope, значит, ключевое слово, ну и так далее. -5396.86 5400.46 SPEAKER_02 В общем, все, что мы знаем про C# 11, должно быть поддержано. -5400.46 5415.26 SPEAKER_02 В Blazor, сервер APOC завезли hot reload, теперь можно делать, завезли NuGet Central Package Management, и появилось early preview для ARM64 под Windows и Linux. -5415.26 5422.62 SPEAKER_02 Кроме того, DotMemory, теперь который встроенный в райдере и встроенный в DotMemory, стал доступен на Linux и на Mac. -5422.62 5429.66 SPEAKER_02 Короче, ну, много всяких разного, улучшений, грубо говоря, по сути, там, 7 из DK, новый UI-чик и Performance. -5429.66 5432.54 SPEAKER_02 Значит, с Performance тема отдельная. -5432.54 5446.30 SPEAKER_02 У нас на самом деле была статья, которая была опубликована в блоге nDependa довольно давно, от автора, собственно, этого самого nDependa, про то, что, а давайте сравним Performance райдера и Visual Studio. -5446.30 5452.66 SPEAKER_02 Ну, типа, много кто живет в райдере, много кто живет в Visual Studio, много кто живет в Visual Studio и в ReSharper. -5452.66 5454.82 SPEAKER_02 Давайте поймем, кто быстрее, кто медленнее. -5454.82 5457.82 SPEAKER_01 Ну, всем же известно, что ReSharper тормозит, правильно? -5457.82 5459.98 SPEAKER_02 Да, ясное дело, ReSharper тормозит, но вопрос на сколько. -5459.98 5469.22 SPEAKER_02 И на момент публикации статьи студия была версии 17.24, райдер был версии 20.22.1.2. -5469.22 5478.82 SPEAKER_02 Все это тестировал товарищ на своем компе, это Xeon с 2.7 ГГц, с 64 ГГ памяти, так что кажется памяти должно хватать IDE. -5478.82 5483.10 SPEAKER_02 Ну, понятно, SSD, винтовая десятка, вот это все. -5483.10 5488.70 SPEAKER_02 Тестировал это на двух Solutions, на nDependa, собственно, 38 проектов, примерно, ну, почти 6000 файлов. -5488.70 5494.58 SPEAKER_02 И есть такой Knob Commerce проектик, это 28 проектов и 5300 файлов. -5494.58 5507.22 SPEAKER_02 Сначала он замерял, сколько проходит времени до момента, когда мы просто берем и запускаем райдер или Visual Studio, не открывая никаких Solutions. -5507.22 5512.46 SPEAKER_02 Соответственно, студия чистая занимает 4 секунды, студия с ReSharper 6 секунд, райдер 5 секунд. -5512.46 5519.14 SPEAKER_02 Ну, окей, разница вроде небольшая, нормально, сойдет. -5519.14 5543.26 SPEAKER_02 Дальше если мы открываем nDepend Solution, это надо напомнить, примерно 6000 файлов, 38 проектов, то у студии это занимает 17 секунд, студии с ReSharper это занимает 20-25, то есть он называется First Responsive и Fully Responsive, то есть хоть как-то с ним можно работать через 20 секунд, со студией, в смысле с ReSharper, а так полноценно работать уже через 25. -5543.26 5546.58 SPEAKER_02 Райдер же занимает 13, то есть быстрее, чем студия на 4 секунды. -5546.58 5549.78 SPEAKER_01 Это на холодную, да, то есть кэширование всегда включено? -5549.78 5558.10 SPEAKER_02 Я подожди, ну, он говорил, что технология замеров это типа я много-много-много раз открывал, ну и брал, там, выкидывал аутлайер и брал что-то средненькое. -5558.10 5561.78 SPEAKER_00 А, понятно, значит кэш уже был и он просто переездался. -5561.78 5573.98 SPEAKER_02 Да-да-да, то есть это не полностью абсолютно свежий, свежесклонированный Solution, который ты вообще в жизни никогда не видел, нет, это твоя обычная рабочая работа, то есть ты просто берешь Solution, с которой ты в среднем работаешь и его там открываешь. -5573.98 5583.22 SPEAKER_02 А билд не сильно отличается, там 22, 22,3, 23 секунды, в общем, на билд можно не смотреть. -5583.22 5589.46 SPEAKER_02 С Solution, но в Commerce там чиселки примерно похожие, Rider секунд на 5 быстрее. -5589.46 5612.26 SPEAKER_02 И общие выводы у него были следующие, что как бы в целом Rider выглядит более респонсив, и это понятно почему, потому что у него UI-чик отдельно, а ReSharper, да, в бэкэндах смысле, который, ReSharper отдельный, это отдельный процесс, который там где-то там в бэкграунде фигачит, анализирует все, а UI-чик становится доступным быстрее, несмотря на то, что это Java. -5612.26 5623.06 SPEAKER_02 А в студии, когда студия с ReSharper, ну ReSharper, он хоть и потихонечку выносится в бэкграунд, там все-таки довольно много всего все еще происходит в самой студии, ну в смысле в основном потоке, и поэтому медленнее. -5623.06 5634.22 SPEAKER_02 Его очень огорчает, в принципе, время старта пустого, пустой IDE, что студии, что Rider, то есть 4-5 секунд, это прям как бы долго. -5634.22 5635.98 SPEAKER_02 Что там запускаться? -5635.98 5641.54 SPEAKER_02 Ну так, было бы круто, если пустая студия или пустой Rider запускалась бы за секунду, это было бы норм. -5641.54 5644.26 SPEAKER_02 Сейчас он действительно довольно долго запускается. -5644.26 5662.66 SPEAKER_02 И его вывод в статье такой, что ну как бы да, Rider быстрее, поэтому если вы как бы, вам нужна скорость, пользуйтесь Rider, но если вам нужны старые фреймворки, да, там Rider до сих пор не поддерживает WinForms на DotNet Core, ну и всякие другие типа там WCF и прочее, если вы чем-то таким пользуетесь, ну наверное вам придется жить в студии. -5662.66 5673.02 SPEAKER_02 Это одна из причин, почему я сейчас много живу в студии, я сейчас много работаю с WinForms, а Rider их не очень умеет на DotNet Core, ну в смысле он их не умеет. -5673.02 5676.02 SPEAKER_02 Отдельный вопрос, зачем WinForms на DotNet Core, но вот так сложилось. -5676.02 5701.26 SPEAKER_02 Я взял и когда я готовился, я попробовал это дело на одном из Solutions, который у меня был под рукой, который я довольно регулярно открываю, это 24 CS Proj, а там примерно 5000 CS File Lake, студия у меня без ReSharper, ReSharper у меня в принципе не стоит, у меня получилось, что студия без ReSharper запускалась 13 секунд открывалась, Solution я проверял это до момента, когда я смогу сказать Ctrl+T и что-нибудь поискать. -5701.26 5705.70 SPEAKER_02 То есть студия заняла 13 секунд, у Rider это заняло 16 секунд. -5705.70 5708.66 SPEAKER_02 То есть у меня Rider открывался дольше. -5708.66 5709.66 SPEAKER_02 Неожиданно. -5709.66 5710.66 SPEAKER_02 Да. -5710.66 5718.06 SPEAKER_02 То есть, ну это студия без ReSharper, то есть вот у меня как-то так, может они кэши как-то более оптимально раскладывают, я не знаю. -5718.06 5723.02 SPEAKER_02 И вот как раз вышел 22.3, обновленный Rider, который быстрее. -5723.02 5724.50 SPEAKER_02 Что они там сделали? -5724.50 5730.18 SPEAKER_02 Они завязали побольше от CPU ядер для сканирования файликов при старте. -5730.18 5737.02 SPEAKER_02 Они автоматически при инсталляции теперь себя добавляют в исключение Windows Defender, если мало ли кто-то этого не делает, то очень рекомендуется. -5737.02 5739.26 SPEAKER_02 Прям, теперь они сами это делают. -5739.26 5743.54 SPEAKER_02 А лучше всю эту папочку с исходниками тоже туда добавьте, иначе будет тормозить. -5743.54 5758.62 SPEAKER_02 ReSharper в бэкэнде, который у них крутится, стал побыстрее за счет того, что, по сути ReSharper как работает у них, он грузит всякие модули, просто сканируя все папочки, ну все длфки-папочки в округе и пытаясь понять, что нужно подгрузить. -5758.62 5766.14 SPEAKER_02 Вот они теперь там анализируют кастомные свои атрибуты, точнее всю нужную методат, но они пихают в свои кастомные атрибуты, за счет чего это побыстрее работает. -5766.14 5769.54 SPEAKER_02 Ну пооптимизировали memory traffic. -5769.54 5775.74 SPEAKER_02 В ReSharper бэкэнде стали использовать серверный вариант ГЦ, от этого получше перформанс. -5775.74 5785.90 SPEAKER_02 И еще, мы не обсуждали в подкасте, может быть как-нибудь обсудим отдельно, что вышел уже флит для C#, от JetBrains. -5785.90 5793.46 SPEAKER_02 И для того, чтобы штука эта работала, им пришлось написать новый C# парсер, который вообще никак не связан с ReSharper. -5793.46 5812.34 SPEAKER_02 Он такой типа легковесный и все дела, и поэтому теперь райдер работает таким образом, что пока не пригрузился полноценный ReSharper на бэкэнде, у тебя есть уже какой-то работающий на фронте простенький C# парсер, ну простенький, но при этом он что-то умеет, поэтому у тебя есть ощущение, что можно работать раньше. -5812.34 5821.30 SPEAKER_02 И вот в моем тесте до момента, когда я могу сказать Ctrl+T, у меня появляется Solution Explorer, я могу сказать Ctrl+T, вместо 16 секунд стало 11 секунд. -5821.30 5824.06 SPEAKER_02 О, это же заметно, это хорошо. -5824.06 5833.82 SPEAKER_02 На новой версии, да, то есть тут у меня на конкретном одном Solution, на конкретном одном моем компе, в абсолютно не научном тесте, назовем это так, видна экономия в 5 секунд. -5833.82 5842.18 SPEAKER_02 Я не знаю, буду ли я видеть это в каждодневной работе, я довольно часто меняю Solution, запускаю райдер, закрываю райдер и так далее, посмотрим. -5842.18 5844.86 SPEAKER_02 Но кажется, что действительно перформанс там стал получше. -5844.86 5856.18 SPEAKER_00 Отлично, будем смотреть, как развивается, как друг друга перегоняет, может студия это тоже подстегнет, пересмотреть что-то в своих запусках и кэшированиях. -5856.18 5859.58 SPEAKER_02 Да, ну что, давай последнюю тему обсудим. -5859.58 5868.50 SPEAKER_00 Да, темка подслушана, я расскажу, что я такого интересного нашел за это время среди наших коллег. -5868.50 5872.18 SPEAKER_00 Прежде всего хотелось бы отметить подкаст «Подлодка. -5872.18 5875.70 SPEAKER_00 273 выпуск» про интересную тему «Оценки не нужны». -5875.70 5884.30 SPEAKER_00 Потому что я очень часто сталкиваюсь с людьми, которые считают, что почему-то оценки нужны и очень много менеджеров хотят странного, они хотят каких-то сроков. -5884.30 5892.86 SPEAKER_00 В общем, и этот выпуск интересен тем, что он эту тему обсуждает довольно многогранно и разбирает там частые кейсы. -5892.86 5904.70 SPEAKER_00 В общем, например, чем оценка отличается от прогноза, это тоже для многих будет откровением, что мы называем не теми словами, которые должны называть всю эту терминологию, можно ли просто работать, а не вот это вот все. -5904.70 5913.34 SPEAKER_00 А как делать там осознанную разработку или выдумывать против того, чтобы выдумывать цифры и натягивать какие-то оценки на какие-то мифические сроки. -5913.34 5922.78 SPEAKER_00 Еще интересное рассуждение, как цепочка оценка, синдром самозванца и стресс приводят людей к выгоранию. -5922.78 5931.22 SPEAKER_00 Тоже никогда не прослеживал такую вещь, но оказывается, вот те команды, у которых есть какая-то оценка, какие-то строки, они чаще выгорают. -5931.22 5933.50 SPEAKER_00 Что со всем этим делать? -5933.50 5942.74 SPEAKER_00 И на куче конкретных примеров рассказывается очень много практических кейсов, какие-то научные пытаются к этому выводы все подвести и так далее. -5942.74 5963.58 SPEAKER_00 В общем, если вас интересуют оценки или если вам нужно каким-то образом убедить ваших менеджеров, что оценки это не всегда хорошо и может быть конкретно в вашей ситуации, они совсем и не нужны, то есть попытаться хотя бы это сделать, попробуйте послушать подкасты, много интересных, есть аргументов, с помощью которых можно дальше пообщаться с вашим руководством. -5963.58 5968.10 SPEAKER_00 Далее подкаст «Проветримся», ведущий подкаст Иван Ямщиков. -5968.10 5978.38 SPEAKER_00 Я Ваню очень много слушаю, очень много смотрю, очень много люблю и в принципе везде, где мне встречается Иван Ямщиков, я пытаюсь все эти выступления посмотреть. -5978.38 5990.74 SPEAKER_00 Кто не знает, это исследователь в основном искусственного интеллекта, он работал в Яндексе, в Эбби, он доцент высшей школы экономики, у него там еще куча всяких регалий международных. -5990.74 5998.74 SPEAKER_00 В общем, это такой нормальный ученый, можно так сказать, и уже после этого популяризатор искусственного интеллекта. -5998.74 6019.70 SPEAKER_00 Он очень интересно рассказывает вообще любую техническую тему, что бы он не затронул, но в частности в этом подкасте к нему приходит огромное число различных людей, которые увлекаются теми или иными технологиями, и кстати не только технологиями, и он с ними разговаривает с кем-то в формате интервью, с кем-то в формате просто дружественной беседы, в зависимости от гостя. -6019.70 6024.38 SPEAKER_00 Темы выбираются всегда интересные, обычно это околотехнические какие-то темы тоже. -6024.38 6036.22 SPEAKER_00 В общем, Ваня чрезвычайно начитан, чрезвычайно интересно говорит, у него прекрасно воставленная речь, и тот человек, с которым безусловно всегда интересно и пообщаться, и послушать его подкасты. -6036.22 6041.58 SPEAKER_00 В качестве примера, что у него последний сезон, например, он записывал про медитацию. -6041.58 6071.58 SPEAKER_00 Как я уже сказал, до этого у него были абсолютно технические все вещи, в основном в этом сезоне, даже в прошлом сезоне, можно сказать, он взял тему медитации, разобрал её, провёл несколько уроков медитации в своём подкасте, обсудил в то же самое время клёвые книги по психологии, о том, как их можно применить к нашей IT-жизни, о том, как относиться к окружающему миру. -6071.58 6074.98 SPEAKER_00 В общем, всё в этой теме разобрал, тоже очень хорошо. -6074.98 6088.70 SPEAKER_00 И, по-моему, сейчас уже у него начался новый сезон, когда он вернулся уже к техническим темам, недавно с Нобелевским лауреатом по физике общался, вот тоже очень интересный подкаст. -6088.70 6101.82 SPEAKER_00 Короче, если кому-то интересно встать в сторону популяризации физики искусственного интеллекта и прочего вот этого научного нормальным языком среди нормальными людьми и гостями, вот всячески советую Ивана. -6101.82 6107.10 SPEAKER_00 И опять, где бы его доклад не увидели, обязательно поэкспериментируйте, посмотрите, думаю, вам зайдёт. -6107.10 6113.82 SPEAKER_00 Так, и последняя на рассылочка, которую я хотел с вами поделиться, это Кадаза. -6113.82 6119.90 SPEAKER_00 Недавно мы в нашем чатике открыли для себя этот забавный ресурс, это ролики про обучение на C#. -6119.90 6138.78 SPEAKER_00 В принципе, обучение на C# на русском языке, их есть много в интернете, это даже не самый популярный, я так думаю, но что выделяет его среди всех остальных, это у него есть шоты ютубовские, это 30-секундные ролики, которые вам за 30 секунд рассказывают какую-то тему. -6138.78 6150.82 SPEAKER_00 И там очень клёвые темы, например, там топ 10 вещей в АСП.нете, которые должен знать каждый разработчик, типа как устроить перформанс, или как за 30 секунд объясняется, как устроен семафор. -6150.82 6154.78 SPEAKER_00 В общем, такие вещи, которые начинающему разработчику просто must have. -6154.78 6161.94 SPEAKER_00 И как бы потратить 30 секунд, пока ты там, не знаю, едешь где-нибудь в лифте или что-то в этом духе, каждый способен. -6161.94 6165.38 SPEAKER_00 Ролики классные, интересные, записаны прикольно. -6165.38 6169.98 SPEAKER_00 И ещё одна отличная фишка этого канала, это в том, что там прекрасная графика. -6169.98 6177.38 SPEAKER_00 Я не знаю, в чём это делается, если вы вдруг знаете, в каких редакторах или с помощью каких средств, инструментов, обязательно напишите нам в комментарии. -6177.38 6184.26 SPEAKER_00 В общем, графика там обалденная, то есть это всё показывается с цветной анимацией, красиво, наглядно, по делу. -6184.26 6190.54 SPEAKER_00 И что ещё раз прибавляет пользы того материала, который там и так очень хорошо подаётся. -6190.54 6203.82 SPEAKER_00 В общем, если вы начинающий разработчик или просто вам интересно, как можно сделать современные интересные ролики про программирование, красочно, бодро и занимательно, в общем, попробуйте, посмотрите на YouTube канал Кадаза. -6203.82 6207.26 SPEAKER_02 Да, интересно, там причём не только короткие, там есть и более длинные. -6207.26 6208.26 SPEAKER_02 Короче, всё. -6208.26 6215.22 SPEAKER_00 Да, да, длинные тоже с прекрасной графикой, с отличным объяснением, тоже миллион просмотров, поэтому да. -6215.22 6223.94 SPEAKER_02 Ну и там есть Telegram-каналчик, в котором чуть более часто выходят какие-то новости, хотя они в видеоформате, так что да, может быть действительно будет интересно, если вы изучаете C#. -6223.94 6232.22 SPEAKER_02 Ну что, на этом, наверное, на сегодня надо нам заканчивать, мы с тобой уже сидим почти 3 часа, всё это пишем, готовим -6232.22 6234.82 SPEAKER_00 и так далее, так что… Да, уже скоро утро. -6234.82 6240.70 SPEAKER_02 Ну ещё не утро, но да, на часах час ночи, чтобы вы знали, как мы всё это пишем. -6240.70 6258.90 SPEAKER_02 Так что да, сегодня мы посмотрели на то, быстрый ли у нас S/Panet Core, подумали, как раскладывать файлики в новых проектах с минимальной API, при этом давайте все будем использовать новый MemoryPack Serializer, который ещё сам супербыстрый, собирать это всё GitHub-экшенами на GitHub. -6258.90 6276.06 SPEAKER_02 А если вы собирались собрать .NET, то к вашим услугам теперь есть монолитный репозиторий всего .NET в месте, если же вы собираете ваши Nuget пакеты, берите Nugetizer, делайте это всё в райдере, который стал ещё быстрее, особенно по сравнению с Visual Studio, да ещё и с ReSharper. +1008.68 1031.72 "Игорь Лабутин" Так что для каждой, для каждого подхода к своей задачке, но интересно вот так вот почитать, что народ думает и что же вот тот самый техэмпауэр, в который все верят и говорят, о, техэмпауэр, мы заняли какое-то n-ное место, на самом деле надо внимательно смотреть, с каким бенчмарком вы заняли и какое из 15 мест, какое из 15 ваших бенчмарков. +1031.72 1038.56 "Анатолий Кулаков" И что в это время еще там делали другие и как читерили они и вообще все вместе как это юзабельно. +1038.56 1052.16 "Анатолий Кулаков" Да, действительно, когда начинаешь работать ради цифр, когда в твоих метриках устанавливаются какие-то критерии, какие-то чиселки, то начинаешь работать на чиселке, а не на то, чтобы сделать хорошо свою работу. +1052.16 1061.24 "Анатолий Кулаков" Так вот типичное доказательство и здесь, когда тебе выставили какой-то бенчмарк, то ты делаешь фреймворк для того, чтобы пройти бенчмарк, а не для того, чтобы сделать быстрый фреймворк. +1061.24 1063.80 "Анатолий Кулаков" Это грустно, конечно, друзья. +1063.80 1070.52 "Анатолий Кулаков" Надеюсь, что все-таки мы дойдем до каких-нибудь нормальных циферок с нормальным реалистик кодом, чтобы было не стыдно. +1070.52 1074.64 "Игорь Лабутин" Ну слушай, 184 тысячи реквестов в секунду, мне кажется, +1074.64 1075.64 "Игорь Лабутин" не так, чтобы стыдно. +1075.64 1088.80 "Анатолий Кулаков" Это неплохо, да, безусловно, неплохо, но опять же, хотелось бы точно такой же подход сравнить и на других языках, то есть с точно таким же уровнем плейнинга, таким же уровнем роутинга, в общем, как-то научиться это все хотя бы близко подгонять по функциональности. +1088.80 1093.42 "Игорь Лабутин" Ну языки настолько разные, что боюсь, что прям идеально подогнать не сможем. +1093.66 1097.90 "Анатолий Кулаков" Да ладно, для Java странно скомпилируется один в один просто. +1097.90 1105.06 "Игорь Лабутин" Нет, Java, да, я согласен, то есть там, грубо говоря, ну там спринговая есть наверняка реализация, я не смотрел, где она там находится, но наверняка есть. +1105.06 1109.94 "Игорь Лабутин" То есть понятно, что нужно сравнивать, грубо говоря, мейнстрим, там, дотнета с мейнстримом Java, но… +1109.94 1112.82 "Анатолий Кулаков" Да, то есть действительно, что люди переиспользуют каждый день. +1112.82 1118.22 "Анатолий Кулаков" Вот взять прям по процентам, и мы видим, что там 90% всех ASP приложений, то есть всех веб-приложений – это ASP.NET. +1118.22 1124.10 "Анатолий Кулаков" Вот значит, и в Java берем там 100% всех веб-приложений – это Spring, и погнали значит их сравнивать. +1124.10 1127.98 "Анатолий Кулаков" И вот это должно более-менее дать какую-то реалистику картину. +1127.98 1129.98 "Игорь Лабутин" Ну, наверное, да. +1129.98 1131.98 "Игорь Лабутин" Ладно, давай дальше. +1131.98 1132.98 "Игорь Лабутин" Да, давай. +1132.98 1134.58 "Анатолий Кулаков" У нас сегодня много тем. +1134.58 1144.14 "Анатолий Кулаков" Не отходя далеко от веба, интересная статья тут есть про рассуждение немножко про Minimal API, нафига он вообще нужен, и зачем он появился, и как его можно использовать. +1144.14 1150.82 "Анатолий Кулаков" Вот ты как думаешь, Minimal API нам все еще нужен, или это была неудачная попытка, и можно его закапывать? +1150.82 1164.30 "Игорь Лабутин" Знаешь, я в работе им, так скажем, не пользуюсь, а в целом я вполне, наверное, одобряю, что он есть, но я пока не понимаю, как я его буду использовать. +1164.30 1171.54 "Игорь Лабутин" То есть вот я, это должны быть совсем минимальные какие-то компоненты, а я небольшой любитель прямо микро-микросервисов. +1171.54 1174.30 "Игорь Лабутин" То есть я скорее любитель просто сервисов. +1174.30 1175.30 "Игорь Лабутин" Трех рутов, да? +1175.30 1176.30 "Игорь Лабутин" Да-да-да. +1176.30 1185.22 "Игорь Лабутин" То есть нет, если по какой-то логике деление, мне понадобится сделать сильно маленький сервис с одним endpoint, то наверное да, я возьму Minimal API. +1185.22 1186.22 "Игорь Лабутин" Почему нет? +1186.22 1187.22 "Игорь Лабутин" Вот. +1187.22 1202.14 "Игорь Лабутин" И я так понимаю, что одна из целей вот этого Minimal API была попытка собрать что-то, что не так завязано нам огромную магию рефлексии контроллеров, и вот этого всего огромного хозяйства под названием MVC. +1202.14 1212.54 "Анатолий Кулаков" Может быть, но видишь, смотря на развитие Minimal API, особенно в последнем дотнете, который недавно зарелизался, невольно начинаешь наблюдать, что вся эта магия рефлексии проникает туда. +1212.54 1221.38 "Анатолий Кулаков" То есть ты легко можешь заинжектировать туда любой сервис в скобочке какой захочешь, а логерю можно засунуть те же самые тайп-мароты, http-контексты и это все. +1221.38 1226.10 "Анатолий Кулаков" То есть точно такая же рефлексия, только не через контроллер к тебе придет, а через делегат. +1226.10 1227.10 "Анатолий Кулаков" Ну кажется, какая разница. +1227.10 1229.02 "Игорь Лабутин" Ну может быть, может быть. +1229.02 1238.02 "Игорь Лабутин" В общем, для чего-то это точно делается, есть какие-то use-case, я пока для себя их не нашел, но у меня, видимо, и сценарий пока не подходящий. +1238.02 1249.02 "Анатолий Кулаков" Ну да, тема мутная, вот чтобы ее немножко прояснить, давайте попробуем обратиться к одному из авторов, который примерно понимает, как это использовать, зачем это нужно и как это применить. +1249.02 1256.02 "Анатолий Кулаков" Самое главное, не в каких-то hello world, которые вы хотите показать студенту в одном файлике, а в более-менее нормальных продакшн-системах. +1256.02 1265.82 "Анатолий Кулаков" И статья как раз-таки называется тоже довольно интересно, а не пора ли нам передумать структуру наших проектов с новым дотнетом. +1265.82 1268.58 "Анатолий Кулаков" Давайте посмотрим, что же здесь можно передумать. +1268.58 1270.58 "Анатолий Кулаков" Для тех, кто пропустил, начнем с начала. +1270.58 1278.14 "Анатолий Кулаков" Во времена дотнет 6 вышла такая прекрасная штука, новый API, который называется minimal web API. +1278.14 1289.42 "Анатолий Кулаков" Этот специальный способ, назовем его так, позволяет вам писать, обрабатывать web-реквесты, возвращать web-респонсы и все это делать абсолютно без контроллеров. +1289.42 1292.46 "Анатолий Кулаков" Кажется, что это единственная фишка избежать контроллеров. +1292.46 1300.66 "Анатолий Кулаков" Почему они захотели этого избежать, то есть действительно ли контроллеры такие медленные, или такие большие, или такие некрасивые, то есть вот это никакой предпосылки не было. +1300.66 1303.90 "Анатолий Кулаков" Просто команда села и сказала, вот смотрите, как мы умеем миленько писать. +1303.90 1321.50 "Анатолий Кулаков" С тех самых пор вкладывается огромное количество усилий в minimal API, добавляются различные методы расширения, подключается там аутентификация, авторизация, подключается dependency injection, прочие там навешиваются свагерские атрибуты и в общем он превращается в полноценную замену подхода с контроллерами. +1321.50 1332.82 "Анатолий Кулаков" А разница казалось бы практически минимальная, та же самая однострочка с кучей атрибутов и с кучей fluent интерфейсов заменялась бы просто-напросто одним контроллером с теми же самыми атрибутами. +1332.82 1335.50 "Анатолий Кулаков" То есть разница чисто техническая. +1335.50 1337.46 "Анатолий Кулаков" Другой пока нам не приводили. +1337.46 1339.50 "Анатолий Кулаков" Ну будем работать с тем, что есть. +1339.50 1351.10 "Анатолий Кулаков" И даже если новый шаблон раньше создавали в бета-версиях первых .NET, то по умолчанию он использовал minimal API, ISP.NET template использовал minimal API. +1351.10 1360.94 "Анатолий Кулаков" Сам от этой идеи откатились, вроде начали генерить большой нормальный стандартный, но периодически возвращаются и может быть даже официально вернутся к этому подходу. +1360.94 1381.66 "Анатолий Кулаков" Если же мы используем minimal API template ISP.NET, в то же самое время к нам прилетает сразу top-level statement, то есть у нас нет никакого program, класса program, у нас сразу файл начинается с того, что у нас появляется application builder и мы погнали там строить web application и мапить ему всякие роуты. +1381.66 1386.42 "Анатолий Кулаков" И буквально там из пяти строчек мы можем собрать полноценный веб-сервер. +1386.42 1392.54 "Анатолий Кулаков" И самое интересное в этом minimal API будет, это как раз маппинг этих роутов. +1392.54 1401.10 "Анатолий Кулаков" То есть мы там можем писать map get, передать туда роут, по которому мы хотим, чтобы наш делегат вызывался и передать непосредственно сам делегат. +1401.10 1405.58 "Анатолий Кулаков" То есть что будет происходить, когда к нам придет запрос, например, вернуть фразу hello world. +1405.58 1407.82 "Анатолий Кулаков" Этого в принципе вполне достаточно. +1407.82 1419.06 "Анатолий Кулаков" Вот из таких вот делегатиков, даже я бы сказал пар, роут плюс делегатик, плюс обработчик входящего запроса и состоит minimal API. +1419.06 1427.30 "Анатолий Кулаков" Дальше идут небольшие усложнения, там навешивается, как я уже сказал, интерфейсом или атрибутом всяким возможностям, но суть его остается на месте. +1427.30 1440.90 "Анатолий Кулаков" При этом с новым подходом, с minimal API и top-level statement у нас нет program.cs, у нас нет startup.cs, у нас нет методов, которые конфигурируют сервисы, у нас нет папочки с контроллерами, в которых лежит куча контроллеров. +1440.90 1444.86 "Анатолий Кулаков" У нас там есть один единственный файлик, в который можно войти и все это написать. +1444.86 1447.14 "Анатолий Кулаков" Кажется красиво, мило и прекрасно. +1447.14 1453.90 "Анатолий Кулаков" Но теперь давайте рассуждать в терминах как раз-таки нормальной реалистичной разработки. +1453.90 1457.22 "Анатолий Кулаков" Что будет, если мы захотим добавить туда новую функциональность? +1457.22 1462.30 "Анатолий Кулаков" Допустим, мы хотим добавить новый контроллер, новый обработчик, новый роут. +1462.30 1476.06 "Анатолий Кулаков" По идее самый легкий способ, самый очевидный способ, который нас все подталкивает, это просто-напросто пойти в файлик program.cs, найти там вот этот наш web-аппликейшен и добавить к нему еще один map.get. +1476.06 1480.90 "Анатолий Кулаков" Передать туда еще один роут и передать туда еще один делегат и вот таким образом накидывать новые фичи. +1480.90 1492.70 "Анатолий Кулаков" Это очень просто, это очень понятно, но легко представить, что если у нас там будет большое число уже роутов, если их там будет десятки и может быть сотни, то этот файлик превратится в жуткое месиво. +1492.70 1500.94 "Анатолий Кулаков" Он будет мега грязным, он будет очень неподдержанным, он будет абсолютно неразборчивым и ничего там разобрать будет невозможно и работать с этим, поддерживать это никак нельзя будет. +1500.94 1509.86 "Анатолий Кулаков" В то же самое время, если бы у нас были контроллеры, то у нас там было бы 10 контроллеров по 10 методов и вполне реально такие проекты живут и даже намного больше. +1509.86 1521.06 "Анатолий Кулаков" И поэтому люди, смотрящие после настоящего production кода на вот это издевательство, они туда не очень лезут, в этот minimal API. +1521.06 1526.34 "Анатолий Кулаков" Другой подход, если нам нужно добавить новую кейт-фичу, это все-таки вернуться к нашим старым контроллерам. +1526.34 1532.78 "Анатолий Кулаков" Для этого нам понадобится в билдере всего лишь на все вызвать метод addControllers, который наверняка во многих ваших проектах уже есть. +1532.78 1538.22 "Анатолий Кулаков" И все, контроллеры будут знакомые, интересные и ими можно будет продолжать пользоваться так же, как и раньше. +1538.22 1544.14 "Анатолий Кулаков" Но у контроллеров автор выделяет две очень большие проблемы, которые он видит. +1544.14 1554.02 "Анатолий Кулаков" Во-первых, это то, что контроллеры группируются по техническому уровню абстракции, то есть так называемому не feature concern, а technical concern. +1554.02 1572.50 "Анатолий Кулаков" Когда мы в папочке с контроллерами храним отдельно контроллеры, в папочке с бизнес-моделями храним бизнес-модели, может быть даже вы видели, что у некоторых есть папочка интерфейс, они там хранят интерфейсы, в папочке с enum'ами - enum'чики, в папочке с делегатиками - делегатики и прочие вот такие глупости. +1572.50 1578.38 "Анатолий Кулаков" И в этом есть проблема, мы ее осмотрим немножко попозже. +1578.38 1595.26 "Анатолий Кулаков" И вторая проблема это в том, что несмотря на то, что ваш запрос может быть очень простым, допустим по какому-то простому роту вернуть hello world или более приземленный пример, это по статическому, то есть по понятному константному url health-чека, вернуть ответ, что да, сервис жив. +1595.26 1608.42 "Анатолий Кулаков" В общем, очень простая ситуация, очень элементарная, но для того, чтобы ее реализовать, вам нужно будет добавить в контроллер, вам нужно добавить action-метод, навесить там каких-то атрибутов, сделать там какой-нибудь return action result, еще что-то. +1608.42 1612.34 "Анатолий Кулаков" В общем, слишком много действий приходится делать для каких-то примитивных случаев. +1612.34 1621.50 "Анатолий Кулаков" То есть сложные вещи в контроллерах делаются сложно, это нормально, но легкие вещи там тоже делаются сложно, и вот это уже не очень нормально. +1621.50 1625.62 "Анатолий Кулаков" В этом заключается вторая проблема, которую автор видит как раз-таки в контроллерах. +1625.62 1630.94 "Анатолий Кулаков" А теперь давайте посмотрим, что же он предлагает, как он предлагает все эти дилеммы, все эти проблемы решить. +1630.94 1634.98 "Анатолий Кулаков" Итак, прежде всего вернемся к нашему technical concern. +1634.98 1648.54 "Анатолий Кулаков" Автор предлагает забросить традиционную модель директорий, про которую я уже чуть выше упоминал, и перевести ее из технологического аспекта более в структуру доменного моделирования. +1648.54 1661.06 "Анатолий Кулаков" То есть сгруппировать наши папочки не по той функции, которую они выполняют, не по интерфейсам, контроллерам и моделям, а сгруппировать их по доменам. +1661.06 1677.70 "Анатолий Кулаков" Группировка по доменам очень распространена, когда вы пишете domain layer, особенно если вы придерживаетесь DDD, вот там всегда domain layer обычно внутри себя содержит папочки именно с тем контекстом, который конкретно используется для определенных бизнес-моделей. +1677.70 1679.74 "Анатолий Кулаков" Также можно сделать и здесь. +1679.74 1687.34 "Анатолий Кулаков" То есть когда различные домены приложения превращаются в некую структуру папок. +1687.34 1692.26 "Анатолий Кулаков" И эти папки обычно называют фичами или также можно их назвать модулями. +1692.26 1693.26 "Анатолий Кулаков" Приведем пример. +1693.26 1699.58 "Анатолий Кулаков" Вместо контроллеров в вашем приложении появляется папочка, которая называется modulus. +1699.58 1713.26 "Анатолий Кулаков" И внутри этого модуля папочки, которые, например, для магазина могут называться корзина, могут называться заказы, какой-нибудь чек-аут, какой-нибудь юзер менеджмент или кабинет пользователя. +1713.26 1717.10 "Анатолий Кулаков" В общем, эти папочки делятся как раз по функциональности, что они делают. +1717.10 1721.02 "Анатолий Кулаков" И внутри этой папочки уже находится абсолютно все, что нужно. +1721.02 1730.50 "Анатолий Кулаков" Например, для того, чтобы работала корзина, нам нужен какой-нибудь модель этой корзины, нам нужны какие-то валидаторы этой корзины, какие-нибудь серилизаторы этой корзины и так далее. +1730.50 1732.18 "Анатолий Кулаков" Все это находится внутри одной папочки. +1732.18 1741.46 "Анатолий Кулаков" Вот именно в этом и заключается вся суть этого фичи фолдеров или модуль фолдеров. +1741.46 1745.18 "Анатолий Кулаков" Внутри такая папочка, как я уже сказал, называется в этих терминах модуль. +1745.18 1747.38 "Анатолий Кулаков" Давайте же посмотрим, из чего состоит модуль. +1747.38 1753.30 "Анатолий Кулаков" Прежде всего модуль состоит из файла, который регистрирует все зависимости, которые здесь есть. +1753.30 1760.06 "Анатолий Кулаков" В этом файле добавляются необходимые классы в DI контейнер. +1760.06 1762.02 "Анатолий Кулаков" То есть у него в этом файле есть два метода. +1762.02 1772.62 "Анатолий Кулаков" Первый метод добавляет все классы в DI контейнер, а второй метод как раз прописывает руты у нашего минималпиа, то есть маппит все эти руты с делегатиками. +1772.62 1788.14 "Анатолий Кулаков" То есть обзаведясь одним этим файлом, мы таким образом разделили все наши сотни делегатов, которые я приводил в начале, мы их разделили на 10 таких модулей, которые относятся к своему домену. +1788.14 1789.82 "Анатолий Кулаков" У каждого модуля будет всего-навсего 10 маппингов. +1789.82 1797.22 "Анатолий Кулаков" Это уже более чисто, это уже легко поддерживать, а само деление на модули дает нам очень хорошую например тестируемость. +1797.22 1804.50 "Анатолий Кулаков" Для того, чтобы протестировать какой-то класс корзины, мы уже не должны потаскивать все приложения, регистрировать там какие-то непонятные зависимости. +1804.50 1813.62 "Анатолий Кулаков" Мы просто берем вот этот классик с регистрацией корзины, вызываем у него метод зарегистрировать DI контейнер, вызываем метод зарегистрировать руты и все. +1813.62 1816.66 "Анатолий Кулаков" И мы можем уже полноценно взаимодействовать с рутами корзины. +1816.66 1820.62 "Анатолий Кулаков" Независимо от ничего другого, потому что он самодостаточен и полноценный. +1820.62 1826.22 "Анатолий Кулаков" И также в этом модуле очень легко удалять ненужные вещи. +1826.22 1829.38 "Анатолий Кулаков" Понадобился нам какой-то рут, мы его туда добавили в одном индейценном понятном месте. +1829.38 1831.50 "Анатолий Кулаков" Не понадобился - удалили. +1831.50 1844.50 "Анатолий Кулаков" Далее мы идем в наш программ.cs, в билдере подключаем эти модули с помощью метода register module, в аппликейшене подключаем все маппинги с помощью mapping points. +1844.50 1856.14 "Анатолий Кулаков" И мы получаем как раз таки довольно чистый, хороший, понятный программ.cs, который просто-напросто подключает вот эти доменные модули, а в каждом отдельном модуле у нас уже распространена какая-то логика. +1856.14 1868.42 "Анатолий Кулаков" Если у нас есть какая-то функциональность, которая нужна всем модулям, там логирование, аутентификация, какие-то middleware, те же самые свагеры, их можно для начала вставить в программ.cs, если будет нужно, просто вынести в какой-то отдельный классик. +1868.42 1873.78 "Анатолий Кулаков" Не суть важна, у нас сейчас самая главная тема понять это вот эти вот самые модули. +1873.78 1882.46 "Анатолий Кулаков" Естественно эти модули элементарно регистрировать автоматически, чтобы не ходить, не вызывать определенные методы, di-контейнера, mapping-routes. +1882.46 1890.26 "Анатолий Кулаков" Мы просто можем Reflection просканировать текущую assembly, выяснить все классы, которые наследуются от маркеров, от специального интерфейса imodule. +1890.26 1902.90 "Анатолий Кулаков" У этого интерфейса можно два метода те же самые сделать, зарегистрировать классики, зарегистрировать роуты, вызвать эти методы автоматически, и у нас появляется очень легкая и приятная модель регистрации. +1902.90 1909.42 "Анатолий Кулаков" Нам уже не нужно менять код в нескольких местах для того, чтобы завести нам, допустим, вообще новый домен. +1909.42 1916.74 "Анатолий Кулаков" Нам не нужно бежать в папочку с контроллером, дописывать контроллеры, в папочку с моделями дописывать какую-то модель, с валидаторами дописывать валидатор. +1916.74 1936.82 "Анатолий Кулаков" То есть мы уже не бегаем по всему Solution, мы всего лишь навсего заходим в один модуль, добавляем туда класс, реализующий imodule, подключаем ему необходимые модельки, валидаторы, хендлеры, все подряд, и Reflection автоматически, без изменения чего-то еще снаружи, нам подхватывает эту реализацию и предоставляет все необходимые endpoints для работы приложения. +1936.82 1945.90 "Анатолий Кулаков" Очень получается удобно, гибко и самое приятное, что в одном месте все меняется, не нужно никуда больше ходить. +1945.90 1950.94 "Анатолий Кулаков" Модуль получается, как я уже сказал, самодостаточной единицей. +1950.94 1957.78 "Анатолий Кулаков" И более того, он получается более гибкий, чем стандартные подходы с контроллерами и с моделями. +1957.78 1967.86 "Анатолий Кулаков" Потому что если вы хотите сделать что-то простое, допустим, тоже самый холсчек, то внутри этого модуля вам даже не нужно выделять отдельные хендлеры. +1967.86 1976.30 "Анатолий Кулаков" Вы просто можете с помощью minimal API смапить один единственный делегатик с холсчека, и все, и ваша функциональность реализована просто одной строчкой. +1976.30 1978.30 "Анатолий Кулаков" Вам не нужно загоняться чем-то больше. +1978.30 1997.06 "Анатолий Кулаков" Если у вас есть сложная функциональность, та же самая корзина, у которой есть какие-то валидаторы, какой-нибудь походок в базе данных, перемаппинг моделей, то вы можете внутри этой папочки корзина создать себе под папочки какие-то, создать себе дополнительные классики, создать себе те же самые модели. +1997.06 2003.06 "Анатолий Кулаков" В общем, организовать полностью ту структуру, которая позволит вот эту сложность нивелировать с помощью разделения. +2003.06 2014.78 "Анатолий Кулаков" Также модули можно, например, выделять, если у вас там завелся какой-то сабмодуль, и потом его функциональность стала настолько большой, что вы понимаете, что его нужно перенести на какой-то уровень выше. +2014.78 2015.78 "Анатолий Кулаков" То же самое элементарно. +2015.78 2023.02 "Анатолий Кулаков" Вы его выделяете, всего лишь на все добавляете регистрационную часть i-модуль, и все, он уже живет как полноценный модуль. +2023.02 2040.82 "Анатолий Кулаков" Также данный подход с модулями, он более понятен, потому что, когда новый разработчик приходит в ваш проект, ему не нужно уже бегать по 50 папочкам для того, чтобы осознать, где лежат контроллеры, где лежат слои доступа к базе данных для корзины, где лежат валидаторы. +2040.82 2044.54 "Анатолий Кулаков" Он просто идет в модуль, и в этом модуле содержится абсолютно все. +2044.54 2047.22 "Анатолий Кулаков" Все, что ему нужно, это вот перед глазами преследовать одну папочку. +2047.22 2054.94 "Анатолий Кулаков" Это гораздо легче, чем бегать по всему приложению и искать, где там что регистрируется, и что происходит. +2054.94 2057.66 "Анатолий Кулаков" Следующий аспект, что по модулям легче навигироваться. +2057.66 2061.18 "Анатолий Кулаков" То есть, довольно понятно становится, где что лежит. +2061.18 2069.10 "Анатолий Кулаков" Это может быть вывод из предыдущего пункта, где что лежит, куда идти и что делать. +2069.10 2073.66 "Анатолий Кулаков" Также автор рекомендует придерживаться вот этого понятия, что держать модули нужно как можно проще. +2073.66 2080.38 "Анатолий Кулаков" То есть, если у вас есть какая-то простая функциональность, не выпендривайтесь, напишите ее в одном делегате и забудьте. +2080.38 2085.06 "Анатолий Кулаков" Если она начинает разрастаться, тогда уже можно подумать об отдельном методе. +2085.06 2089.82 "Анатолий Кулаков" Если она уж слишком большая, смотрите на отдельные классы или может быть даже уже потом на отдельной папочке. +2089.82 2097.38 "Анатолий Кулаков" Но начинать всегда стоит с одного и единственного файла, вот этого модуля регистрации. +2097.38 2104.54 "Анатолий Кулаков" Дальше его уже можно бить на различные части и усложнять по мере усложнений вашей логики. +2104.54 2110.14 "Анатолий Кулаков" То есть, нужно держать как можно проще то, что у вас есть. +2110.14 2117.26 "Анатолий Кулаков" И соответственно, ваша структура проектов таким образом тоже будет отражать сложность этих модулей. +2117.26 2129.62 "Анатолий Кулаков" То есть, вы можете прям открыть проект и посмотреть, что если папочка с корзиной там наворочена, у нее там много подпапок, много каких-то файлов, вы понимаете, что это сложная доменная область и туда нужно как-то больше сил, чтобы погрузиться. +2129.62 2132.10 "Анатолий Кулаков" То есть, вы отражается реальная доменная область. +2132.10 2147.22 "Анатолий Кулаков" Если вы заходите в папочку в кабинет пользователя и там нет практически ничего, кроме одного файлика с парочкой роутов, который перенаправляет на какой-нибудь третий сторонний сайт, вы сразу визуально понимаете, что в вашем приложении вот эта доменная область, она довольно простая. +2147.22 2156.02 "Анатолий Кулаков" И таким образом у вас структура проекта отражается с тем доменом, который вы используете на работе. +2156.02 2157.02 "Анатолий Кулаков" Это тоже довольно приятно. +2157.02 2161.90 "Анатолий Кулаков" И сами модули, они получаются довольно гибкие. +2161.90 2165.90 "Анатолий Кулаков" Как я уже сказал, их можно прям отдельно тестировать, так как у вас это отдельная самодостаточная папочка. +2165.90 2170.78 "Анатолий Кулаков" Их можно передвигать между друг другом, можно выделять какой-то сабмодуль, если он разросся. +2170.78 2177.66 "Анатолий Кулаков" Можно наоборот, вкладывать их в сабмодуль, удалять элементарно, так как у нас динамическая регистрация, никто об этом даже не узнает. +2177.66 2182.22 "Анатолий Кулаков" Комбинировать несколько модулей в одну штуку, какой-то один большой модуль. +2182.22 2188.82 "Анатолий Кулаков" В общем, всего это данная структура каталогов, данная структура проектов позволяет очень гибко и легко делать. +2188.82 2192.22 "Анатолий Кулаков" Автор находит очень много примеров, где такая структура давно используется. +2192.22 2215.34 "Анатолий Кулаков" И контроллеры там как раз-таки и казались вот этой избыточной штукой, которая вырождалась всегда в класс с контроллером, и экшен-методы, просто состоящие из одного-единственного метода, который вызывает там сервис или дальше, или может быть бросает в медиатор какую-нибудь команду или какую-нибудь query, и все, и больше ничего не делает. +2215.34 2218.58 "Анатолий Кулаков" То есть там вырождение уже было давно и было очевидно. +2218.58 2232.90 "Анатолий Кулаков" И вот такая структура с минимал-апиаем, она как раз-таки позволяет вот этот ненужный слой, который уже эволюционно начал отмирать, вот она позволяет его вообще убрать и дальше уже подумать, что мы можем сделать на основании тех возможностей, которые у нас есть. +2232.90 2234.50 "Анатолий Кулаков" Вот такое интересное предложение. +2234.50 2238.94 "Анатолий Кулаков" Как ты думаешь, Игорь, достойно того, чтобы попробовать? +2238.94 2252.70 "Игорь Лабутин" Ну по крайней мере это выглядит как логичный способ объединить вот эти самые разрозненные, ну точнее простыню действительно этих вызовов map-get-map-get во что-то новое и хорошее. +2252.70 2259.74 "Игорь Лабутин" Кроме того, есть же в седьмом дотнете теперь группы, то есть теперь можно еще сказать map-group с общим префиксом. +2259.74 2268.14 "Игорь Лабутин" И потом ты получаешь билдер, который можешь передать, например, в какой-нибудь модуль для дальнейшей настройки endpoints. +2268.14 2270.30 "Игорь Лабутин" То есть возможно группы тут еще помогут дополнительно. +2270.30 2278.90 "Анатолий Кулаков" Да, мне кажется они вот точно отражают сущность модуля, что у тебя одна группа получается, это ровно на один модуль, ты его там полностью, этот домен описываешь. +2278.90 2284.46 "Игорь Лабутин" Ну единственное, что если тебе дать только самый групп билдер, ты не сможешь добавлять новые сервисы. +2284.46 2293.26 "Игорь Лабутин" То есть от сервисов тоже, ну от модуля тоже нужен тот самый интерфейсик, который сможет добавить тебе нужные модули сервисы до того, как ты пошел определять endpoints. +2293.26 2300.10 "Игорь Лабутин" Но в целом для endpoints возможно группы будут как-то тоже более интересны и добавят возможностей. +2300.10 2301.94 "Анатолий Кулаков" Там именно поэтому выделено два метода. +2301.94 2304.94 "Анатолий Кулаков" Один метод регистрирует сервисы в DA, а второй только маппет роуты. +2304.94 2305.94 "Анатолий Кулаков" Ну да. +2305.94 2306.94 "Анатолий Кулаков" То есть там они именно разнесены во времени специально. +2306.94 2322.58 "Игорь Лабутин" Ну в общем надо посмотреть, я пока не видел ни одного такого прям большого хорошего жирного проекта на minimal api, в основном так всякие модельные штуки, но я, наверное по open source, если пошариться, то можно найти. +2322.58 2324.78 "Игорь Лабутин" Посмотрим, подождем, может на работе появится. +2324.78 2335.42 "Игорь Лабутин" А пока пойдем дальше, и следующая штука, которая я не знаю насколько она появится на работе, я пока не готов такую штуку брать в работу, это новый сериализатор. +2335.42 2340.22 "Анатолий Кулаков" Подожди, подожди, это самый быстрый сериализатор на свете, его надо брать в работу, он же самый быстрый, +2340.22 2349.98 "Игорь Лабутин" он же за перформанс. У него есть некоторые но, которые мне, например, не то чтобы не позволяют его взять, но я буду сильно сомневаться брать его или нет. +2349.98 2366.74 "Игорь Лабутин" Смотрите, в общем, был у нас message pack такой формат, формат в принципе он написан отдельно, у него есть спецификация, и у нас была реализация message pack для C# написанная человеком по имени Yoshifumi Kawai, который возможно вам известен по нику NewCC. +2366.74 2377.82 "Анатолий Кулаков" Я думаю, что если вы сталкивались с быстрой сериализацией, с бинарной сериализацией, искали самый клевый, самый крутой сериализатор, то вы обязательно с ним сталкивались, потому что этот просто гений сериализации. +2377.82 2389.46 "Игорь Лабутин" Да, у него был UTF-8 Jason сериализатор, который быстрее всех, у него был Zero Formatter, по-моему, это называлось, который тоже там как-то очень быстро все сериализовывал, десериализовывал, но они были очень специфичные и узкие. +2389.46 2410.70 "Игорь Лабутин" А здесь он, соответственно, да, message pack никуда не делся, message pack живет, он используется в SignalARIA, туда пришли ребята из Microsoft, помогли все это оптимизировать, переписать, дописать на Span и вот это все, но этого показалось мало, и поэтому этот самый товарищ Yoshifumi, он написал новый сериализатор, назвал его Memory Pack. +2410.70 2423.66 "Игорь Лабутин" Он еще в несколько раз быстрее message pack, лучше всего он работает на семерке, на седьмом дотнете, но также поддерживает пятый и шестой дотнеты, то есть если вы на чем-то более раннем, забудьте, он не будет работать. +2423.66 2430.46 "Игорь Лабутин" Еще он поддерживает Unity и он поддерживает TypeScript, про TypeScript отдельно расскажу чуть позднее. +2430.46 2450.90 "Игорь Лабутин" Причем он такой как бы, сериализатор прикольный, он там поддерживает полиморфизм, умеет быть version tolerant, циклические ссылки и все возможные современные способы ввода-вывода, это интерфейсы iBufferWriter, это работа с ReadOnlySequence, с системой iOPipelines, вот это все. +2450.90 2455.46 "Игорь Лабутин" Короче звучит, я статью начал читать, звучало прям вообще зашибенно. +2455.46 2456.94 "Игорь Лабутин" Плюс он использует SourceGenerator. +2456.94 2459.78 "Анатолий Кулаков" Обязательно, какой же сериализатор без SourceGenerator? +2459.78 2460.78 "Анатолий Кулаков" Да. +2460.78 2462.42 "Игорь Лабутин" Вообще красавчик, заверните два, я уже беру. +2462.42 2481.94 "Игорь Лабутин" Да, поэтому теперь во-первых, для того чтобы его использовать, вы должны сделать следующее, вы должны ваш класс, который вы хотите сериализовывать, ну и вы его объявляете partial, ну чтобы к нему можно было, понятно, накрутить сериализатор, нагенерить собственно сериализатор, и помечаете его атрибутом memory-packable. +2481.94 2484.14 "Игорь Лабутин" Ну и все, вы готовы. +2484.14 2500.66 "Игорь Лабутин" В смысле, все нормально, поскольку он от SourceGenerator, то это все там AOT-friendly, плюс в CompileTime у вас проверят, что внутри вашего класса или структуры, которую вы сериализуете, лежат только те классы либо структуры, которые он умеет сериализовывать. +2500.66 2507.02 "Игорь Лабутин" Тут возникают тонкости, он сериализует далеко не все, есть некоторые но. +2507.02 2516.54 "Игорь Лабутин" Во-первых, статья дальше продолжает говорить следующее, возьмем самый простой тип, это int, ну int-ов у нас много, их сериализовать надо. +2516.54 2519.14 "Игорь Лабутин" Какие у нас есть варианты сериализации int-а? +2519.14 2532.26 "Игорь Лабутин" Мы можем его сериализовывать как бы как 4 байта, ну просто вот взять 4 байта и записать, а можем сериализовывать по технологии, которая называется, ну или спецификации, которая называется var int, которая как раз используется в MessagePack. +2532.26 2545.62 "Игорь Лабутин" Идея там в том, что для маленьких чисел, которых у нас вообще говоря довольно много, используется тогда минимум 1 байт, то есть 1 битик из байта на самом деле просто используется для признака, есть ли там еще следующий байт за этим числом. +2545.62 2550.02 "Игорь Лабутин" И по сути у вас 32 бита этого числа размазывается уже не по 4, а по 5 байтам максимум. +2550.02 2558.02 "Игорь Лабутин" Плюс это, ну то есть во-первых, большие числа потребуют больше байт, ну очень большие, да. +2558.02 2567.62 "Игорь Лабутин" А во-вторых, это все-таки требует некоторых ресурсов CPU на предмет, значит декодировать это все, потому что битовые операции, вот это все, ну короче, какая-то работа требуется. +2567.62 2575.02 "Игорь Лабутин" Но если вы фигачите по int-ы прям как они есть, то сериализация будет быстрее, особенно если это массивы. +2575.02 2583.14 "Игорь Лабутин" Понятное дело, что вы просто можете скопировать целиком весь массив в выходной поток или наоборот, и у вас все гораздо быстрее. +2583.14 2590.34 "Игорь Лабутин" Вот, значит здесь в этом новом сериализаторе используется fixed сериализация, то есть int-ы сериализуются как 4 байта. +2590.34 2597.54 "Игорь Лабутин" В massage-паке использовался varint, поэтому он компактнее, но зато помедленнее. +2597.54 2598.54 "Игорь Лабутин" Дальше строки. +2598.54 2600.98 "Игорь Лабутин" Со строками ситуация в каком-то смысле похожа. +2600.98 2604.90 "Игорь Лабутин" В тотнете внутри они хранятся в utf-16, как вы может быть знаете. +2604.90 2620.90 "Игорь Лабутин" Если мы в основном работаем со строками, которые у нас влезают в utf-8, то есть английский и прочие не очень экзотические языки, то по сути сериализованная строчка в utf-16 будет занимать в 2 раза больше места. +2620.90 2633.14 "Игорь Лабутин" В данном случае у него был сделан выбор в пользу сериализации в utf-8, хотя можно настроить, чтобы он сериализовывал прям в utf-16, если вам важна скорость и не важен размер. +2633.14 2637.62 "Игорь Лабутин" Тогда он будет прям фигачить байтиками из массива чаров изнутри строки. +2637.62 2652.14 "Игорь Лабутин" При этом, забавный момент, поскольку мы в момент сериализации по строке проходимся, в любом случае, то мы вместе со строкой сериализуем ее длину, причем ее длину и в utf-8 размере и в utf-16 размере. +2652.14 2656.86 "Игорь Лабутин" Они могут быть разные, поскольку там разные эти уникальные символы. +2656.86 2662.86 "Игорь Лабутин" И это помогает потом быстро десериализовать, потому что мы сразу можем залокитить нужный размер. +2662.86 2669.74 "Игорь Лабутин" Ну и есть еще несколько всяких трюков на предмет того, что массив булов он пакуется как массив битов. +2669.74 2671.06 "Игорь Лабутин" Ну то есть тут понятно. +2671.06 2675.56 "Игорь Лабутин" А еще у него есть компрессия, но компрессия прям на уровне отдельных байтерей. +2675.56 2687.66 "Игорь Лабутин" То есть можно на какой-нибудь байтерей, если вы знаете, что в нем прям много всего хранится, прямо на весь атрибут, а вот этот еще пожми, пожалуйста, дополнительно, и он будет использовать алгоритм Бротли, чтобы пожать вот этот байтерей при сериализации. +2687.66 2694.30 "Игорь Лабутин" По тестам, говорит, выходит это эффективнее, чем сжимать потом итоговый поток. +2694.30 2696.26 "Игорь Лабутин" Зачем потребовался dotnet 7? +2696.26 2702.10 "Игорь Лабутин" То есть не то чтобы потребовался, но 7 версия немножко отличается от 5 и 6, она даже немножко быстрее. +2702.10 2706.38 "Игорь Лабутин" Во-первых, ну она более оптимизирована, поэтому она побыстрее. +2706.38 2709.70 "Игорь Лабутин" Во-вторых, используются статически абстрактные мемберы в интерфейсах. +2709.70 2728.42 "Игорь Лабутин" То есть вот вы объявляете вашу модель как partial class, source generator, понятно, дописывает свою часть как свою часть partial class, и в этом месте объявляет, что ваш модель реализует некоторый специальный интерфейс, в котором генерится на самом деле два метода serialize и deserialize статически. +2728.42 2729.42 "Игорь Лабутин" Чуешь смысл? +2729.42 2731.42 "Анатолий Кулаков" Ну да, нормальный подход. +2731.42 2741.94 "Игорь Лабутин" То есть у тебя получается на твоей модели волшебным образом появляются два метода serialize и deserialize, которые статически, но они реализованы в стороннем интерфейсе, и за счет этого их не нужно реализовать в твоем методе. +2741.94 2745.14 "Игорь Лабутин" Ну допустим, почему бы нет. +2745.14 2746.14 "Игорь Лабутин" Вот. +2746.14 2757.10 "Игорь Лабутин" Дальше используются reffields, и дальше используются всяческие супер оптимизации для типов, ну, стандартной библиотеки, назовем это так, то есть listt. +2757.10 2765.18 "Игорь Лабутин" То есть, например, у него есть в коде структурка, которая по набору полей полностью повторяет внутреннее устройство listt. +2765.18 2772.74 "Игорь Лабутин" И за счет этого он может оптимально, оперируя эту структуркой, оптимально копировать содержимое listt. +2772.74 2776.98 "Игорь Лабутин" То есть там очень такая low-level магия, сильно завязанная она. +2776.98 2780.38 "Игорь Лабутин" То есть если сейчас в рантайме взять и поменять порядок полей в listt, этот стерилизатор сломается полностью. +2780.38 2784.50 "Анатолий Кулаков" Я помню, у Стэна Драпкина был похожий хак, у него было еще круче. +2784.50 2787.02 "Анатолий Кулаков" Ну, смысл в том же самом, да. +2787.02 2794.18 "Анатолий Кулаков" И его расчет, как раз я ему задавал этот вопрос, его расчет был на то, что типа listt — это настолько устраивающаяся структура, что никто им не отнимет. +2794.18 2795.18 "Анатолий Кулаков" Да. +2795.18 2796.18 "Игорь Лабутин" Мы в этом уверены. +2796.18 2797.18 "Игорь Лабутин" Да, именно поэтому. +2797.18 2813.82 "Игорь Лабутин" То есть тут тоже есть некоторое количество хаков, то есть, например, он использует новую штуку, по-моему, это в шестом, знаете, появилась, да, вот это вот collection-marshal s-span, по-моему, в шестерке появилась, когда ты можешь получить доступ к, собственно, массиву внутри листа, значит, ну к спану точнее, да, поверх массива внутри листа. +2813.82 2818.50 "Игорь Лабутин" Но там, например, проблема в том, что этот спан возвращается той длины, сколько у тебя элементов в листе. +2818.50 2821.98 "Игорь Лабутин" При десерилизации у тебя сколько элементов в листе внутри нового? +2821.98 2824.98 "Анатолий Кулаков" Мы не знаем, если не записали каунт. +2824.98 2829.46 "Игорь Лабутин" Не-не-не, очевидно ноль, ну в смысле, ты вот взял лист, даже если… Ты хочешь его наполнить, да? +2829.46 2839.78 "Игорь Лабутин" Да, я хочу наполнить его десерилизацией, он пустой, возможно, массив-то не пустой, потому что, возможно, массив мы там переиспользовали откуда-то, ну в смысле, в этом листе мы ему сказали clear, грубо говоря, перед этим. +2839.78 2846.94 "Игорь Лабутин" Он там, в нем что-то лежало, то есть он может быть длинный, но если ты скажешь collection_marshal_span, тебе вернется спан нулевой длины. +2846.94 2875.54 "Игорь Лабутин" Поэтому через вот эту вот типа копию-не копию, значит, структурки, через приведение типов можно внутри листа задать, что у него на самом деле length нужной тебе длины, которую ты взял из десерилизатора, после чего спан тебе вернет нужную длину, ну в смысле, collection_marshal_span вернет спан нужной длины, ты в этот спан запишешь содержимое из, собственно, десерилизованных данных и проставишь эту длину еще раз уже нормально. +2875.54 2880.34 "Игорь Лабутин" Короче, там такая супермагия, ну значит, от этого он, конечно, +2880.34 2892.02 "Анатолий Кулаков" быстрый. Ну, может, это и звучит как бы страшно, но если разобраться, то все эти ORM-ки, допустим, самые быстрые, все десерилизаторы, которые самые быстрые, они такую магию применяют уже давно и долго, поэтому это нормально. +2892.02 2897.72 "Игорь Лабутин" Ну да, ну в общем, для десерилизатора такого general purpose звучит немножко страшно. +2897.72 2911.06 "Игорь Лабутин" Итак, детали, значит, десерилизует он, понятно, все встроенные типы плюс кучу встроенных коллекций, там основные, понятно, листы, дикшн, ремапы, вот это все, стеки очереди и все такое прочее. +2911.06 2923.58 "Игорь Лабутин" Значит, если вы десерилизуете структуру, то никакие аннотации, вообще десерилизатор позволяет задать всякие аннотации, ну типа вызвать callback до сериализации, после сериализации, вот это все. +2923.58 2934.66 "Игорь Лабутин" Короче, если это структура, то никаких там конструкторов аннотаций вызываться не будет никогда, она сериализуется просто напрямую из памяти, вот как она лежит, так и сериализуется туда-сюда. +2934.66 2962.62 "Игорь Лабутин" Поддерживается полиморфизм, для этого нужно либо на базовом классе, либо интерфейсе, разметить атрибутиками, типа вот у этого интерфейса есть там челды такие-то, каждому челду присвоить свой номер, он, видимо, будет сериализован как ключик, чтобы понимать, какой класс создать при десерилизации, но можно эту штуку собрать и в коде тоже, в рантайме прямо определить, сколько у тебя там челдов и как их десериализовать. +2962.62 2967.46 "Игорь Лабутин" Дальше эта штука поддерживает два режима версионирования. +2967.46 2976.82 "Игорь Лабутин" Есть так называемый режим limited version tolerance, то есть такой ограниченный режим версионированности, в нем работают следующие ограничения. +2976.82 2991.54 "Игорь Лабутин" Во-первых, если у вас есть структура, то вы не можете ее менять вообще никак, ну вот совсем, то есть если вы какую-то структуру описали, начали ее сериализовать, все, ее менять больше нельзя никогда, иначе вы десериализовать не сможете, потому что она десериализуется при моем копировании. +2991.54 3006.62 "Игорь Лабутин" Вы можете добавлять мемберов, но удалять нельзя, а также вы не можете менять у мемберов тип, либо порядок, то есть по сути вы в классы, вы можете просто дописывать поля в конец, больше вы не можете делать ничего. +3006.62 3015.46 "Игорь Лабутин" Это, понятное дело, довольно ограничивает все, поэтому есть версия, которая называется full version tolerance, точнее режим работы. +3015.46 3030.78 "Игорь Лабутин" В этом случае структурки все еще не могут быть поменены, там ничего не поменялось, а у классов все мемберы должны обязательно иметь атрибут memory pack order и явно прописанные чиселку, в каком порядке их сериализовать. +3030.78 3049.82 "Игорь Лабутин" Ну и понятно, в этом случае вы можете добавлять и удалять, но если вы добавляете новые элементы, поля или property, то нужно будет использовать неиспользуемые чиселки, то есть вы дописываете в конец, а если какое-то поле удалили, то больше эту чиселку переиспользовать нельзя в этом классе. +3049.82 3055.74 "Игорь Лабутин" Но логика понятна, поскольку мы не сериализуем имена, мы сериализуем только значения, но нужно знать точный порядок. +3055.74 3058.70 "Игорь Лабутин" Поэтому такие дела. +3058.70 3062.30 "Игорь Лабутин" Тип все еще менять нельзя у мемберов. +3062.30 3072.38 "Игорь Лабутин" Получается, за счет того, что в отличие от message pack тут не пишется ни имена, ни структура, ничего, получается понятно, очень компактный формат, до некоторой степени вообще похоже на protobuf, в общем-то. +3072.38 3082.02 "Игорь Лабутин" Там по сути тоже самое, тоже размечается порядок строгий, типы заранее известны в схеме, и вы просто гоняете все только значения. +3082.02 3088.50 "Игорь Лабутин" Но вот он такой, protobuf, но без явной схемы на основе классов. +3088.50 3101.54 "Игорь Лабутин" При этом есть опция в compile time, поскольку это все source генератор и вот это все, то в compile time выплюнуть файлик, в котором будет написано, а какая же в итоге псевдосхема какая получается. +3101.54 3116.98 "Игорь Лабутин" То есть это позволяет, например, во время CI проверить, что эта схема не поменялась, то есть закоммитить предыдущую схему и если схема поменялась, как-нибудь на CI отругаться либо сверить схемы и проверить, что вы там поля не убрали, что-нибудь в таком духе. +3116.98 3140.14 "Игорь Лабутин" Короче, довольно много ограничений, но если вам нужен прям супербыстрая скорость или у вас довольно такие стабильные типы, ну например вы сериализуете много там, не знаю, каких-нибудь там векторов или матриц, которые строго фиксированы на размеры и никогда меняться не будут, ну потому что что там еще в векторе из трех элементов нужно добавлять, там всегда три элемента, то возможно такой сериализатор имеет место, имеет право на жизнь. +3140.14 3141.14 "Игорь Лабутин" По перфомансу. +3141.14 3172.02 "Игорь Лабутин" По перфомансу есть замеры, ну я видел их только в этой статье пока, поэтому не знаю, будут ли еще какие-то независимые когда-нибудь, но смысл в том, что если мы берем JSON, JSON для сериализуется в бенчмарках MessagePack за 23 секунды, ой за 23 миллисекунды видимо, десериализуется за 39, а MemoryPack за 13-25 соответственно, то есть выигрыш где-то раза в 2 на сериализации и в 1,5 на десериализации. +3172.02 3196.18 "Игорь Лабутин" А вот если мы берем, вот тут для примера сериализовался век, как раз таки массив из векторов, то есть массив из трехмерных векторов, 10 тысяч элементов, то MessagePack на это тратил 10 миллисекунд и 26 на распаковку, а MemoryPack 0.2 и 0.3 соответственно, то есть тут уже разница в, что там, 10, в 50 раз приблизительно. +3196.18 3210.30 "Игорь Лабутин" То есть ну прям по скорости действительно круто, ну понятно за счет чего, за счет того, что он работает напрямую с памятью во многом старается, то есть положить в сериализованные данные ровно так, как они лежат в памяти объектов, удобно ведь? +3210.30 3227.34 "Игорь Лабутин" При этом в этой же статье есть вполне частное сравнение с MessagePack с точки зрения функциональности, то есть и он говорит, что MessagePack все еще круче, чем MemoryPack, чем, что во-первых он точно совместим между разными языками, MessagePack вы сможете распаковать на Java, на Python, на чем угодно. +3227.34 3232.78 "Игорь Лабутин" MessagePack совместим с JSON в том смысле, что в MessagePack пишутся имена, вам не нужно знать схему. +3232.78 3244.42 "Игорь Лабутин" Он полностью version-tolerant по дефолту, он позволяет там всякие анонимные типы сериализовывать и так далее, ну и он давным-давно работает, так сказать, проверен временем. +3244.42 3257.74 "Игорь Лабутин" MemoryPack по дефолту, ну как бы, понятно, супербыстрый, но по дефолту limited version-tolerant, то есть вы очень ограничены, что вы можете делать с полями и изменениями ваших моделей. +3257.74 3262.50 "Игорь Лабутин" Единственный поддерживаемый язык, кроме C#, это TypeScript. +3262.50 3275.26 "Игорь Лабутин" Для TypeScript там на самом деле в момент компиляции генерятся JS-файлики, которые нужно потом заинклюдить в ваш код TypeScript, и там написан JS-код, который, собственно, может десериализовать и сериализовать то, что вы собрали. +3275.26 3277.74 "Игорь Лабутин" То есть там тоже код дегенерации, по сути, это делается. +3277.74 3307.46 "Игорь Лабутин" И он, конечно, MemoryPack лучше, чем MessagePack, если вам нужен performance, если вам нужен AOT, потому что MessagePack все еще на рефлекшене, а не все там работает в AOT, MemoryPack - Strongly Compiled Time, поэтому там AOT, полиморфизм, циклические ссылки, то, что называется Override Deserialization, то есть вы можете подсунуть существующий объект, как мы смотрели с примером, в список, и он в существующий список заново положит новые данные. +3307.46 3310.70 "Игорь Лабутин" Ну, в общем, примерно так. +3310.70 3330.10 "Игорь Лабутин" И рекомендация автора, собственно, говорит следующее, что если вы живете только в C#, в C# ни с кем другим не общаетесь, и у вас достаточно стабильные модели, можно использовать MemoryPack, но думайте про вот эту версионность, то есть если вы собираетесь часто менять модели, скорее всего, это не ваш вариант. +3330.10 3332.82 "Игорь Лабутин" В любом другом случае, используйте MessagePack. +3332.82 3333.82 "Игорь Лабутин" Как-то так. +3333.82 3336.86 "Игорь Лабутин" Будешь использовать такую штуку. +3336.86 3360.18 "Анатолий Кулаков" На самом деле я много писал проектов, где скорость и компактность, и Memory Allocation были очень важными вещами, важнее всего, и честно могу сказать, что вот эти все глупости, толерантность к версионированию, меняние порядка полей, еще что-то, ну вообще это не играет никакой роли, если вам нужно выжать максимальный перформанс. +3360.18 3368.70 "Анатолий Кулаков" Я думаю, что здесь даже полиморфизм в дистиллизации появился только потому, что его элементарно поддержать с помощью Source Generator. +3368.70 3372.18 "Анатолий Кулаков" Если бы не было Source Generator, то тут бы и полиморфизма тоже, естественно, никакого бы не было. +3372.18 3373.18 "Анатолий Кулаков" Это слишком затратно. +3373.18 3378.54 "Анатолий Кулаков" Поэтому если, ну то есть люди, которые выжимают перформанс, они не загоняются такими глупостями. +3378.54 3381.06 "Анатолий Кулаков" Для них вот главное перегнать максимально эффективно. +3381.06 3391.22 "Анатолий Кулаков" И поэтому там делаются и отдельные структуры, которые никогда в жизни не меняются, а если меняются, то заводятся полностью другие структуры, постепенно все переезжается руками. +3391.22 3395.70 "Анатолий Кулаков" И полиморфизм там делается руками, если вдруг это почему-то вам нужно в таком случае. +3395.70 3400.22 "Анатолий Кулаков" В общем, там где нужен перформанс, все вот эти минусы, они абсолютно несущественны. +3400.22 3404.74 "Анатолий Кулаков" Там нужно просто гонять Massive Byte, просто как сумасшедший максимально эффективно. +3404.74 3413.18 "Анатолий Кулаков" И если там действительно Memory Pack показывает шикарные результаты, которые обгоняют всех, то конечно, я его использовать буду. +3413.18 3417.90 "Анатолий Кулаков" Я еще хотел подчеркнуть это, что это как раз не General Purpose, а сервизатор, как ты говорил. +3417.90 3422.10 "Анатолий Кулаков" А если мне нужен какой-нибудь General Purpose, то наверное, Message +3422.10 3433.10 "Игорь Лабутин" Pack, да, наше все. Ну вот авторы, я так понимаю, это все дело, судя по тому, что это что-то поддерживает Unity, как раз это все пилят ради игр, где много однотипных мосилов, так скажем. +3433.10 3434.10 "Анатолий Кулаков" Массивые экстрапов, матрицы. +3434.10 3438.98 "Анатолий Кулаков" Да, где как раз таки не важен ваш JSON compatibility, так наплевать всем на него. +3438.98 3440.30 "Игорь Лабутин" Да, и там это все нужно. +3440.30 3444.86 "Игорь Лабутин" Но действительно, наверное, есть такие области в обычном программировании, но скорее всего, я все-таки потащу Message Pack. +3444.86 3448.98 "Игорь Лабутин" Я пока не вижу, где я такое могу использовать, но опять же, областей есть много разных. +3448.98 3454.86 "Игорь Лабутин" Давай дальше, у нас еще много тем, поэтому надо не останавливаться. +3454.86 3457.02 "Анатолий Кулаков" Да, да, давай быстрее. +3457.02 3465.70 "Анатолий Кулаков" Чтобы развеять там твой перформанс, интерналс и все такое, хочу немножко стратегическую для начинающих бросить, говорим про GitHub Actions. +3465.70 3486.30 "Анатолий Кулаков" Так вдруг случилось, что я почему-то узнал, что если люди уже начали выходить на GitHub, то есть раньше у нас на GitHub вообще разработчики в России практически не выходили, сейчас уже мы GitHub не боимся, сейчас уже GitHub это как бы стандартная часть нашей жизни, не только там, чтобы посмотреть, но и многие люди уже как бы и даже коммитят, и даже пушат, и даже вообще не боятся. +3486.30 3497.94 "Анатолий Кулаков" Но GitHub Actions это все еще для многих какой-то черный ящик, вот поэтому хотелось бы дать такую вводную про GitHub Actions, зачем он нужен, для чего используется и вообще как он может помочь дотнет-разработчику. +3497.94 3500.62 "Анатолий Кулаков" Давай немножко быстренько в это дело и копнем. +3500.62 3504.10 "Анатолий Кулаков" Соответственно, что такое GitHub Actions? +3504.10 3508.94 "Анатолий Кулаков" Это возможность continuous integration и continuous delivery для GitHub. +3508.94 3521.14 "Анатолий Кулаков" Самое в нем прекрасное в том, что он бесплатный, доступен абсолютно каждому, если у вас есть репозиторий, то в этом репозитории вы можете смело использовать бесплатный CIDI, что в наше время в принципе очень даже хорошо и очень даже щедро. +3521.14 3525.86 "Анатолий Кулаков" У них там довольно нормальный пол агентов, в принципе у меня никогда не было с ними проблем. +3525.86 3532.66 "Анатолий Кулаков" Я раньше сидел на всяких Avera и Travis, и там у меня все время были какие-то очереди, занятости, все такое. +3532.66 3540.42 "Анатолий Кулаков" Здесь же Microsoft вкладывает огромное количество бабла, введено в эту инфраструктуру, и агентов там полно, никаких очередей нет. +3540.42 3543.10 "Анатолий Кулаков" Но давайте поближе, для чего это все? +3543.10 3549.86 "Анатолий Кулаков" Прежде всего, чтобы автоматизированно тестировать, билдить, конечно же, ваш код и может быть даже деплоить. +3549.86 3553.46 "Анатолий Кулаков" GitHub Workflow представляет собой набор YAML файликов. +3553.46 3567.38 "Анатолий Кулаков" Это расширение .yaml какой-нибудь или .yml, и данный файлик просто-напросто складывается внутрь вашего Git репозитория и в специальную папочку, которая называется .git/workflows. +3567.38 3576.06 "Анатолий Кулаков" В этой папочке вы можете сложить несколько различных YAML файликов, в зависимости от того, насколько многообразный Workflow вам требуется. +3576.06 3594.98 "Анатолий Кулаков" Прекрасно здесь то, что нет никакого GUI, не может там какие-нибудь кнопочки утечь, не надо никуда переносить, это всего-навсего настраивается в одном YAML файле, что поддерживает тему Build as Code, то есть мы собираем весь билд и описываем его в виде того же самого кода, если из-за кода считать YAML, и это очень удобно. +3594.98 3610.18 "Анатолий Кулаков" Версионируется, распространяется вместе с бранчами, можно экспериментировать в различных ветках, не мешая основной, есть и история, можно всегда посмотреть, кто это, кто менял какие переменные, в общем все прелести кода у билда здесь появляются. +3610.18 3623.66 "Анатолий Кулаков" Workflow, GitHub Workflow, он как раз-таки использует GitHub Actions, GitHub Actions состоит из инструкций, а вот эти самые непосредственные инструкции, они запускают таски. +3623.66 3627.34 "Анатолий Кулаков" В общем такая иерархия, давайте разберемся подробнее в терминологии, чтобы не запутываться. +3627.34 3629.58 "Анатолий Кулаков" Прежде всего GitHub Actions. +3629.58 3640.50 "Анатолий Кулаков" GitHub Actions это платформа для CI/CD, она позволяет вам запускать такие обычные рутинные вещи для каждого проекта, как сборка, тестирование и развертывание. +3640.50 3648.58 "Анатолий Кулаков" Далее есть такое понятие как Workflow, это как раз-таки настраиваемый автоматический процесс, который умеет запускать джабы. +3648.58 3654.02 "Анатолий Кулаков" Об этом вернемся чуть попозже, а прежде всего мы узнаем, кто их запускает, то есть какое событие их запускает. +3654.02 3655.70 "Анатолий Кулаков" У нас есть такое понятие как Event. +3655.70 3665.38 "Анатолий Кулаков" Event это как раз-таки специальная активность, которая происходит внутри репозитория, которая триггерит, запускает Workflow, и в свою очередь запускает джабы. +3665.38 3677.94 "Анатолий Кулаков" Внутри репозитория что у нас может быть, например, кто-то запушил новое изменение, кто-то создал новый pull request, кто-то создал новый issue даже, на все на это может поджечь триггер, который запустит соответствующий Workflow. +3677.94 3682.30 "Анатолий Кулаков" Как я уже сказал, Workflow для исполнения запускает джабы. +3682.30 3690.30 "Анатолий Кулаков" Джабы это набор шагов, которые будут выполняться на одном раннере, то есть они будут выполняться не параллельно, они будут на одном раннере выполняться последовательно. +3690.30 3705.06 "Анатолий Кулаков" Если вы хотите, чтобы с вашим основным процессом, то есть с вашим основным джабом выполнялись какие-то другие вещи, сканирование кода вполне может, сканирование кода на какие-нибудь security-извимости вполне может идти параллельно с тем, когда вы код билдите и тестируете. +3705.06 3713.68 "Анатолий Кулаков" Это можно сделать двумя джабами, и они будут запускаться параллельно, и друг другу мешать не будут, а билд у вас в общее время будет соответственно намного меньше. +3713.68 3716.66 "Анатолий Кулаков" Дальше есть такое понятие как Actions. +3716.66 3728.42 "Анатолий Кулаков" Actions это специально написанные маленькие приложенницы, которые как раз таки выполняют непосредственно различную работу с различными аспектами. +3728.42 3733.98 "Анатолий Кулаков" Эти приложения, они обычно сложные, но очень часто переиспользуемые. +3733.98 3742.18 "Анатолий Кулаков" Такие как, например, запустить команду, или скачать репозиторий, или пропатчить определенный файлик. +3742.18 3746.62 "Анатолий Кулаков" То есть обычные такие команды, они выполнены, каждая эта команда в виде отдельного приложения. +3746.62 3751.26 "Анатолий Кулаков" И такие приложения называются Actions, что довольно удобно об этом мы посмотрим попозже. +3751.26 3754.54 "Анатолий Кулаков" И еще одно понятие, которое вам пригодится это Runner. +3754.54 3764.26 "Анатолий Кулаков" То есть это непосредственно тот сервер, который запускает ваш workflow в результате, когда триггернуло какое-то событие. +3764.26 3767.74 "Анатолий Кулаков" Теперь давайте разберемся, что же внутри находится этого GitHub workflow. +3767.74 3771.22 "Анатолий Кулаков" Как я уже сказал, workflow это всего лишь навсего ямл файлик. +3771.22 3774.46 "Анатолий Кулаков" И в этом одном единственном ямл файлике описано абсолютно все, что вам нужно. +3774.46 3784.10 "Анатолий Кулаков" Поэтому вы можете пойти, найти в GitHub этот файл, просто визуально его открыть, посмотреть и вытащить оттуда какие-нибудь интересные подходы, интересные хаки. +3784.10 3785.10 "Анатолий Кулаков" Все в одном месте. +3785.10 3787.42 "Анатолий Кулаков" Этот файлик обычно не такой уж и большой. +3787.42 3790.74 "Анатолий Кулаков" Для примитивных проектов он можно в десяток строк вложить. +3790.74 3796.90 "Анатолий Кулаков" Для каких-то более больших, более богатых там уже естественно комментарии, ветвления, параллельности. +3796.90 3799.34 "Анатолий Кулаков" Но до этого нам еще дожить надо. +3799.34 3801.34 "Анатолий Кулаков" Итак, в каждом workflow прежде всего есть имя. +3801.34 3806.34 "Анатолий Кулаков" Это имя будет отображаться в интерфейсе GitHub, когда pipeline будет запускаться. +3806.34 3814.58 "Анатолий Кулаков" У него есть набор триггеров, по которым этот workflow будет триггериться в зависимости от какого-то ивента или от какого-то другого события. +3814.58 3817.10 "Анатолий Кулаков" В общем все это описывается в этом же файле. +3817.10 3825.58 "Анатолий Кулаков" Для того чтобы workflow работал вам нужно указать хотя бы один триггер, иначе его некому будет запускать, никакое событие не произойдет и он никогда не будет работать. +3825.58 3827.86 "Анатолий Кулаков" Очень полезным бывает атрибут ignore. +3827.86 3835.78 "Анатолий Кулаков" Это секция ignore, которая вам рассказывает, что workflow нужно запускать не всегда, а только на определенный шаблон каких-нибудь файликов. +3835.78 3850.70 "Анатолий Кулаков" Допустим, если мы исправляем ошибку в файле readme, то есть в текстном описании нашего проекта, и коммитим такой коммит в нашей репозитории, то естественно не надо запускать никакой билд, то есть не надо запускать workflow, который перезапустит опять наши тесты, начнет это все гонять. +3850.70 3857.58 "Анатолий Кулаков" Мы понимаем, что файл readme никак на наши тесты не повлияет, скорее всего статус останется таким же, каким он был до этого. +3857.58 3870.58 "Анатолий Кулаков" Мы можем задавать какие-то перемены в этом ямле, то есть использовать его более-менее как полноценный более-менее язык, переменные в одном месте объявлять, в одном месте менять, а дальше уже в течение всей жизни в коде его как-то использовать. +3870.58 3874.82 "Анатолий Кулаков" У нас есть список джебов, есть хороший параметр, называется стратегия. +3874.82 3877.02 "Анатолий Кулаков" Стратегия обычно задает матрицу операционных систем. +3877.02 3888.22 "Анатолий Кулаков" Как вы сейчас знаете, дотнет у нас кросс-платформенный, поэтому вы можете написать матрицу операционных систем, на которой вы хотите тестировать ваш код, указать там допустим Ubuntu, Windows и macOS. +3888.22 3898.54 "Анатолий Кулаков" И в результате этого у вас запустится уже не один джоб, а целых три джоба на различных операционных системах и в каждом из джобов будут выполнены определенные шаги. +3898.54 3903.26 "Анатолий Кулаков" Вот давайте как раз таки разберемся, какие например шаги выполняет стандартный дотнет разработчик. +3903.26 3913.90 "Анатолий Кулаков" Прежде всего первым шагом он делает чек-аут, то есть мы забираем из гитхаба тот репозиторий или ту ветку или тот коммит, который мы сейчас хотим протестировать. +3913.90 3929.54 "Анатолий Кулаков" Дальше мы можем настроить переменные окружения дотнета, например выставить версию дотнета, с которой мы будем билдиться, выбрать версию SDK, с которой мы будем билдиться и запускать соответственно тесты. +3929.54 3945.10 "Анатолий Кулаков" Следующим шагом у нас идет обычно рестор пакетов, это запуск стандартной команды dotnet restore, дальше билд, это команда dotnet build и обычно тест, это команда dotnet test, как несложно догадаться, вот из таких там простых шагов и складывается минимальный pipeline. +3945.10 3951.62 "Анатолий Кулаков" И в результате этого весь ваш код будет обязательно собирабельный, тестируемый и ресторабельный. +3951.62 3968.18 "Анатолий Кулаков" Можно добавлять больше, например можно собирать артефакты, NuGet пакеты допустим, Docker images, и отсюда же можно их прям пушить, какой-нибудь NuGet.org или в Docker Hub или куда-то еще в ваш приватный репозиторий, если вам это вдруг нужно. +3968.18 3980.62 "Анатолий Кулаков" Также можно запускать различные уязвимости, сканирование на security уязвимости и анализировать ваш код, насколько там соответствует параметрам различным, которые у вас там приняты. +3980.62 3988.38 "Анатолий Кулаков" Естественно можно запускать не просто security уязвимости, а просто проверку качества кода или проверку стиля, который принят в вашей команде. +3988.38 3996.86 "Анатолий Кулаков" Вот все вот эти проверочки, они тоже сделаны в виде отдельных экшенов, они уже есть, они уже стандартные, все подхватываются, вам нужно добавить просто-напросто одну строчку. +3996.86 4013.82 "Анатолий Кулаков" Ну и естественно разворачивать приложение тоже можно, если у вас площадка, на которой вы хотите развернуть доступно из агентов GitHub, то есть это какое-нибудь стандартное публичное облако, Azure, Yandex, еще что-нибудь в общем, туда тоже можно прямо из GitHub запольнуть ваше свеженькое приложение и оно уже попадет непосредственно на площадку. +4013.82 4022.98 "Анатолий Кулаков" Еще один аспект, о котором часто забывают, а зря, это кэширование, потому что наше дотант приложение очень сильно зависит от различных референсов. +4022.98 4026.54 "Анатолий Кулаков" Таких референсов, ну, get-пакетов, ну, get-референсов, их может быть очень много. +4026.54 4041.30 "Анатолий Кулаков" И у GitHub Actions есть специальная оптимизация, которая позволяет вам указать там папочки, которые будут кэшироваться и указать там маски, к которым файлам нужно кэшировать специальный ключ, когда сбрасывать кэш. +4041.30 4057.02 "Анатолий Кулаков" В общем, там много настроечек, но самый главный смысл, что обычно так случается, что большую часть всего пайплайна занимает именно .NET Restore, потому что пойти там куда-нибудь в интернет и оттуда скачать там 100 тысяч миллионов зависимостей, это довольно долго. +4057.02 4060.82 "Анатолий Кулаков" Это часто бывает дольше, чем забилдить, даже протестировать приложение. +4060.82 4067.66 "Анатолий Кулаков" И вот, если у вас такая ситуация, то как раз кэширование много пакетов – это ваше спасение. +4067.66 4075.46 "Анатолий Кулаков" Один из самых крутых фич, которые вам дает GitHub Actions – это проверка вашего workflow. +4075.46 4090.94 "Анатолий Кулаков" То есть вы можете задать специальные условия, которые проверят статус текущего commit, текущей ветки, которая к вам, например, приходит в виде pull-request, и завалить определенно билд, если вам это нужно, или наоборот, не завалить, а пропустить билд. +4090.94 4106.34 "Анатолий Кулаков" Ну, например, вы можете сконфигурировать, что если ваш pull-request не компилируется, то, естественно, вы не хотите видеть его в мастере, и вы можете такую настройку сделать в workflow, что если данный pull-request не компилируется, то запретить merge в мастер. +4106.34 4108.46 "Анатолий Кулаков" И дальше вы можете наворачивать. +4108.46 4114.82 "Анатолий Кулаков" Соответственно, он должен не только компилироваться, но и проходить, например, style-гайды, должен проходить там качество кода, должен выдавать какой-то артефакт. +4114.82 4119.18 "Анатолий Кулаков" И вообще абсолютно все, что в вашу фантазию может прийти, можно здесь проверить. +4119.18 4129.94 "Анатолий Кулаков" И вот такие вот проверки, вот такие вот quality-гейты, то есть какие-то ворота, которые гарантируют определенное качество в мастере, вы можете строить на основании вот этих GitHub-экшенсов. +4129.94 4139.30 "Анатолий Кулаков" Также существует огромное количество там сторонних экшенов, которые может написать абсолютно каждый разработчик. +4139.30 4144.78 "Анатолий Кулаков" И есть .NET Developer Community, которая поставляет GitHub-экшенсы для .NET. +4144.78 4147.50 "Анатолий Кулаков" И там полно всякого интересного. +4147.50 4159.94 "Анатолий Кулаков" Например, можно взять экшенс, который генерирует вам классные отчеты, показывает покрытие кода, который генерирует классные бейджи, то есть картинки, с помощью которых вы можете нарядить ваш репозиторий. +4159.94 4172.10 "Анатолий Кулаков" В общем, там уйма веселья, уйма всего интересного, но прежде всего, конечно, нужно научиться настраивать экшены вашим конкретным репозиториям под те минимальные шаги, которые обеспечат вам хотя бы тестируемый и валидный мастер. +4172.10 4176.34 "Анатолий Кулаков" А уже все остальное там для вас откроется дальше, там уже много всего интересного. +4176.34 4180.26 "Игорь Лабутин" Да, технология хорошая. +4180.26 4182.94 "Игорь Лабутин" Я ее немножечко использовал, на самом деле. +4182.94 4196.98 "Игорь Лабутин" Ну, на работе мы в GitHub не живем, у меня на GitHub C# практически нет, но когда я куда-то контрабидил в другие проекты, то да, было пару мест, где нужно было поправить GitHub-экшенс, workflow описание, и это было прямо очень приятно. +4196.98 4207.86 "Анатолий Кулаков" Ну, я думаю, на любой работе, естественно, на твоей тоже обязательно будет какой-нибудь CI/CD, и это уже как бы стандарт любой разработки. +4207.86 4215.62 "Анатолий Кулаков" Поэтому то, что у нас open-source проекты некоторые не имеют встроенного CI/CD, это вот грустно, даже не проекты, а репозиторий. +4215.62 4221.58 "Анатолий Кулаков" Хотелось бы, чтобы там тоже это было как бы стандарт, сделать его просто, он бесплатный, поэтому почему бы просто +4221.58 4230.34 "Игорь Лабутин" не сделать. Давай пойдем дальше, поговорим про CI/CD, но уже немножко другой, ну, то есть не совсем про CI/CD, но тоже про сборку и про код. +4230.34 4235.42 "Игорь Лабутин" Заанонсили штуку под названием .NET Virtual Monolithic Repository. +4235.42 4241.30 "Игорь Лабутин" Ну, как заанонсили, анонсмент появился, но там есть куча дисклеймеров, давайте разбираться. +4241.30 4246.86 "Анатолий Кулаков" Слушай, ну звучит прям солидно, да, такой виртуальный монолитик репозиторий, прям очень интересно. +4246.86 4267.86 "Игорь Лабутин" Да, смысл в том, что если сейчас вы хотите собрать полностью .NET, вот получить, условно говоря, инсталлер .NET SDK или рантайма целиком, то вам нужно это сделать из кучи разных отдельных репозиторий, там у нас как раз рантайм отдельно, спиноткор отдельно, EF отдельно, то отдельно, все отдельно, инсталлеры вообще черти где живут. +4267.86 4272.50 "Игорь Лабутин" То есть, короче, очень сложный процесс, который в состоянии сделать только Microsoft. +4272.50 4277.26 "Игорь Лабутин" Сейчас сделали новые репозитории под названием внезапно .NET/.NET. +4277.26 4282.82 "Игорь Лабутин" Вот, он тоже в организации .NET и репозитории называется .NET. +4282.82 4300.18 "Игорь Лабутин" Это виртуальный монолитик, монолитный, то есть репозиторий, который включает в себя весь код, который необходим для того, чтобы собрать себе .NET SDK плюс систему под названием Source Build, это та штука, которая, собственно, используется для сборки .NET SDK. +4300.18 4317.94 "Игорь Лабутин" Причина, ну не причина, одна из целей, которая достигалась, это то, что у нас теперь есть один коммит, то есть как только вы туда, вы можете собрать точнее .NET и ваша сборка будет полностью идентифицироваться одним единственным коммитом. +4317.94 4321.30 "Игорь Лабутин" Понятное дело, поскольку это один-единый репозиторий. +4321.30 4330.26 "Игорь Лабутин" Это виртуальные репозитории, это зеркало, куда регулярно синхронизируются изменения из всех оригинальных репозиториев. +4330.26 4339.38 "Игорь Лабутин" То есть это не сабмодули, это не что-либо другое, это просто нормальные репозитории, куда регулярно коммитятся чинджи автоматически из других репозиториев. +4339.38 4345.78 "Игорь Лабутин" И эта штука все еще экспериментал, то есть это пока эксперимент, посмотреть, как оно будет жить. +4345.78 4355.42 "Игорь Лабутин" Майкрософт ожидает, что она станет более-менее нормальной постоянной штукой примерно к моменту первой превьюшки 8-го .NET, которая запланирована на февраль 23-го года. +4355.42 4357.66 "Анатолий Кулаков" Они подразумевают из нее собирать все время или +4357.66 4359.26 "Анатолий Кулаков" зачем она им практически нужна? +4359.26 4362.22 "Игорь Лабутин" Вот. Значит, цели этой штуки следующие. +4362.22 4371.94 "Игорь Лабутин" Во-первых, иметь возможность, собственно, иметь весь код в одном репозитории, и чтобы вы могли идентифицировать единым коммитом это все. +4371.94 4377.82 "Игорь Лабутин" Второе, они собираются релизить и собирать SDK для восьмерки оттуда, в том числе. +4377.82 4389.54 "Игорь Лабутин" Третье, сейчас очень сложно протестировать, например, если вы пишете какую-то фичу, которая зависит, например, одновременно и от рантайма, и от какого-нибудь там, не знаю, BCL. +4389.54 4395.62 "Игорь Лабутин" Это лежит, ну, рантайм с BCL лежат в одной репо, поэтому тут как раз более-менее нормально. +4395.62 4401.34 "Игорь Лабутин" А вот если вам нужно какое-нибудь изменение там в BCL и в SP над Core вместе протестировать, то это сложнее. +4401.34 4409.42 "Игорь Лабутин" Нужно собирать сначала BCL, потом использовать этот BCL, собирать SP над Core, ну, то есть там прям, это очень непросто, особенно для внешних контрибьюторов. +4409.42 4413.14 "Игорь Лабутин" Ну и для внутренних тоже, сути по всему. +4413.14 4435.46 "Игорь Лабутин" И цель как раз-таки, что в таком репозитории вы можете создать, это, конечно, виртуальный репозиторий, но никто не мешает вам, например, создать в нем бранч, что-нибудь погонять, потестировать, поменять одновременно там и рантайм, и BCL, и SP, и что угодно еще, собрать из этого SDK, попробовать что-нибудь погонять, попроверять, а потом аккуратненько все свои чинжи уже спортировать в оригинальной репозитории, чтобы нормально закоммитить. +4435.46 4471.58 "Игорь Лабутин" И третье, эээ, третье, четвертое, цель это удовлетворить требованиям ребят под названием Red Hat Economical, например, это Ubuntu, которые, как мы помним, нативно теперь собирают себе дотнеты в свои нативные пакеты, а по требованиям open-source должен быть способ собрать эту самую штуку из единого репозитория, грубо говоря, ну то есть скачать репозиторий, сказать, грубо говоря, git clone, да, build, и у тебя собрался дополнительный дотнет, готовый пакет, или для там Red Hat, например. +4471.58 4473.14 "Игорь Лабутин" Как реализован SYNC? +4473.14 4506.70 "Игорь Лабутин" Значит, они думали сделать сабмодули, решили, что не надо, почитав отзывы в интернете, дальше они хотели сделать сабтри, это такая прям очень, как я понимаю, advanced технология, когда ты в git-репозиториях, по сути, коллекция деревьев внутри, в внутреннем представлении, ты технически можешь на самом деле хранить несколько деревьев, не связанных друг с другом, и потом их вмерживать вместе в единый комит, но там были трудности с тулингом вокруг этого, git немножко криво это поддерживает, и, короче, решили, что не будем. +4506.70 4569.94 "Игорь Лабутин" Поэтому в итоге они пришли к выводу, что мы просто напишем custom.sync решение, которое просто аккуратненько, по-моему, сейчас настроено раз в три часа, идет во все значит репозитории, их там двадцать восемь, да, двадцать шесть штук, то есть дотнет у нас сейчас состоит из двадцати шести разных репозиториев, то есть это решение, программка она идет в двадцать шесть репозиториев, раз в три часа, делает там аккуратно git-create-patch, и потом этот патч, аккуратно делает git-apply-patch на этот репозиторий, они еще этим добиваются крутой штуки, им нужно уметь исключательно исключать некоторые файлы, то есть, например, там есть какие-нибудь, не знаю, огромные бинарники для каких-то очень специфических тестов, там, или performance каких-нибудь, или еще чего-нибудь, которые они не хотят видеть в этом едином большом репозитории, они аккуратно исключают, потому что всякие моменты типа там, submodule, subrep, вот это все, оно бы все вытащило целиком, а так они имеют возможность что-то исключить. +4569.94 4580.98 "Игорь Лабутин" Вот, сейчас это все поддерживает только восьмой дотнет и выше, и вряд ли это будет поддерживать более раннее, понятное дело, потому что начали делать это только сейчас. +4580.98 4593.22 "Игорь Лабутин" Полностью билд из сурсов доступен сейчас только на линуксе, потому что первичная цель это видимо была, чтобы Red Hat и Canonical, им было полегче собирать свои версии дотнета. +4593.22 4599.58 "Игорь Лабутин" Мак и Windows будут готовы только к девятому дотнету, пока ждать не стоит, сейчас пока там все завязано на линуксе. +4599.58 4611.50 "Игорь Лабутин" И на данный момент пока еще нельзя сделать полностью оффлайновый билд, то есть там сейчас реквизит для того, как все это собрать, оно уже там сейчас есть, выглядит довольно забавно. +4611.50 4615.14 "Игорь Лабутин" Шаг первый, как ты думаешь, какой, что тебе нужно, чтобы собрать дотнет? +4615.14 4618.18 "Анатолий Кулаков" Ну, наверное, выкачать репозиторий, запустить дотнот билд. +4618.18 4621.10 "Игорь Лабутин" Ага, сейчас, первым шагом поставить дотнот SDK, вот +4621.10 4623.10 "Анатолий Кулаков" так вот, понимаешь? Ну, да, неплохо. +4623.10 4628.30 "Игорь Лабутин" Да, то есть типа вот для того, чтобы собрать SDK из сурсов, тебе нужно поставить другой дотнот SDK, ну типа +4628.30 4631.22 "Анатолий Кулаков" это облегчит жизнь канонику, я чувствую. +4631.22 4644.30 "Игорь Лабутин" Да, ну у них есть цель все это сделать полностью оффлайн, он там еще за какими-то Nuget пакетами пойдет, на самом деле, во время билда, и там это сказано явно, что типа сейчас мы не оффлайн, мы пойдем в интернет за Nuget, но над этим всем они работают, чтобы было полностью оффлайн. +4644.30 4646.22 "Анатолий Кулаков" Как они сделают Nuget пакет оффлайн? +4646.22 4649.94 "Анатолий Кулаков" Не знаю, я не знаю пока, не знаю, будем следить. +4649.94 4650.94 "Игорь Лабутин" Хорошо, будем посмотреть. +4650.94 4667.06 "Игорь Лабутин" Вот, именно поэтому, видимо, они говорят, что это все экспериментал, то есть у них прям большими буквами написано, что типа мы в принципе можем решить, что нафиг не нужно и дропнуть, ну в смысле в таком виде, да, не взлетело, и дропнуть вообще весь репозиторий, так что вы там типа на него пока не завязываете сильно, пока все очень экспериментал. +4667.06 4682.98 "Игорь Лабутин" Но как-то так, так что возможно, возможно, к, не знаю, к релизу девятки, а восьмерки у нас, да, следующий релиз, к релизу восьмерки, соответственно, через год у нас будет возможность собрать свою собственную SDK, но пока на Linux только, а там, глядишь, через пару лет и до Mac с винтой доберемся. +4682.98 4713.38 "Анатолий Кулаков" Не знаю, слушай, выглядит это как какой-то позор, я вот, почитав их цели, я надеялся, что они как раз такие сделают, там, Sub3, SubRep, SubModule, что-нибудь там виртуально изобретут, потому что знаешь, прикольно, вот все большие гиганты там, всякие Facebook, Яндекс, Google, они как раз делают Monorep у себя, а потом для того, чтобы решить все проблемы Monorep, они изобретают собственный инструментарий, который позволяет из этой Monorep кусочки выдёргивать, как бы их изменения туда какие-то делать и обратно потом в Monorep эти кусочки заливать, но так, чтобы они не сломали всю Monorep там. +4713.38 4714.38 "Анатолий Кулаков" Ну правильно. +4714.38 4715.38 "Анатолий Кулаков" Чем такие извращения делают. +4715.38 4717.78 "Анатолий Кулаков" Да, Microsoft такое же делал для своих, для гита. +4717.78 4722.74 "Анатолий Кулаков" Да, у Microsoft же такая же система есть, было бы прекрасно, если бы Microsoft как раз-таки с другой стороны подошёл. +4722.74 4745.62 "Анатолий Кулаков" Вот у нас есть много маленьких репозиториев, а мы сделаем вот такую виртуальную штуку, которая их соединяет в Monorep, а то если они разрабатываются как отдельные репозитории со всеми их плюсами, и если тебе вдруг почему-то надо, вот забери их в отдельную Monorep, и безусловно, как бы вторым плюсом от этого всего было бы обратная картинка, ты можешь в этой Monorep всё поменять, и он должен разлететься по своим репозиториям, все эти изменения. +4745.62 4752.34 "Анатолий Кулаков" Не важно, там в pull-request, ещё каким-то образом, ну то есть тогда бы это вообще геймчейджер был, то есть это какой-то новый подход на рынке. +4752.34 4756.42 "Анатолий Кулаков" А так они нажали F5, как бы в фаре скопировали все дифы, и всё. +4756.42 4759.74 "Анатолий Кулаков" Ну что это такое, я в 90-х этим занимался. +4759.74 4762.42 "Игорь Лабутин" Ну вот они только сейчас к этому пришли. +4762.42 4763.42 "Анатолий Кулаков" Тормозят. +4763.42 4768.06 "Анатолий Кулаков" Это не уровень технологической компании мирового уровня, ну что это такое. +4768.06 4770.86 "Игорь Лабутин" Посмотрим, может что новое придумают, ты будешь доволен. +4770.86 4772.82 "Игорь Лабутин" Но пока ты не доволен, я понял. +4772.82 4773.82 "Анатолий Кулаков" Пойдём дальше. +4773.82 4776.26 "Анатолий Кулаков" Да, будем надеяться, что их эксперименты будут поудачнее. +4776.26 4784.02 "Анатолий Кулаков" Вот кстати, насчёт неудачных экспериментов, ты знал, что Nuget, он как бы не очень удачный эксперимент, несмотря на то, что им как бы пользуются все. +4784.02 4786.02 "Анатолий Кулаков" Да нет, норм эксперимент, нормально. +4786.02 4795.94 "Анатолий Кулаков" Да ладно, вот я нашёл автора, который, ну автор инструмента, который называется Nugetizer, и он вот говорит, что реально у Nuget есть проблемы. +4795.94 4799.22 "Игорь Лабутин" Проблемы, наверное, есть много где, ну давай. +4799.22 4801.34 "Игорь Лабутин" Ну погоди, ну автора нет. +4801.34 4802.94 "Анатолий Кулаков" А, окей, давай. +4802.94 4804.74 "Анатолий Кулаков" Вот, короче, инструментик. +4804.74 4807.42 "Анатолий Кулаков" Как я уже сказал, Nugetizer. +4807.42 4813.34 "Анатолий Кулаков" Это простой, гибкий, интуитивно понятный и очень мощный Nuget упаковщик. +4813.34 4818.06 "Анатолий Кулаков" Хороший слово, пакетчинг, упаковщик, пусть будет упаковщик. +4818.06 4827.34 "Анатолий Кулаков" И этот упаковщик был призван для того, чтобы устранить все минусы Nuget, которые у него накопились, т.е. +4827.34 4834.82 "Анатолий Кулаков" он такой взглянул на Nuget формат под новым углом, взглянул на то, что он умеет и решил переделать всё правильно и по-своему. +4834.82 4853.58 "Анатолий Кулаков" В общем, как я уже сказал, стандартный, стандартный вот этот SDK, у него есть встроенная поддержка упаковки, т.е. сборка бинарников различных в какой-то определенном формате и запаковка их в Nuget пакет. +4853.58 4877.62 "Анатолий Кулаков" Но, как говорит автор, что дизайн того, как команды у Nuget работают, т.е. даже не команды, а описание самого пакета, т.е. это команды, которые в msbuild в props файлах у нас вписаны, т.е. как вот эти сами таргеты работают, как у них пропертии работают, как эти айтемы комбайнятся, сделано абсолютно неконсистентно и нелогично. +4877.62 4890.90 "Анатолий Кулаков" Там плохие дефолты, часто различные команды противоречат синтаксис у друг друга, в общем, и это видно, что инструмент развивался многие-многие годы и подошел, т.е. в результате получилось большое такое неконсистентное месиво. +4890.90 4916.82 "Анатолий Кулаков" И когда вы начинаете не просто собирать там какой-то маленький пакетик из одной сборочки, из вашего одного проектика, там все хорошо, а когда вы начинаете собирать какие-то сложные пакеты, когда у вас много проектов, из них вылетает много сборок и в зависимости от различных условий вам нужно насобирать такой пакет под различные платформы с различными файликами под каждую платформу с различными версиями. +4916.82 4922.98 "Анатолий Кулаков" В общем, это все становится очень-очень сложно и самое главное непредсказуемо. +4922.98 4932.74 "Анатолий Кулаков" Т.е. что там получится в результате, а главное, что получится после того, как выйдет новая версия или когда кто-то поменяет там один флажочек, это становится абсолютно непредсказуемо. +4932.74 4942.38 "Анатолий Кулаков" В общем, это все автора абсолютно не устраивало, поэтому он написал свой инструмент, который позволяет вам это все дело паковать по-своему. +4942.38 4953.42 "Анатолий Кулаков" Для того, чтобы использовать Nugetizer вы должны прописать в css-прош файли специальную директиву, которая рассказывает, какие прош-файлы нужно упаковать, какие нет. +4953.42 4971.78 "Анатолий Кулаков" Так же, как и у обычного Nuget, у него есть стандартные какие-то атрибуты, стандартные элементы, которые, например, могут добавить контекст в destination пакет, но делают они это намного умнее, у него есть шаблоны, которые раскрываются поумнее, у него есть дефолты, которые более предсказуемы. +4971.78 4982.42 "Анатолий Кулаков" Например, если вы захотите засунуть сюда в пакет всю папочку, он вам засунет всю папочку, без всяких там магических звездочек и решеточек, которые вам нужно в стандартном Nuget пакере использовать. +4982.42 4997.86 "Анатолий Кулаков" Интересная команда в том, что можно указать директиву пакет-шаппл-патх, и он все пакеты, которые соберет из всех проектов, неважно где они на какой глубине настроены, он их соберет и сложит в отдельную директорию, там где вы укажете. +4997.86 5008.86 "Анатолий Кулаков" В общем, возможности все такие же точно, но детализация как раз заключается в удобстве, в понятных дефолтах, в более умном поведении и прочем. +5008.86 5018.62 "Анатолий Кулаков" На примере Redmi покажу, вот каждый знает, что есть обычно у проектов Redmi файл, в котором описаны основные способы работы с проектом. +5018.62 5024.42 "Анатолий Кулаков" И также недавно Nuget добавил возможность запихивания Redmi как раз в пакет. +5024.42 5026.74 "Анатолий Кулаков" Мы об этом тоже говорили в каком-то выпуске. +5026.74 5043.98 "Анатолий Кулаков" То есть для того, чтобы пользователь мог искать ваш пакет, например, в Visual Studio или в Rider, и когда он найдет пакет, щелкнул на него, у него в этот момент показывается Redmi, в который красиво с форматированием, может быть даже с картинками, с графиками рассказывается про вашу прекрасную библиотеку. +5043.98 5050.10 "Анатолий Кулаков" Вот такие Redmi тоже сейчас добавляют в пакеты. +5050.10 5058.82 "Анатолий Кулаков" И обычно тот Redmi файл, который лежит у вас в GitHub репозитории, он не очень соответствует тому Redmi файлу, который вам хотелось бы видеть в этом пакете. +5058.82 5065.70 "Анатолий Кулаков" Например, в репозитории обычно сначала находятся секции о том, как склонировать репозиторий, как его сбилдить. +5065.70 5073.06 "Анатолий Кулаков" В конце там находится какое-нибудь "Спасибо нашим контрибьюторам" или "Как законтрибьютировать наоборот в этот гид репозитории". +5073.06 5085.06 "Анатолий Кулаков" Когда мы читаем Redmi про Nougat пакет, естественно там не должно быть никакой фразы о том, как склонировать репозиторий или как законтрибьютировать в репозитории, потому что мы находимся в контексте Nougat пакета, нет там никакого репозитория. +5085.06 5098.82 "Анатолий Кулаков" И вот чтобы победить такую некрасивость, Nougatizer поддерживает query к MD файлам, который позволяет достать определенную секцию. +5098.82 5107.14 "Анатолий Кулаков" Например, вы можете сказать "Дай мне Redmi файл", секцию только "Usage", секция это то, что с таким заголовком идет. +5107.14 5120.06 "Анатолий Кулаков" А потом добавим в конце из документов футер для моего пакета, и тогда он добавит какую-то определенную часть, которая будет только в пакете, но не будет в Redmi на очередном гидхаб репозитории. +5120.06 5124.70 "Анатолий Кулаков" В общем, вот такие действия может творить и при этом придавать красивость. +5124.70 5137.02 "Анатолий Кулаков" Как я, наверное, не сказал, Nougatizer распространяется с помощью Global Tools, это позволяет ему легко и быстро кроссплатформенно вписаться в любой ваш проект. +5137.02 5142.38 "Анатолий Кулаков" Его нужно запускать из Project Directory. +5142.38 5152.66 "Анатолий Кулаков" Интересный момент, что если его просто запустить без всяких параметров, он выдаст вам быстрый отчет того, какие пакеты он сделает из этого репозитория, то есть какие пакеты будут сгидлены. +5152.66 5166.40 "Анатолий Кулаков" Он вам удобно покажет там файлы, всю структуру, версию, какую DLL он куда положит, по какому пути, в какой платформе она будет, по каким папочкам он это все разложит. +5166.40 5168.18 "Анатолий Кулаков" И это все будет показано очень быстро. +5168.18 5180.34 "Анатолий Кулаков" Там специально есть оптимизация, которая использует не настоящую компиляцию для того, чтобы понять все эти зависимости, а специальную IDE, Debug Time, по-моему, или Debug Time компиляция, вот как-то так называется. +5180.34 5187.18 "Анатолий Кулаков" То есть это специальный хак, специальная компиляция для IDE, которая используется для того, чтобы быстрее в верхнем уровне понять, что происходит. +5187.18 5198.14 "Анатолий Кулаков" В общем, этот луза тоже это делает для того, чтобы мгновенно выдать вам вот такой красивый большой полноценный отчет с предсказуемым набором пакетов и с предсказуемой структурой, которая у вас там будет в результате. +5198.14 5209.18 "Анатолий Кулаков" В общем, если вы страдаете от того, что у вас очень сложный проект, который упаковывается в очень сложные пакеты, то можно посмотреть на этот инструмент, кажется, что он вам может хорошо помочь. +5209.18 5226.74 "Анатолий Кулаков" Я же, наверное, в своих проектах обычно стараюсь такого не делать, хотя у меня есть очень сложные Get пакеты, но как-то я обходился стандартным форматом, собирал их с помощью специального Nuspec файла, и тоже вроде как так было все хорошо, не вижу причин не меняться. +5226.74 5242.22 "Игорь Лабутин" Я более того скажу, я, по-моему, ни разу не пользовался возможностью сборки из Cessproj на прямую, я всегда писал Nuspec отдельный, где ты четенько можешь указать прям конкретный список файлов, конкретный там, что куда положить, какой редми взять и вот это все. +5242.22 5244.22 "Анатолий Кулаков" Ну это ты просто старпер же. +5244.22 5245.22 "Анатолий Кулаков" Спасибо. +5245.22 5248.30 "Анатолий Кулаков" Когда появился новый, не знаю, обращайтесь, это +5248.30 5254.74 "Анатолий Кулаков" же когда появился новый SDK формат, то как бы все стали собирать именно из Proj файлов для того, чтобы как раз вот эти Nuspec никому не были нужны. +5254.74 5257.82 "Анатолий Кулаков" Ну это работает, естественно, только когда тебе нужно один к одному. +5257.82 5269.18 "Анатолий Кулаков" Как только ты хочешь из нескольких проектов собрать один пакет, то там мы возвращаемся к нашему Nuspec, и я рад, что они были не забросили, не деприкетили, а до сих пор поддерживают, и это прекрасная мощная штука, которая часто выручает. +5269.18 5276.70 "Игорь Лабутин" Ну и продолжим пользоваться по старинке, как и пользовались пока не отделят и не забудут. +5276.70 5279.58 "Игорь Лабутин" Давай дальше, пойдем к теме. +5279.58 5298.98 "Игорь Лабутин" Я на самом деле не планировал ее исходно включать в этот подкаст, но раз уж вышел райдер 2022.3, и буквально за пару дней, наверное, до записи подкаста или около того, то решил включить, потому что это все очень подходит под те темы, которые мы сегодня обсуждаем. +5298.98 5311.98 "Игорь Лабутин" Итак, новый райдер 2022.3, там вышло большое количество E-апов, и теперь у нас поддержан .NET 7, то есть если вы хотели попробовать новый SDK, то вот как раз таки ставьте 2022.3, там будет поддержка седьмого .NET. +5311.98 5317.82 "Игорь Лабутин" Поддержан VSL 2, туда можно заканчиваться для Remote Development прямо из райдера. +5317.82 5328.02 "Игорь Лабутин" Можно теперь, ну мы про это рассказывали, таскать Tool Window к окошкам, которые вы вытащили из основного окна. +5328.02 5329.58 "Игорь Лабутин" Ты, кстати, пробовал, это реально работает? +5329.58 5332.42 "Игорь Лабутин" Я не пробовал еще, я обновился, но я не попробовал еще. +5332.42 5334.18 "Игорь Лабутин" Блин, клевый фича. +5334.18 5335.18 "Игорь Лабутин" Надо будет попробовать. +5335.18 5345.66 "Игорь Лабутин" Но я на самом деле очень редко пользуюсь многомониторной конфигурацией для редактирования кода, у меня всегда райдер, ну то есть если я работаю, то это максимальный расширяющий рендер на основном экране и все. +5345.66 5347.38 "Игорь Лабутин" Я второй монитор не использую. +5347.38 5350.10 "Анатолий Кулаков" Да-да, это, конечно, для нескольких мониторов. +5350.10 5355.46 "Игорь Лабутин" Вот, то есть я не умею программировать на двух мониторах, мне нужен один, и по центру. +5355.46 5358.94 "Анатолий Кулаков" Для решения твоей проблемы три монитора. +5358.94 5360.94 "Анатолий Кулаков" Я пробовал, отличная штука. +5360.94 5361.94 "Игорь Лабутин" Да, возможно, возможно. +5361.94 5366.50 "Игорь Лабутин" Вопрос, как их подключать, да, ну в общем, там возникают другие вопросы, куда их ставить на стол. +5366.50 5379.42 "Игорь Лабутин" Так, новый Toolbar, ну вообще новый, немножко такой UI-чик, про который говорили, может быть, вы слышали в других разных EDG'ках, теперь он есть в райдере, там более чистенький и так далее. +5379.42 5384.30 "Игорь Лабутин" Тоже еще, я буквально сегодня обновился, поэтому не пробовал еще полностью, но так выглядит приятно. +5384.30 5386.34 "Игорь Лабутин" Посмотрю, как будет в работе. +5386.34 5396.86 "Игорь Лабутин" Поддержаны всякие новые C# фичи, там UTF-8 литералы, файл local type, статик abstract member, rostering literals, ref field, scope, значит, ключевое слово, ну и так далее. +5396.86 5400.46 "Игорь Лабутин" В общем, все, что мы знаем про C# 11, должно быть поддержано. +5400.46 5415.26 "Игорь Лабутин" В Blazor, сервер APOC завезли hot reload, теперь можно делать, завезли NuGet Central Package Management, и появилось early preview для ARM64 под Windows и Linux. +5415.26 5422.62 "Игорь Лабутин" Кроме того, DotMemory, теперь который встроенный в райдере и встроенный в DotMemory, стал доступен на Linux и на Mac. +5422.62 5429.66 "Игорь Лабутин" Короче, ну, много всяких разного, улучшений, грубо говоря, по сути, там, 7 из DK, новый UI-чик и Performance. +5429.66 5432.54 "Игорь Лабутин" Значит, с Performance тема отдельная. +5432.54 5446.30 "Игорь Лабутин" У нас на самом деле была статья, которая была опубликована в блоге nDependa довольно давно, от автора, собственно, этого самого nDependa, про то, что, а давайте сравним Performance райдера и Visual Studio. +5446.30 5452.66 "Игорь Лабутин" Ну, типа, много кто живет в райдере, много кто живет в Visual Studio, много кто живет в Visual Studio и в ReSharper. +5452.66 5454.82 "Игорь Лабутин" Давайте поймем, кто быстрее, кто медленнее. +5454.82 5457.82 "Анатолий Кулаков" Ну, всем же известно, что ReSharper тормозит, правильно? +5457.82 5459.98 "Игорь Лабутин" Да, ясное дело, ReSharper тормозит, но вопрос на сколько. +5459.98 5469.22 "Игорь Лабутин" И на момент публикации статьи студия была версии 17.24, райдер был версии 20.22.1.2. +5469.22 5478.82 "Игорь Лабутин" Все это тестировал товарищ на своем компе, это Xeon с 2.7 ГГц, с 64 ГГ памяти, так что кажется памяти должно хватать IDE. +5478.82 5483.10 "Игорь Лабутин" Ну, понятно, SSD, винтовая десятка, вот это все. +5483.10 5488.70 "Игорь Лабутин" Тестировал это на двух Solutions, на nDependa, собственно, 38 проектов, примерно, ну, почти 6000 файлов. +5488.70 5494.58 "Игорь Лабутин" И есть такой Knob Commerce проектик, это 28 проектов и 5300 файлов. +5494.58 5507.22 "Игорь Лабутин" Сначала он замерял, сколько проходит времени до момента, когда мы просто берем и запускаем райдер или Visual Studio, не открывая никаких Solutions. +5507.22 5512.46 "Игорь Лабутин" Соответственно, студия чистая занимает 4 секунды, студия с ReSharper 6 секунд, райдер 5 секунд. +5512.46 5519.14 "Игорь Лабутин" Ну, окей, разница вроде небольшая, нормально, сойдет. +5519.14 5543.26 "Игорь Лабутин" Дальше если мы открываем nDepend Solution, это надо напомнить, примерно 6000 файлов, 38 проектов, то у студии это занимает 17 секунд, студии с ReSharper это занимает 20-25, то есть он называется First Responsive и Fully Responsive, то есть хоть как-то с ним можно работать через 20 секунд, со студией, в смысле с ReSharper, а так полноценно работать уже через 25. +5543.26 5546.58 "Игорь Лабутин" Райдер же занимает 13, то есть быстрее, чем студия на 4 секунды. +5546.58 5549.78 "Анатолий Кулаков" Это на холодную, да, то есть кэширование всегда включено? +5549.78 5558.10 "Игорь Лабутин" Я подожди, ну, он говорил, что технология замеров это типа я много-много-много раз открывал, ну и брал, там, выкидывал аутлайер и брал что-то средненькое. +5558.10 5561.78 "Анатолий Кулаков" А, понятно, значит кэш уже был и он просто переездался. +5561.78 5573.98 "Игорь Лабутин" Да-да-да, то есть это не полностью абсолютно свежий, свежесклонированный Solution, который ты вообще в жизни никогда не видел, нет, это твоя обычная рабочая работа, то есть ты просто берешь Solution, с которой ты в среднем работаешь и его там открываешь. +5573.98 5583.22 "Игорь Лабутин" А билд не сильно отличается, там 22, 22,3, 23 секунды, в общем, на билд можно не смотреть. +5583.22 5589.46 "Игорь Лабутин" С Solution, но в Commerce там чиселки примерно похожие, Rider секунд на 5 быстрее. +5589.46 5612.26 "Игорь Лабутин" И общие выводы у него были следующие, что как бы в целом Rider выглядит более респонсив, и это понятно почему, потому что у него UI-чик отдельно, а ReSharper, да, в бэкэндах смысле, который, ReSharper отдельный, это отдельный процесс, который там где-то там в бэкграунде фигачит, анализирует все, а UI-чик становится доступным быстрее, несмотря на то, что это Java. +5612.26 5623.06 "Игорь Лабутин" А в студии, когда студия с ReSharper, ну ReSharper, он хоть и потихонечку выносится в бэкграунд, там все-таки довольно много всего все еще происходит в самой студии, ну в смысле в основном потоке, и поэтому медленнее. +5623.06 5634.22 "Игорь Лабутин" Его очень огорчает, в принципе, время старта пустого, пустой IDE, что студии, что Rider, то есть 4-5 секунд, это прям как бы долго. +5634.22 5635.98 "Игорь Лабутин" Что там запускаться? +5635.98 5641.54 "Игорь Лабутин" Ну так, было бы круто, если пустая студия или пустой Rider запускалась бы за секунду, это было бы норм. +5641.54 5644.26 "Игорь Лабутин" Сейчас он действительно довольно долго запускается. +5644.26 5662.66 "Игорь Лабутин" И его вывод в статье такой, что ну как бы да, Rider быстрее, поэтому если вы как бы, вам нужна скорость, пользуйтесь Rider, но если вам нужны старые фреймворки, да, там Rider до сих пор не поддерживает WinForms на DotNet Core, ну и всякие другие типа там WCF и прочее, если вы чем-то таким пользуетесь, ну наверное вам придется жить в студии. +5662.66 5673.02 "Игорь Лабутин" Это одна из причин, почему я сейчас много живу в студии, я сейчас много работаю с WinForms, а Rider их не очень умеет на DotNet Core, ну в смысле он их не умеет. +5673.02 5676.02 "Игорь Лабутин" Отдельный вопрос, зачем WinForms на DotNet Core, но вот так сложилось. +5676.02 5701.26 "Игорь Лабутин" Я взял и когда я готовился, я попробовал это дело на одном из Solutions, который у меня был под рукой, который я довольно регулярно открываю, это 24 CS Proj, а там примерно 5000 CS File Lake, студия у меня без ReSharper, ReSharper у меня в принципе не стоит, у меня получилось, что студия без ReSharper запускалась 13 секунд открывалась, Solution я проверял это до момента, когда я смогу сказать Ctrl+T и что-нибудь поискать. +5701.26 5705.70 "Игорь Лабутин" То есть студия заняла 13 секунд, у Rider это заняло 16 секунд. +5705.70 5708.66 "Игорь Лабутин" То есть у меня Rider открывался дольше. +5708.66 5709.66 "Игорь Лабутин" Неожиданно. +5709.66 5710.66 "Игорь Лабутин" Да. +5710.66 5718.06 "Игорь Лабутин" То есть, ну это студия без ReSharper, то есть вот у меня как-то так, может они кэши как-то более оптимально раскладывают, я не знаю. +5718.06 5723.02 "Игорь Лабутин" И вот как раз вышел 22.3, обновленный Rider, который быстрее. +5723.02 5724.50 "Игорь Лабутин" Что они там сделали? +5724.50 5730.18 "Игорь Лабутин" Они завязали побольше от CPU ядер для сканирования файликов при старте. +5730.18 5737.02 "Игорь Лабутин" Они автоматически при инсталляции теперь себя добавляют в исключение Windows Defender, если мало ли кто-то этого не делает, то очень рекомендуется. +5737.02 5739.26 "Игорь Лабутин" Прям, теперь они сами это делают. +5739.26 5743.54 "Игорь Лабутин" А лучше всю эту папочку с исходниками тоже туда добавьте, иначе будет тормозить. +5743.54 5758.62 "Игорь Лабутин" ReSharper в бэкэнде, который у них крутится, стал побыстрее за счет того, что, по сути ReSharper как работает у них, он грузит всякие модули, просто сканируя все папочки, ну все длфки-папочки в округе и пытаясь понять, что нужно подгрузить. +5758.62 5766.14 "Игорь Лабутин" Вот они теперь там анализируют кастомные свои атрибуты, точнее всю нужную методат, но они пихают в свои кастомные атрибуты, за счет чего это побыстрее работает. +5766.14 5769.54 "Игорь Лабутин" Ну пооптимизировали memory traffic. +5769.54 5775.74 "Игорь Лабутин" В ReSharper бэкэнде стали использовать серверный вариант ГЦ, от этого получше перформанс. +5775.74 5785.90 "Игорь Лабутин" И еще, мы не обсуждали в подкасте, может быть как-нибудь обсудим отдельно, что вышел уже флит для C#, от JetBrains. +5785.90 5793.46 "Игорь Лабутин" И для того, чтобы штука эта работала, им пришлось написать новый C# парсер, который вообще никак не связан с ReSharper. +5793.46 5812.34 "Игорь Лабутин" Он такой типа легковесный и все дела, и поэтому теперь райдер работает таким образом, что пока не пригрузился полноценный ReSharper на бэкэнде, у тебя есть уже какой-то работающий на фронте простенький C# парсер, ну простенький, но при этом он что-то умеет, поэтому у тебя есть ощущение, что можно работать раньше. +5812.34 5821.30 "Игорь Лабутин" И вот в моем тесте до момента, когда я могу сказать Ctrl+T, у меня появляется Solution Explorer, я могу сказать Ctrl+T, вместо 16 секунд стало 11 секунд. +5821.30 5824.06 "Игорь Лабутин" О, это же заметно, это хорошо. +5824.06 5833.82 "Игорь Лабутин" На новой версии, да, то есть тут у меня на конкретном одном Solution, на конкретном одном моем компе, в абсолютно не научном тесте, назовем это так, видна экономия в 5 секунд. +5833.82 5842.18 "Игорь Лабутин" Я не знаю, буду ли я видеть это в каждодневной работе, я довольно часто меняю Solution, запускаю райдер, закрываю райдер и так далее, посмотрим. +5842.18 5844.86 "Игорь Лабутин" Но кажется, что действительно перформанс там стал получше. +5844.86 5856.18 "Анатолий Кулаков" Отлично, будем смотреть, как развивается, как друг друга перегоняет, может студия это тоже подстегнет, пересмотреть что-то в своих запусках и кэшированиях. +5856.18 5859.58 "Игорь Лабутин" Да, ну что, давай последнюю тему обсудим. +5859.58 5868.50 "Анатолий Кулаков" Да, темка подслушана, я расскажу, что я такого интересного нашел за это время среди наших коллег. +5868.50 5872.18 "Анатолий Кулаков" Прежде всего хотелось бы отметить подкаст «Подлодка. +5872.18 5875.70 "Анатолий Кулаков" 273 выпуск» про интересную тему «Оценки не нужны». +5875.70 5884.30 "Анатолий Кулаков" Потому что я очень часто сталкиваюсь с людьми, которые считают, что почему-то оценки нужны и очень много менеджеров хотят странного, они хотят каких-то сроков. +5884.30 5892.86 "Анатолий Кулаков" В общем, и этот выпуск интересен тем, что он эту тему обсуждает довольно многогранно и разбирает там частые кейсы. +5892.86 5904.70 "Анатолий Кулаков" В общем, например, чем оценка отличается от прогноза, это тоже для многих будет откровением, что мы называем не теми словами, которые должны называть всю эту терминологию, можно ли просто работать, а не вот это вот все. +5904.70 5913.34 "Анатолий Кулаков" А как делать там осознанную разработку или выдумывать против того, чтобы выдумывать цифры и натягивать какие-то оценки на какие-то мифические сроки. +5913.34 5922.78 "Анатолий Кулаков" Еще интересное рассуждение, как цепочка оценка, синдром самозванца и стресс приводят людей к выгоранию. +5922.78 5931.22 "Анатолий Кулаков" Тоже никогда не прослеживал такую вещь, но оказывается, вот те команды, у которых есть какая-то оценка, какие-то строки, они чаще выгорают. +5931.22 5933.50 "Анатолий Кулаков" Что со всем этим делать? +5933.50 5942.74 "Анатолий Кулаков" И на куче конкретных примеров рассказывается очень много практических кейсов, какие-то научные пытаются к этому выводы все подвести и так далее. +5942.74 5963.58 "Анатолий Кулаков" В общем, если вас интересуют оценки или если вам нужно каким-то образом убедить ваших менеджеров, что оценки это не всегда хорошо и может быть конкретно в вашей ситуации, они совсем и не нужны, то есть попытаться хотя бы это сделать, попробуйте послушать подкасты, много интересных, есть аргументов, с помощью которых можно дальше пообщаться с вашим руководством. +5963.58 5968.10 "Анатолий Кулаков" Далее подкаст «Проветримся», ведущий подкаст Иван Ямщиков. +5968.10 5978.38 "Анатолий Кулаков" Я Ваню очень много слушаю, очень много смотрю, очень много люблю и в принципе везде, где мне встречается Иван Ямщиков, я пытаюсь все эти выступления посмотреть. +5978.38 5990.74 "Анатолий Кулаков" Кто не знает, это исследователь в основном искусственного интеллекта, он работал в Яндексе, в Эбби, он доцент высшей школы экономики, у него там еще куча всяких регалий международных. +5990.74 5998.74 "Анатолий Кулаков" В общем, это такой нормальный ученый, можно так сказать, и уже после этого популяризатор искусственного интеллекта. +5998.74 6019.70 "Анатолий Кулаков" Он очень интересно рассказывает вообще любую техническую тему, что бы он не затронул, но в частности в этом подкасте к нему приходит огромное число различных людей, которые увлекаются теми или иными технологиями, и кстати не только технологиями, и он с ними разговаривает с кем-то в формате интервью, с кем-то в формате просто дружественной беседы, в зависимости от гостя. +6019.70 6024.38 "Анатолий Кулаков" Темы выбираются всегда интересные, обычно это околотехнические какие-то темы тоже. +6024.38 6036.22 "Анатолий Кулаков" В общем, Ваня чрезвычайно начитан, чрезвычайно интересно говорит, у него прекрасно воставленная речь, и тот человек, с которым безусловно всегда интересно и пообщаться, и послушать его подкасты. +6036.22 6041.58 "Анатолий Кулаков" В качестве примера, что у него последний сезон, например, он записывал про медитацию. +6041.58 6071.58 "Анатолий Кулаков" Как я уже сказал, до этого у него были абсолютно технические все вещи, в основном в этом сезоне, даже в прошлом сезоне, можно сказать, он взял тему медитации, разобрал её, провёл несколько уроков медитации в своём подкасте, обсудил в то же самое время клёвые книги по психологии, о том, как их можно применить к нашей IT-жизни, о том, как относиться к окружающему миру. +6071.58 6074.98 "Анатолий Кулаков" В общем, всё в этой теме разобрал, тоже очень хорошо. +6074.98 6088.70 "Анатолий Кулаков" И, по-моему, сейчас уже у него начался новый сезон, когда он вернулся уже к техническим темам, недавно с Нобелевским лауреатом по физике общался, вот тоже очень интересный подкаст. +6088.70 6101.82 "Анатолий Кулаков" Короче, если кому-то интересно встать в сторону популяризации физики искусственного интеллекта и прочего вот этого научного нормальным языком среди нормальными людьми и гостями, вот всячески советую Ивана. +6101.82 6107.10 "Анатолий Кулаков" И опять, где бы его доклад не увидели, обязательно поэкспериментируйте, посмотрите, думаю, вам зайдёт. +6107.10 6113.82 "Анатолий Кулаков" Так, и последняя на рассылочка, которую я хотел с вами поделиться, это Кадаза. +6113.82 6119.90 "Анатолий Кулаков" Недавно мы в нашем чатике открыли для себя этот забавный ресурс, это ролики про обучение на C#. +6119.90 6138.78 "Анатолий Кулаков" В принципе, обучение на C# на русском языке, их есть много в интернете, это даже не самый популярный, я так думаю, но что выделяет его среди всех остальных, это у него есть шоты ютубовские, это 30-секундные ролики, которые вам за 30 секунд рассказывают какую-то тему. +6138.78 6150.82 "Анатолий Кулаков" И там очень клёвые темы, например, там топ 10 вещей в АСП.нете, которые должен знать каждый разработчик, типа как устроить перформанс, или как за 30 секунд объясняется, как устроен семафор. +6150.82 6154.78 "Анатолий Кулаков" В общем, такие вещи, которые начинающему разработчику просто must have. +6154.78 6161.94 "Анатолий Кулаков" И как бы потратить 30 секунд, пока ты там, не знаю, едешь где-нибудь в лифте или что-то в этом духе, каждый способен. +6161.94 6165.38 "Анатолий Кулаков" Ролики классные, интересные, записаны прикольно. +6165.38 6169.98 "Анатолий Кулаков" И ещё одна отличная фишка этого канала, это в том, что там прекрасная графика. +6169.98 6177.38 "Анатолий Кулаков" Я не знаю, в чём это делается, если вы вдруг знаете, в каких редакторах или с помощью каких средств, инструментов, обязательно напишите нам в комментарии. +6177.38 6184.26 "Анатолий Кулаков" В общем, графика там обалденная, то есть это всё показывается с цветной анимацией, красиво, наглядно, по делу. +6184.26 6190.54 "Анатолий Кулаков" И что ещё раз прибавляет пользы того материала, который там и так очень хорошо подаётся. +6190.54 6203.82 "Анатолий Кулаков" В общем, если вы начинающий разработчик или просто вам интересно, как можно сделать современные интересные ролики про программирование, красочно, бодро и занимательно, в общем, попробуйте, посмотрите на YouTube канал Кадаза. +6203.82 6207.26 "Игорь Лабутин" Да, интересно, там причём не только короткие, там есть и более длинные. +6207.26 6208.26 "Игорь Лабутин" Короче, всё. +6208.26 6215.22 "Анатолий Кулаков" Да, да, длинные тоже с прекрасной графикой, с отличным объяснением, тоже миллион просмотров, поэтому да. +6215.22 6223.94 "Игорь Лабутин" Ну и там есть Telegram-каналчик, в котором чуть более часто выходят какие-то новости, хотя они в видеоформате, так что да, может быть действительно будет интересно, если вы изучаете C#. +6223.94 6232.22 "Игорь Лабутин" Ну что, на этом, наверное, на сегодня надо нам заканчивать, мы с тобой уже сидим почти 3 часа, всё это пишем, готовим +6232.22 6234.82 "Анатолий Кулаков" и так далее, так что… Да, уже скоро утро. +6234.82 6240.70 "Игорь Лабутин" Ну ещё не утро, но да, на часах час ночи, чтобы вы знали, как мы всё это пишем. +6240.70 6258.90 "Игорь Лабутин" Так что да, сегодня мы посмотрели на то, быстрый ли у нас S/Panet Core, подумали, как раскладывать файлики в новых проектах с минимальной API, при этом давайте все будем использовать новый MemoryPack Serializer, который ещё сам супербыстрый, собирать это всё GitHub-экшенами на GitHub. +6258.90 6276.06 "Игорь Лабутин" А если вы собирались собрать .NET, то к вашим услугам теперь есть монолитный репозиторий всего .NET в месте, если же вы собираете ваши Nuget пакеты, берите Nugetizer, делайте это всё в райдере, который стал ещё быстрее, особенно по сравнению с Visual Studio, да ещё и с ReSharper. 6276.06 6279.46 None Ну а в свободное время слушайте подкасты, про которые говорил Толя. -6279.46 6284.70 SPEAKER_02 На этом всё, это был 63 выпуск Radio.net. -6284.70 6294.10 SPEAKER_00 Да, всем счастливо, подписывайтесь, шарьте, рассказывайте друзьям, жмите нам на колокольчик, мы ждём ваших комментариев и всячески нас распространяйте. -6294.10 6295.98 SPEAKER_00 Всем спасибо, всем пока! -6295.98 6296.70 SPEAKER_00 Всем пока! -6296.70 6313.98 None [музыка] +6279.46 6284.70 "Игорь Лабутин" На этом всё, это был 63 выпуск Radio.net. +6284.70 6294.10 "Анатолий Кулаков" Да, всем счастливо, подписывайтесь, шарьте, рассказывайте друзьям, жмите нам на колокольчик, мы ждём ваших комментариев и всячески нас распространяйте. +6294.10 6295.98 "Анатолий Кулаков" Всем спасибо, всем пока! +6295.98 6296.70 "Анатолий Кулаков" Всем пока! diff --git a/input/Radio/Transcriptions/RadioDotNet-87.txt b/input/Radio/Transcriptions/RadioDotNet-87.txt index ccfe5f0..24e5164 100644 --- a/input/Radio/Transcriptions/RadioDotNet-87.txt +++ b/input/Radio/Transcriptions/RadioDotNet-87.txt @@ -1,928 +1,927 @@ -0.00 11.68 SPEAKER_00 Здравствуйте, дорогие друзья, в эфире Radio.net и выпуск 87-й. -11.68 14.94 SPEAKER_00 Сегодня с вами в студии Анатолий Кулаков. -14.94 15.94 SPEAKER_01 И Игорь Лабутин. -15.94 16.94 SPEAKER_01 Всем привет. -16.94 19.90 SPEAKER_00 А также большое спасибо всем нашим помогаторам. -19.90 25.66 SPEAKER_00 Если вы не знаете, о чем мы сейчас говорим, проходите на наш сайт на Boosty и присоединяйтесь к доброму списку. -25.66 35.50 SPEAKER_00 Александр, Сергей, Владислав, Шевченко Антон, Лазарев Илья, Гурий Самарин, Виктор, Руслан Артамонов, Александр Ерыгин, Сергей Бензенко, Александр Лапердин и Ольга Бондаренко. -35.50 39.06 SPEAKER_00 Спасибо, друзья, а также те, кто пожелал остаться неизвестными. -39.06 41.70 SPEAKER_00 Так, что у нас интересного? -41.70 44.26 SPEAKER_01 Ну, у нас сегодня, как обычно, много интересного. -44.26 47.06 SPEAKER_01 Мы, как обычно, проговорим часа два, не меньше. -47.06 49.54 SPEAKER_01 Ну, там посмотрим, сколько останется после сведения. -49.54 53.66 SPEAKER_01 Ну, начнем мы с Эндрю Лока, с статейка Эндрю Лока. -53.66 56.94 SPEAKER_01 Обычно мы их как-то на серединку-конец оставляем, но сегодня прямо начнем с нее. -56.94 57.94 SPEAKER_01 Давай. -57.94 62.94 SPEAKER_00 Ну, потому что обычно вначале у нас Микрософт, да, Микрософт сейчас пока еще спит, что-то он после каникул еще не -62.94 63.94 SPEAKER_01 очухался. -63.94 71.94 SPEAKER_01 Ну, не факт, что спит, может быть, они готовят что-то важное и интересное, как в релиз кандидата, ой, да, это что у нас будет, превью один, не релиз кандидата, конечно. -71.94 72.94 SPEAKER_01 Превью один, что-нибудь выкатит, эдакое. -72.94 73.94 SPEAKER_01 Сейчас как бахнут. -73.94 74.94 SPEAKER_01 Весь подкаст обсуждать будем. -74.94 75.94 SPEAKER_01 Ну, посмотрим. -75.94 76.94 SPEAKER_01 Будем надеяться, будем надеяться. -76.94 80.94 SPEAKER_00 Для нас, чем больше инфоповодов, тем лучше. -80.94 99.74 SPEAKER_00 Кстати, про инфоповоды, .NEXT открыл CFP, поэтому если вы мечтали стать докладчиком на весь мир, прогреметь и побывать на самой большой .NET конференции в России, то милости просим, подавайтесь на доклады, заходите, смотрите, что там есть интересного. -99.74 102.82 SPEAKER_00 И к локу, да, вернемся к локу. -102.82 111.94 SPEAKER_00 И лок у нас, в принципе, он обычно по ISP нас гоняет, но в этот раз он решил рассмотреть дефолт имплеметейшн метод для интерфейсов. -112.50 121.22 SPEAKER_00 Такая спорная тема, мы, по-моему, на весь год, прошлый год про нее что-нибудь выдумывали, обсуждали, насколько это будет плохо, насколько будет хорошо. -121.22 124.62 SPEAKER_00 Как тебе, Игорь, вот зарелизились дефолт интерфейс методы? -124.62 126.94 SPEAKER_00 Оправдались ли все твои страхи или наоборот? -126.94 130.94 SPEAKER_01 Честно говоря, я их прям так напрямую особо и не использую. -130.94 138.18 SPEAKER_01 Вот я что-то не припомню, чтобы я хоть раз писал именно дефолтный интерфейс метод в своем обычном коде, как-то не нужно было. -138.18 140.86 SPEAKER_01 Может быть, в библиотеках это прям сильно нужно, мне не пригождалось пока. -140.86 165.94 SPEAKER_00 Ну вот тоже, я напомню, что самое главное опасение всего сообщества было в том, что абстрактные классы как-то выродятся, все начнут вымазывать интерфейс имплементацией, запихивать туда всякие непотребные методы, а абстрактные классы уйдут в небытие, и вот эта вот наша святая, долго играющая преемственность в наследовании, она вообще вся испортится, испоганится, непонятно, что будет. -165.94 170.66 SPEAKER_00 Ну, как показала практика, хоть и недолгая, в принципе, этого не происходит. -170.66 186.58 SPEAKER_00 Дефолтная имплементация в методах, в дефолтных интерфейсах этих, она используется довольно редко, используется довольно специфично, абстрактные классы по-прежнему на месте, и люди пока не сильно злоупотребляют этими методами, что в принципе и требовалось. -186.58 189.46 SPEAKER_00 То есть их нужно применять там, где они в реальности нужны. -189.46 193.66 SPEAKER_00 А там, где не нужны, их применять, как вы, наверное, догадались, не следует. -193.66 205.02 SPEAKER_00 Так что, в принципе, не такие они получились страшные, как все об этом думали, как бы, если подходить с умом, то даже микроскопом можно забивать гвозди. -205.02 208.42 SPEAKER_00 Итак, что же нам Эндрю про них рассказывает? -208.42 212.58 SPEAKER_00 Ну, прежде всего, как положено, прямо с самого начала, что же такое, за чудо такое. -212.58 223.22 SPEAKER_00 Прежде всего, методы, эти дефолт интерфейс метод, а также, в принципе, правильнее будет назвать дефолт интерфейс имплементейшнс, потому что там не только методы могут быть. -223.22 246.46 SPEAKER_00 Они были введены в C# восьмом, и основная их цель была для того, чтобы эволюционировать и изменять интерфейсы без breaking changes, то есть без калечащих изменений, потому что на самом деле, даже добавление поля, казалось бы, такой безобидная вещь, как добавление, вы уже не удаляете, не ренеймите, а просто добавляете. -246.46 258.02 SPEAKER_00 Даже добавление поля к интерфейсу, это является breaking changes, потому что на этот интерфейс уже могла насоздаваться куча наследников, и все ваши наследники перестанут компилироваться. -258.02 265.86 SPEAKER_00 В случае Microsoft, если они, допустим, в системных интерфейсах что-то добавят, может перестать компилироваться полмира, поэтому они себе этого позволить не могли. -265.86 271.06 SPEAKER_00 И вот эта проблема решалась с помощью дефолтной реализации интерфейсов. -271.06 274.74 SPEAKER_00 И начиная с .NET восьмого, что мы можем делать? -274.74 282.98 SPEAKER_00 Мы теперь можем в интерфейсах задавать не только заголовки, но и реализовывать непосредственно само тело, реализовать метод body. -282.98 295.98 SPEAKER_00 И после того, как мы это смогли сделать, уже добавление каких-то методов не стало breaking changes, т.е. ваш код по-прежнему продолжит компилироваться, несмотря на то, что в интерфейсе могло добавиться еще 10 методов. -295.98 299.42 SPEAKER_00 На первый взгляд это очень сильно походит на абстрактные классы. -299.42 305.94 SPEAKER_00 Т.е. вполне валидный вопрос, а чем абстрактные классы отличаются от интерфейса с дефолтной имплементацией. -305.94 312.82 SPEAKER_00 Но на этот вопрос мы ответим немножко позже, но на первый взгляд это, в принципе, кажется одним и тем же. -312.82 324.12 SPEAKER_00 Так, и после того, как мы научились добавлять дефолтную имплементацию после .NET восьмого, Microsoft стал это обширно использовать. -324.12 330.46 SPEAKER_00 Ну, опять же, не злоупотребляя, в своих библиотеках, и наш код после этого не ломается. -330.46 337.08 SPEAKER_00 В общем, то, что они хотели добиться этим, сейчас видно, что они этого достигли, и, в принципе, все счастливы. -337.08 355.38 SPEAKER_00 Также нужно отметить, что реализовать мы можем не только методы в интерфейсах, в интерфейсах мы можем также заводить свойства, мы можем заводить приватные филды, не только публичные, например, мы можем заводить статические методы, в общем, там творится практически такая же свобода, как и в обычных классах. -355.38 375.66 SPEAKER_00 Теперь давайте же все-таки поговорим, а что же с ними не так, чем они отличаются в абстрактных классах, а самое главное, какие есть подводные камни при использовании этих дефолтных имплементаций, потому что вроде все ввели, про них все забыли, но мало кто догадывает, зачем чревато, если вдруг в своем коде вы захотите вот такую штуку использовать. -375.66 386.54 SPEAKER_00 Итак, первый подводный камень, с которым вы, возможно, столкнетесь, это в том, что в отличие от абстрактных классов, дефолтные методы в интерфейсах, они не наследуются. -386.54 387.70 SPEAKER_00 Что это значит? -387.70 405.50 SPEAKER_00 Это значит, что если у вас есть интерфейс iCustomer и реализация sampleCustomer, и в интерфейсе iCustomer вы объявили некий метод дефолтным, то есть сделали ему body, написали там какое-то возвращаемое значение, дальше вы пытаетесь это в коде вашем использовать. -405.50 431.92 SPEAKER_00 И как только вы создаете вот этого кастомера и пытаетесь обратиться через интерфейс к вот этому defaultImplement методу, то все у вас будет хорошо, потому что этот дефолтный метод есть в интерфейсе, но как только вы пытаетесь обратиться к sampleCustomer, то есть к наследнику от этого интерфейса, пытаетесь у него найти метод, который дефолтно был добавлен в интерфейсе, вы этого метода не найдете. -431.92 436.28 SPEAKER_00 То есть ваш код просто не скомпилируется, потому что этого метода в данном классе нет. -436.28 446.90 SPEAKER_00 Этого отличают от абстрактного класса, если что, потому что если вы наследуетесь от абстрактного класса, естественно, метод будет как в самом абстрактном классе, так и в наследнике. -446.90 455.02 SPEAKER_00 В случае дефолт интерфейс методов, метод будет только в интерфейсе, а в самом наследнике его не будет, если будете обращаться непосредственно к наследнику. -455.02 459.54 SPEAKER_00 То есть вызвать мы его напрямую не сможем. -459.54 461.30 SPEAKER_00 Решается эта проблема очень просто. -461.30 467.70 SPEAKER_00 Мы берем этого sampleCustomer и сохраняем в переменную iCustomer, то есть переменную с интерфейсом, ну или кастим к интерфейсу. -467.70 471.98 SPEAKER_00 И после того, как мы его скастили, то этот метод на него магическим образом появляется. -471.98 473.98 SPEAKER_00 Кажется, что все нормально. -473.98 500.34 SPEAKER_00 Вот такое небольшое неудобство, в принципе оно расходится с тем, как нам бы, наверное, очевидно, хотелось бы это видеть, но оно было добавлено как раз таки для того, что если вдруг в классе уже такой метод был реализован, или какой-нибудь reflection оббегал этот класс в поисках всех методов, наверное, чтобы он не нашел и у вас не получилось бы какого-то bracketChanger, то есть не нашел эту дефолтную имплементацию. -500.34 505.82 SPEAKER_00 В общем, ради обратной совместимости пришлось ввести такое не очень интуитивное поведение. -505.82 506.82 SPEAKER_00 Дальше. -506.82 508.62 SPEAKER_00 На этом подводные камни не кончаются. -508.62 513.70 SPEAKER_00 Прежде всего, иерархия виртуальных вызовов, т.е. -513.70 527.74 SPEAKER_00 как, наверное, вызываются виртуальные методы с абстрактными классами, все мы знаем, т.е. их можно переопределить, с ними можно и пронаследовать, не переопределять, воспользоваться дефолтным поведением из абстрактного класса и так далее. -527.74 539.34 SPEAKER_00 Когда мы пытаемся сделать то же самое и с дефолтными методами, ну, например, есть у нас интерфейс Shape, который возвращает в виде строки свое имя, getName у него возвращает iShape. -539.34 559.78 SPEAKER_00 Если мы от этого интерфейса, да, и getName это метод, который заимплементирован по дефолту в этом интерфейсе, дальше мы делаем от наследника, который называется Rectangle, и Rectangle наследуется от iShape, при этом не переопределяя метод getName, ну, т.е. по сути должен использовать базовый метод. -559.78 569.46 SPEAKER_00 И дальше мы от Rectangle наследуем квадратик, квадратик тоже переопределяет getName и говорит, что мой name это квадратик. -569.46 572.42 SPEAKER_00 Тут как бы тоже все вроде пока прямо и очевидно. -572.42 580.26 SPEAKER_00 А теперь, внимание, вопрос, что будет, если мы создадим квадратик, приведем его к интерфейсу iShape и дернем у него метод getName? -580.26 594.06 SPEAKER_00 Ну, кажется, что если бы мы делали это все с абстрактными классами, то, естественно, даже несмотря на то, что мы у iShape переменной дернули getName, то override ее в квадратике должен был вернуть нам слово квадратик. -594.06 599.82 SPEAKER_00 Но нет, так не произойдет, нам вернется именно iShape. -599.82 606.66 SPEAKER_00 Это поведение неинтуитивное, и оно абсолютно сбивает с толку тех, кто привык к абстрактным классам и привык от них наследоваться. -606.66 633.14 SPEAKER_00 Для того, чтобы пофиксить это поведение, вам необходимо в наследнике квадратика пронаследоваться не только от Rectangle, но и явно пронаследоваться от интерфейса iShape, несмотря на то, что Rectangle и так наследуется от интерфейса iShape, т.е. здесь вам нужно явное наследование сделать, и только после этого квадратик подхватит override из базового интерфейса. -633.14 634.14 SPEAKER_00 Следующая проблема. -634.14 637.98 SPEAKER_00 Насколько вы знаете, в C# не существует множественного наследования. -637.98 641.38 SPEAKER_00 Кстати, в C, там C++, оно есть. -641.38 648.26 SPEAKER_00 И самая главная причина, на которую все ссылались при дизайне языка, почему так не было сделано, это Diamond Inheritance Problem. -648.26 651.38 SPEAKER_00 Игорь, ты знаешь, как на русский переводится эта -651.38 654.30 SPEAKER_01 проблема? -654.30 659.50 SPEAKER_01 Ромбовидное наследование, обычно я что-то из своих древних плюсовых времён помню какой-то такой термин. -659.50 666.14 SPEAKER_00 Ну да-да, мне тоже кажется, что-то с равновидным, не какое-нибудь там бриллиантовое или… -666.14 668.42 SPEAKER_01 Нет-нет, ну ромбовидное, да. -668.42 670.66 SPEAKER_01 Ну что-то там с ромбами было связано. -670.66 673.74 SPEAKER_01 Ну и оно рисуется в виде ромба обычно, поэтому вот. -673.74 674.74 SPEAKER_00 Да. -674.74 686.10 SPEAKER_00 А рисуется в виде ромба неспроста, потому что эта проблема, она очень похожа на ромб, если представить наследование в виде такой своеобразной диаграммы. -686.10 693.02 SPEAKER_00 Допустим, у вас есть класс IShape, у IShape наследуется первый наследник и наследуется второй наследник. -693.02 694.90 SPEAKER_00 А потом мы захотели сделать класс. -694.90 702.46 SPEAKER_00 И этот класс мы хотим, чтобы он имплементировал два интерфейса, интерфейс наследник 1 и интерфейс наследник 2. -702.46 709.90 SPEAKER_00 И у IShape есть метод getName, и у первого наследника есть getName, и у второго наследника есть getName. -709.90 716.42 SPEAKER_00 И все эти getNames, они переопределены во всех этих трёх интерфейсах, так как мы теперь можем это делать. -716.42 717.42 SPEAKER_00 Вот. -717.42 718.42 SPEAKER_00 И теперь, внимание, вопрос. -718.42 733.06 SPEAKER_00 Вот наш класс, последний, четвёртый, который хочет пронаследоваться и от второго, и от третьего наследника, какой у него метод getName вызовется, т.е. что вернёт, от какого наследника. -733.06 736.46 SPEAKER_00 Это, в принципе, в общем случае неразрешимая проблема. -736.46 740.94 SPEAKER_00 И именно поэтому и не стали делать множественное наследование в C#. -740.94 755.02 SPEAKER_00 Ну, как только у нас появляется дефолтная реализация интерфейси на методах, а методов, а интерфейсов, т.е. мы можем пронаследовать сколько угодно в нашем классе, у нас вот эта ромбовинная проблема наследования, она встаёт в полный рост снова. -755.02 760.34 SPEAKER_00 И здесь Микрософт пошёл самым правильным, наверное, путём. -760.34 762.94 SPEAKER_00 Он на уровне компиляции запрещает такое компилировать. -762.94 767.74 SPEAKER_00 Т.е. он говорит, что компилятор не может найти самый лучший метод, который вам подходит, идите и явно его укажите. -767.74 770.82 SPEAKER_00 В общем, и указать явно это, естественно, можно. -770.82 781.26 SPEAKER_00 Таким образом мы избавляемся от всяких проблем и в рантайме не ловим каких-то непонятных исключений или даже непонятного поведения, я бы сказал, которое вполне вас могло преследовать всю плюс-плюсе. -781.26 783.34 SPEAKER_00 Так, погнали дальше. -783.34 793.34 SPEAKER_00 Следующая проблема, с которой, возможно, столкнётесь, если вы захотите пронаследовать структуру от вашего интерфейса, в котором есть дефолт имплементации. -793.34 799.82 SPEAKER_00 Естественно, структуры тоже могут наследовать интерфейсы, но здесь есть парочка небольших проблем. -799.82 808.78 SPEAKER_00 Прежде всего, для того, чтобы использовать дефолтный метод из дефолтного этого интерфейса, вам необходимо будет структуру прикастить к интерфейсу. -808.78 818.50 SPEAKER_00 Как мы уже обсуждали чуть ранее, что только интерфейс может вызывать методы, которые явно задекларированы в интерфейсе, но их нет в самом наследнике. -818.50 822.98 SPEAKER_00 И как только вы кастите структуру к интерфейсу, у вас неизбежно появляется боксинг. -822.98 830.30 SPEAKER_00 А боксинг у вас появляется не просто так, а вместе с избыточным потреблением памяти, то есть вызывается memory location. -830.30 838.54 SPEAKER_00 И обычно, то есть в обычных программах, наверное, вам memory location может не так страшен, но здесь мы используем структуру. -838.54 841.26 SPEAKER_00 И обычно структуру используют как раз там, где памяти выделять не надо. -841.26 844.70 SPEAKER_00 И это высокопроизводительный и обычный оптимальный код. -844.70 846.90 SPEAKER_00 Как раз где не хочется в ХИПе выделять память. -846.90 853.98 SPEAKER_00 И как только вы начинаете кастить вашу структуру к интерфейсу, вы автоматически все плюсы структуры как бы теряете. -853.98 857.30 SPEAKER_00 Поэтому, скорее всего, именно в этом месте вы этого не хотите. -857.30 870.50 SPEAKER_00 И также нужно сказать, что дефолтные методы в интерфейсе, когда пытаются изменить структуру, они получают ее, естественно, через интерфейс. -870.50 874.54 SPEAKER_00 То есть они по случаю получают забокшенную копию самой структуры. -874.54 878.02 SPEAKER_00 Таким образом, чтобы они там не меняли, до оригинала они никак не дотянутся. -878.02 884.50 SPEAKER_00 То есть, по сути, невозможно из дефолт имплементейшн метода обновить каким-то образом структуру. -884.50 888.38 SPEAKER_00 Из этих двух минусов можно сделать только один единственный правильный вывод. -888.38 896.30 SPEAKER_00 Не используйте структуры и дефолт интерфейс методы вместе, потому что вы явно этого не хотите. -896.30 904.98 SPEAKER_00 Еще один неочевидный подводный камень в том, что дефолтные методы требуют изменения в рантайме. -904.98 911.06 SPEAKER_00 Казалось бы, по идее, наверное, это изменение можно засунуть было в компилятор и все, и дело в шляпе. -911.06 912.06 SPEAKER_00 Но нет. -912.06 913.74 SPEAKER_00 Обновления компилятора вам недостаточно. -913.74 915.58 SPEAKER_00 Нужно еще будет обновиться рантайм. -915.58 923.54 SPEAKER_00 Они есть в рантайме после .NET третьего, поэтому можно смело на этот рантайм переходить, если вам они вдруг зачем-то нужны. -923.54 939.14 SPEAKER_00 В качестве хорошего примера для оптимизации Андрю Лок приводит хорошую оптимизацию от Бена Адамса, который умудрился увеличить перформанс iHeaderDictionary в три раза. -939.14 942.42 SPEAKER_00 В общем, сделал он это довольно нехитрым путем. -942.42 950.58 SPEAKER_00 Раньше к iHeaderDictionary, т.е. это специальный словарик, в который мы ходили за заголовками, аж теперь и квесты, аж теперь и спонсоры. -950.58 951.58 SPEAKER_00 Мы оттуда могли доставать заголовки. -951.58 956.02 SPEAKER_00 Как вы понимаете, заголовков бесконечное множество, там может быть абсолютно любой строковой ключ. -956.02 959.38 SPEAKER_00 В общем, мы раньше их доставали просто из дикшнери лукапом. -959.38 963.46 SPEAKER_00 Ну, не просто лукапом, там умным лукапом с мегаоптимизацией и так далее. -963.46 980.42 SPEAKER_00 Но все эти мегаоптимизации оказались довольно слабыми по сравнению с тем, что мы могли бы в этом iHeaderDictionary просто завести свойства для самых популярных хедров таких, там, accept, content-type, encoding и так далее, и просто обращаться к этим свойствам. -980.42 995.82 SPEAKER_00 Вот именно это Эндрю сделал, т.е. Бен Адамс сделал, сделал это с помощью дефолтных методов, т.е. теперь он на этом интерфейсе смог реализовать свойства, которые напрямую ходят к тому полю, который вы захотели, без всякого лукапа в дикшнере. -995.82 997.98 SPEAKER_00 И все это в три раза ускорило дикшнер. -997.98 1010.22 SPEAKER_00 Вот в принципе один из примеров, как Microsoft использует эти методы не только для расширения интерфейсов, а ради каких-то непонятных методов, ну и ради прям увеличения перформанса. -1010.22 1018.10 SPEAKER_00 Несмотря на то, что API там стал красивше и использовать этот дикшнер стал легче, но главная цель Бена, конечно же, была перформанс. -1018.10 1034.46 SPEAKER_00 Вот такие наши старые новые друзья, может, эта статья открыла для вас какие-то новые вещи, о которых вы раньше не знали и, может быть, как раз показала, почему и не следует в последненной жизни использовать дефолт интерфейс имплементейшнсы. -1034.46 1040.34 SPEAKER_01 Да, звучит интересно, потому что, ну кажется, относительно простая фича всего лишь. -1040.34 1045.38 SPEAKER_01 Казалось бы, добавили методы в интерфейсе, а столько проблем. -1045.38 1049.14 SPEAKER_01 Что может быть, кстати, подчеркивает, почему сложно дизайнить все эти языковые фичи. -1049.14 1054.06 SPEAKER_01 Казалось бы, придумали простую штуку, а вот надо со всем совместить. -1054.06 1063.34 SPEAKER_00 Наверное, главное теперь, что нужно придумать в языке или во всех новых языках, которые люди придумывают, самое главное, что нужно придумывать, это как вы будете избавляться от легоси-конструкции. -1063.34 1070.02 SPEAKER_00 Потому что сейчас это бич C#, и он нам мешает такие хорошие фичи вводить полноценно, красиво, ожидаемо. -1070.02 1074.94 SPEAKER_00 Вот всё это из-за обратной дурацкой совместимости, которая, в принципе-то, по большому счёту никому и не нужна. -1074.94 1077.66 SPEAKER_00 Ну в таком виде, в котором мы могли бы ей пренебречь. -1077.66 1086.86 SPEAKER_01 Ну именно, мы вообще рассказывали, кстати, на эту тему немножко, что команда C# придумала, что они с этим будут делать. -1086.86 1105.14 SPEAKER_01 Напоминаю, что в новом SDK, по-моему, начиная с девятки, если вы скомпилите ваш старый код в девятом SDK с таргетом в восьмёрку, он теоретически сможет вас предупредить, что смотрите, вот эти вот фичи, которые в вашем коде, если вы поменяете таргет на девятку, они изменят поведение. -1105.14 1115.38 SPEAKER_01 То есть, и за счёт этого они теперь могут делать breaking changes, то есть они меняют их, но поменяют так, что если вы компилите со старым таргетом, то поведение старое, например. -1115.38 1127.22 SPEAKER_01 Какое-нибудь там новое ключевое слово будет считаться просто обычной переменной, идентификатором, а вот если с таргетом девятка, то всё, это уже новое поведение, новое ключевое слово и вот это всё. -1127.22 1139.10 SPEAKER_01 Это таки позволит, наконец-таки, не знаю, вводить ключевые слова, не боясь того, что кто-то объявил класс с именем рекорд, с маленькой буквы, в таком духе. -1139.10 1141.38 SPEAKER_01 Так что, надеюсь, станет лучше. -1141.38 1144.58 SPEAKER_00 Да-да, это именно то решение, которое я имел в виду. -1144.58 1147.30 SPEAKER_00 Посмотрим, как оно себя покажет, но кажется, это то, что нам надо. -1147.30 1148.30 SPEAKER_01 Да. -1148.30 1149.30 SPEAKER_01 Пойдём дальше. -1149.30 1151.82 SPEAKER_01 Дальше у нас очередной новости про Aspire. -1151.82 1159.26 SPEAKER_01 На их, не то чтобы вышло статья, но на их гитхабе появилось ишьё, которое называется first release scoping. -1159.26 1164.22 SPEAKER_00 То есть понятно, что… Это для тех, кому не хватило до прошлого выпуска, посвящённое полностью Aspire. -1164.22 1178.42 SPEAKER_01 Да, я боюсь, что… ладно, боюсь неправильный термин, но я думаю, что у нас Aspire будет так или иначе в каждом выпуске появляться, потому что, похоже, это одна из самых больших фичей или компонент, не знаю, направлений того, куда сейчас работает команда ASP. -1178.42 1182.30 SPEAKER_01 Ну, наверное, фреймворк, да, то есть это что-то рядом с AspNet. -1182.30 1192.26 SPEAKER_01 Это AspNet, да, главной движухой и промоутом этого всего занимается Дэвид Фаулер, который, собственно, до этого промоутил minimal API, а теперь вот занимается Aspire. -1192.26 1197.86 SPEAKER_01 Вот, итак, что, собственно, должно войти в первый релиз? -1197.86 1204.10 SPEAKER_01 Напоминаю, что сейчас Aspire это всё-таки превью, там раннее первое, второе, ну, короче, пока это всё очень превью. -1204.10 1213.98 SPEAKER_01 Всё может 20 раз меняться, и оно уже меняется, но когда будет релиз, значит, scope, который сейчас себе команда очертила, он следующий. -1213.98 1234.94 SPEAKER_01 Напоминаю, что Aspire это такой способ запихать в ваше приложение стандартные, так скажем, хорошо проверенные временем конфигурации для широко известных компонент и добавить к этому возможность, соответственно, сервис дискавери, правильной телеметрии и вот этого всего. -1234.94 1243.22 SPEAKER_01 И поэтому, когда мы говорим про скопинг, во-первых, в первую очередь, конечно же, речь идёт о компонентах, ну и ресурсах. -1243.22 1260.34 SPEAKER_01 И здесь Microsoft говорит следующее, что из open-source, они будут ну, open-source на это громко сказано, потому что там есть SQL-сервер, но у них это называется OSS раздел, и там написано, что там будет поддержана Postgres, MySQL, SQL-сервер, Oracle, Mongo, Redis, Kafka и RabbitMQ. -1260.34 1274.46 SPEAKER_01 Ну, то есть, наверное, не знаю, 90% наверное не скажу, но очень существенная часть всего стандартного такого базданческого, ну, базданных, эстеков и кэшей, да? -1274.46 1278.94 SPEAKER_01 Точно есть ещё какие-то, вернее, точно есть ещё какие-то, но это, наверное, покроет большой процент. -1278.94 1284.46 SPEAKER_00 Да, да, хороший список, прям нормальный стандартный стек-энтерпрайзер, и не только. -1284.46 1285.46 SPEAKER_01 Да. -1285.46 1295.94 SPEAKER_01 Дальше, естественно, не могли обойти вниманием Ажуру, там будет, ну, мы уже говорили про Cosmos, Storage, всякие разные, сервис-баски, Vault, OpenAI, AI-сёрч, куда же без AI? -1295.94 1299.46 SPEAKER_01 Azure Redis, Azure Postgres, Azure SQL, тут всё нормально. -1299.46 1309.70 SPEAKER_01 И Dapr мы упоминали в последнем выпуске, что они сделали заделочки под Dapr, соответственно, вот стоит Store и Pub/Sub из Dapr тоже нативно будут, ну, нативно, в смысле, в скоупе релиза будут поддержаны. -1309.70 1323.06 SPEAKER_01 Для дэшборда запланирован очень важный и нужный шаг, называется декаплинг, то есть так, чтобы дэшборд можно было запускать абсолютно отдельно от вашего приложения. -1323.06 1345.58 SPEAKER_01 Сейчас напоминаю, что вы должны, для того, чтобы вставить Aspire в ваш продукт, нужно создать отдельный проект, из него зареференсить или каким-то образом заиспользовать там через пути компоненты, еще через что-нибудь ваши основные остальные проекты, приложения, и после этого, именно из этого продукта, этот проект вы делаете стартом и из него запускается дэшборд. -1345.58 1359.62 SPEAKER_01 Так вот, теперь есть уже pull-request, он вмёржен, то есть последняя ветка мастера или мейна, что у них там в этом самом репозитории, уже содержит отрезанный дэшборд, который как-то можно запускать отдельно. -1359.62 1384.26 SPEAKER_01 Пока еще нет толковой документации, я пока не видел, может быть, уже появилось там, с момента, как я смотрел, недельку назад, но теперь дэшборд в каком-то смысле отцеплен от основного приложения, с которым он работает, и может быть это означает, что мы сможем вскоре увидеть абсолютно standalone дэшборд, который не требует каких-то, ну какой-то магии для своей работы. -1384.26 1388.78 SPEAKER_01 Посмотрим, что они подразумевают под декаплингом, пока просто написано. -1388.78 1389.78 SPEAKER_01 Дэшборд декаплинг. -1389.78 1394.74 SPEAKER_00 А ты не знаешь, он будет запускаться как бы в отдельном процессе, или все равно процесс должен быть этот же? -1394.74 1396.18 SPEAKER_00 То есть как он будет слушать, по сути, все эти метрики? -1396.18 1424.30 SPEAKER_01 Нет, процесс он и был отдельный в любом случае, он по-любому отдельный процесс, он слушает, потому что у него LP-сервер, ну оплентелеметрии и кто там еще, вот, он в любом случае слушает, просто другое дело, что если ты помнишь прошлый выпуск, то мы обсуждали, что там есть еще так называемый DCP, Data Control Plane, или нет, странное название, ну короче, Control Plane, какой-то отдельный процесс, который как раз всем управляет. -1424.30 1434.86 SPEAKER_01 Вот, и дэшборд – это просто отдельный процесс, из которого торчит, собственно, бэкэнд для вот этого фронт-энд-приложения, которое в браузере. -1434.86 1438.70 SPEAKER_01 Поэтому это будет отдельный процесс, однозначно. -1438.70 1459.70 SPEAKER_01 Проблема в том, как научить остальные процессы в системе, ну или в вашем продукте репортить в этот процесс, то есть будут ли какие-то там well-known-урлы, будут ли какие-то, ну короче, непонятно, поскольку он, если он отрезан от основного приложения и не используется для запуска основного приложения, то каким-то образом конфигурацию нужно будет прокинуть. -1459.70 1468.90 SPEAKER_00 Ну, наверное, такой же, как и во всех остальных LTP-сервисах, ты должен подключить внешний телеметрий-провайдер и писать туда, или какой-то агент должен собирать от тебя информацию. -1468.90 1485.38 SPEAKER_01 Я очень надеюсь, что это ровно так, потому что тогда это позволяет использовать его вообще для чего угодно, даже для того, чего Майкрософт не предполагал, ну грубо говоря, для каких-то приложений, там, не знаю, на Java, на Python, на Rust, на Go, да, которые ты просто так из студии не запустишь. -1485.38 1490.86 SPEAKER_00 Ну, я думаю, что они не зря на LTP-сервис рассчитывали на этот протокол. -1490.86 1496.14 SPEAKER_00 То есть они, скорее всего, предполагают, что его можно использовать как standalone-приложение с абсолютно любыми другими приложениями. -1496.14 1501.46 SPEAKER_00 То есть мы ждём конкурента Эластику, или чего-то у нас ещё есть? -1501.46 1502.46 SPEAKER_00 Ну, Эластику, Графани, там, не знаю. -1502.46 1503.46 SPEAKER_00 Графани, да-да-да. -1503.46 1504.46 SPEAKER_01 Чему-нибудь такому. -1504.46 1514.62 SPEAKER_01 Слушай, посмотрим, в том плане, что я думаю, что сейчас должны появиться статьи на предмет как бы, как это мы всё сделали, чтобы оно вместе заработало. -1514.62 1526.90 SPEAKER_01 В смысле, что такое standalone и так далее, потому что пока просто всё очень рано, в смысле, что, ну, только-только вот pull-request недавно вмёрзли, и поэтому пока рано говорить, что всё из этого получится. -1526.90 1527.90 SPEAKER_01 Посмотрим. +0.00 11.68 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Radio.net и выпуск 87-й. +11.68 14.94 "Анатолий Кулаков" Сегодня с вами в студии Анатолий Кулаков. +14.94 15.94 "Игорь Лабутин" И Игорь Лабутин. +15.94 16.94 "Игорь Лабутин" Всем привет. +16.94 19.90 "Анатолий Кулаков" А также большое спасибо всем нашим помогаторам. +19.90 25.66 "Анатолий Кулаков" Если вы не знаете, о чем мы сейчас говорим, проходите на наш сайт на Boosty и присоединяйтесь к доброму списку. +25.66 35.50 "Анатолий Кулаков" Александр, Сергей, Владислав, Шевченко Антон, Лазарев Илья, Гурий Самарин, Виктор, Руслан Артамонов, Александр Ерыгин, Сергей Бензенко, Александр Лапердин и Ольга Бондаренко. +35.50 39.06 "Анатолий Кулаков" Спасибо, друзья, а также те, кто пожелал остаться неизвестными. +39.06 41.70 "Анатолий Кулаков" Так, что у нас интересного? +41.70 44.26 "Игорь Лабутин" Ну, у нас сегодня, как обычно, много интересного. +44.26 47.06 "Игорь Лабутин" Мы, как обычно, проговорим часа два, не меньше. +47.06 49.54 "Игорь Лабутин" Ну, там посмотрим, сколько останется после сведения. +49.54 53.66 "Игорь Лабутин" Ну, начнем мы с Эндрю Лока, с статейка Эндрю Лока. +53.66 56.94 "Игорь Лабутин" Обычно мы их как-то на серединку-конец оставляем, но сегодня прямо начнем с нее. +56.94 57.94 "Игорь Лабутин" Давай. +57.94 62.94 "Анатолий Кулаков" Ну, потому что обычно вначале у нас Микрософт, да, Микрософт сейчас пока еще спит, что-то он после каникул еще не +62.94 63.94 "Игорь Лабутин" очухался. +63.94 71.94 "Игорь Лабутин" Ну, не факт, что спит, может быть, они готовят что-то важное и интересное, как в релиз кандидата, ой, да, это что у нас будет, превью один, не релиз кандидата, конечно. +71.94 72.94 "Игорь Лабутин" Превью один, что-нибудь выкатит, эдакое. +72.94 73.94 "Игорь Лабутин" Сейчас как бахнут. +73.94 74.94 "Игорь Лабутин" Весь подкаст обсуждать будем. +74.94 75.94 "Игорь Лабутин" Ну, посмотрим. +75.94 76.94 "Игорь Лабутин" Будем надеяться, будем надеяться. +76.94 80.94 "Анатолий Кулаков" Для нас, чем больше инфоповодов, тем лучше. +80.94 99.74 "Анатолий Кулаков" Кстати, про инфоповоды, .NEXT открыл CFP, поэтому если вы мечтали стать докладчиком на весь мир, прогреметь и побывать на самой большой .NET конференции в России, то милости просим, подавайтесь на доклады, заходите, смотрите, что там есть интересного. +99.74 102.82 "Анатолий Кулаков" И к локу, да, вернемся к локу. +102.82 111.94 "Анатолий Кулаков" И лок у нас, в принципе, он обычно по ISP нас гоняет, но в этот раз он решил рассмотреть дефолт имплеметейшн метод для интерфейсов. +112.50 121.22 "Анатолий Кулаков" Такая спорная тема, мы, по-моему, на весь год, прошлый год про нее что-нибудь выдумывали, обсуждали, насколько это будет плохо, насколько будет хорошо. +121.22 124.62 "Анатолий Кулаков" Как тебе, Игорь, вот зарелизились дефолт интерфейс методы? +124.62 126.94 "Анатолий Кулаков" Оправдались ли все твои страхи или наоборот? +126.94 130.94 "Игорь Лабутин" Честно говоря, я их прям так напрямую особо и не использую. +130.94 138.18 "Игорь Лабутин" Вот я что-то не припомню, чтобы я хоть раз писал именно дефолтный интерфейс метод в своем обычном коде, как-то не нужно было. +138.18 140.86 "Игорь Лабутин" Может быть, в библиотеках это прям сильно нужно, мне не пригождалось пока. +140.86 165.94 "Анатолий Кулаков" Ну вот тоже, я напомню, что самое главное опасение всего сообщества было в том, что абстрактные классы как-то выродятся, все начнут вымазывать интерфейс имплементацией, запихивать туда всякие непотребные методы, а абстрактные классы уйдут в небытие, и вот эта вот наша святая, долго играющая преемственность в наследовании, она вообще вся испортится, испоганится, непонятно, что будет. +165.94 170.66 "Анатолий Кулаков" Ну, как показала практика, хоть и недолгая, в принципе, этого не происходит. +170.66 186.58 "Анатолий Кулаков" Дефолтная имплементация в методах, в дефолтных интерфейсах этих, она используется довольно редко, используется довольно специфично, абстрактные классы по-прежнему на месте, и люди пока не сильно злоупотребляют этими методами, что в принципе и требовалось. +186.58 189.46 "Анатолий Кулаков" То есть их нужно применять там, где они в реальности нужны. +189.46 193.66 "Анатолий Кулаков" А там, где не нужны, их применять, как вы, наверное, догадались, не следует. +193.66 205.02 "Анатолий Кулаков" Так что, в принципе, не такие они получились страшные, как все об этом думали, как бы, если подходить с умом, то даже микроскопом можно забивать гвозди. +205.02 208.42 "Анатолий Кулаков" Итак, что же нам Эндрю про них рассказывает? +208.42 212.58 "Анатолий Кулаков" Ну, прежде всего, как положено, прямо с самого начала, что же такое, за чудо такое. +212.58 223.22 "Анатолий Кулаков" Прежде всего, методы, эти дефолт интерфейс метод, а также, в принципе, правильнее будет назвать дефолт интерфейс имплементейшнс, потому что там не только методы могут быть. +223.22 246.46 "Анатолий Кулаков" Они были введены в C# восьмом, и основная их цель была для того, чтобы эволюционировать и изменять интерфейсы без breaking changes, то есть без калечащих изменений, потому что на самом деле, даже добавление поля, казалось бы, такой безобидная вещь, как добавление, вы уже не удаляете, не ренеймите, а просто добавляете. +246.46 258.02 "Анатолий Кулаков" Даже добавление поля к интерфейсу, это является breaking changes, потому что на этот интерфейс уже могла насоздаваться куча наследников, и все ваши наследники перестанут компилироваться. +258.02 265.86 "Анатолий Кулаков" В случае Microsoft, если они, допустим, в системных интерфейсах что-то добавят, может перестать компилироваться полмира, поэтому они себе этого позволить не могли. +265.86 271.06 "Анатолий Кулаков" И вот эта проблема решалась с помощью дефолтной реализации интерфейсов. +271.06 274.74 "Анатолий Кулаков" И начиная с .NET восьмого, что мы можем делать? +274.74 282.98 "Анатолий Кулаков" Мы теперь можем в интерфейсах задавать не только заголовки, но и реализовывать непосредственно само тело, реализовать метод body. +282.98 295.98 "Анатолий Кулаков" И после того, как мы это смогли сделать, уже добавление каких-то методов не стало breaking changes, т.е. ваш код по-прежнему продолжит компилироваться, несмотря на то, что в интерфейсе могло добавиться еще 10 методов. +295.98 299.42 "Анатолий Кулаков" На первый взгляд это очень сильно походит на абстрактные классы. +299.42 305.94 "Анатолий Кулаков" Т.е. вполне валидный вопрос, а чем абстрактные классы отличаются от интерфейса с дефолтной имплементацией. +305.94 312.82 "Анатолий Кулаков" Но на этот вопрос мы ответим немножко позже, но на первый взгляд это, в принципе, кажется одним и тем же. +312.82 324.12 "Анатолий Кулаков" Так, и после того, как мы научились добавлять дефолтную имплементацию после .NET восьмого, Microsoft стал это обширно использовать. +324.12 330.46 "Анатолий Кулаков" Ну, опять же, не злоупотребляя, в своих библиотеках, и наш код после этого не ломается. +330.46 337.08 "Анатолий Кулаков" В общем, то, что они хотели добиться этим, сейчас видно, что они этого достигли, и, в принципе, все счастливы. +337.08 355.38 "Анатолий Кулаков" Также нужно отметить, что реализовать мы можем не только методы в интерфейсах, в интерфейсах мы можем также заводить свойства, мы можем заводить приватные филды, не только публичные, например, мы можем заводить статические методы, в общем, там творится практически такая же свобода, как и в обычных классах. +355.38 375.66 "Анатолий Кулаков" Теперь давайте же все-таки поговорим, а что же с ними не так, чем они отличаются в абстрактных классах, а самое главное, какие есть подводные камни при использовании этих дефолтных имплементаций, потому что вроде все ввели, про них все забыли, но мало кто догадывает, зачем чревато, если вдруг в своем коде вы захотите вот такую штуку использовать. +375.66 386.54 "Анатолий Кулаков" Итак, первый подводный камень, с которым вы, возможно, столкнетесь, это в том, что в отличие от абстрактных классов, дефолтные методы в интерфейсах, они не наследуются. +386.54 387.70 "Анатолий Кулаков" Что это значит? +387.70 405.50 "Анатолий Кулаков" Это значит, что если у вас есть интерфейс iCustomer и реализация sampleCustomer, и в интерфейсе iCustomer вы объявили некий метод дефолтным, то есть сделали ему body, написали там какое-то возвращаемое значение, дальше вы пытаетесь это в коде вашем использовать. +405.50 431.92 "Анатолий Кулаков" И как только вы создаете вот этого кастомера и пытаетесь обратиться через интерфейс к вот этому defaultImplement методу, то все у вас будет хорошо, потому что этот дефолтный метод есть в интерфейсе, но как только вы пытаетесь обратиться к sampleCustomer, то есть к наследнику от этого интерфейса, пытаетесь у него найти метод, который дефолтно был добавлен в интерфейсе, вы этого метода не найдете. +431.92 436.28 "Анатолий Кулаков" То есть ваш код просто не скомпилируется, потому что этого метода в данном классе нет. +436.28 446.90 "Анатолий Кулаков" Этого отличают от абстрактного класса, если что, потому что если вы наследуетесь от абстрактного класса, естественно, метод будет как в самом абстрактном классе, так и в наследнике. +446.90 455.02 "Анатолий Кулаков" В случае дефолт интерфейс методов, метод будет только в интерфейсе, а в самом наследнике его не будет, если будете обращаться непосредственно к наследнику. +455.02 459.54 "Анатолий Кулаков" То есть вызвать мы его напрямую не сможем. +459.54 461.30 "Анатолий Кулаков" Решается эта проблема очень просто. +461.30 467.70 "Анатолий Кулаков" Мы берем этого sampleCustomer и сохраняем в переменную iCustomer, то есть переменную с интерфейсом, ну или кастим к интерфейсу. +467.70 471.98 "Анатолий Кулаков" И после того, как мы его скастили, то этот метод на него магическим образом появляется. +471.98 473.98 "Анатолий Кулаков" Кажется, что все нормально. +473.98 500.34 "Анатолий Кулаков" Вот такое небольшое неудобство, в принципе оно расходится с тем, как нам бы, наверное, очевидно, хотелось бы это видеть, но оно было добавлено как раз таки для того, что если вдруг в классе уже такой метод был реализован, или какой-нибудь reflection оббегал этот класс в поисках всех методов, наверное, чтобы он не нашел и у вас не получилось бы какого-то bracketChanger, то есть не нашел эту дефолтную имплементацию. +500.34 505.82 "Анатолий Кулаков" В общем, ради обратной совместимости пришлось ввести такое не очень интуитивное поведение. +505.82 506.82 "Анатолий Кулаков" Дальше. +506.82 508.62 "Анатолий Кулаков" На этом подводные камни не кончаются. +508.62 513.70 "Анатолий Кулаков" Прежде всего, иерархия виртуальных вызовов, т.е. +513.70 527.74 "Анатолий Кулаков" как, наверное, вызываются виртуальные методы с абстрактными классами, все мы знаем, т.е. их можно переопределить, с ними можно и пронаследовать, не переопределять, воспользоваться дефолтным поведением из абстрактного класса и так далее. +527.74 539.34 "Анатолий Кулаков" Когда мы пытаемся сделать то же самое и с дефолтными методами, ну, например, есть у нас интерфейс Shape, который возвращает в виде строки свое имя, getName у него возвращает iShape. +539.34 559.78 "Анатолий Кулаков" Если мы от этого интерфейса, да, и getName это метод, который заимплементирован по дефолту в этом интерфейсе, дальше мы делаем от наследника, который называется Rectangle, и Rectangle наследуется от iShape, при этом не переопределяя метод getName, ну, т.е. по сути должен использовать базовый метод. +559.78 569.46 "Анатолий Кулаков" И дальше мы от Rectangle наследуем квадратик, квадратик тоже переопределяет getName и говорит, что мой name это квадратик. +569.46 572.42 "Анатолий Кулаков" Тут как бы тоже все вроде пока прямо и очевидно. +572.42 580.26 "Анатолий Кулаков" А теперь, внимание, вопрос, что будет, если мы создадим квадратик, приведем его к интерфейсу iShape и дернем у него метод getName? +580.26 594.06 "Анатолий Кулаков" Ну, кажется, что если бы мы делали это все с абстрактными классами, то, естественно, даже несмотря на то, что мы у iShape переменной дернули getName, то override ее в квадратике должен был вернуть нам слово квадратик. +594.06 599.82 "Анатолий Кулаков" Но нет, так не произойдет, нам вернется именно iShape. +599.82 606.66 "Анатолий Кулаков" Это поведение неинтуитивное, и оно абсолютно сбивает с толку тех, кто привык к абстрактным классам и привык от них наследоваться. +606.66 633.14 "Анатолий Кулаков" Для того, чтобы пофиксить это поведение, вам необходимо в наследнике квадратика пронаследоваться не только от Rectangle, но и явно пронаследоваться от интерфейса iShape, несмотря на то, что Rectangle и так наследуется от интерфейса iShape, т.е. здесь вам нужно явное наследование сделать, и только после этого квадратик подхватит override из базового интерфейса. +633.14 634.14 "Анатолий Кулаков" Следующая проблема. +634.14 637.98 "Анатолий Кулаков" Насколько вы знаете, в C# не существует множественного наследования. +637.98 641.38 "Анатолий Кулаков" Кстати, в C, там C++, оно есть. +641.38 648.26 "Анатолий Кулаков" И самая главная причина, на которую все ссылались при дизайне языка, почему так не было сделано, это Diamond Inheritance Problem. +648.26 651.38 "Анатолий Кулаков" Игорь, ты знаешь, как на русский переводится эта +651.38 654.30 "Игорь Лабутин" проблема? +654.30 659.50 "Игорь Лабутин" Ромбовидное наследование, обычно я что-то из своих древних плюсовых времён помню какой-то такой термин. +659.50 666.14 "Анатолий Кулаков" Ну да-да, мне тоже кажется, что-то с равновидным, не какое-нибудь там бриллиантовое или… +666.14 668.42 "Игорь Лабутин" Нет-нет, ну ромбовидное, да. +668.42 670.66 "Игорь Лабутин" Ну что-то там с ромбами было связано. +670.66 673.74 "Игорь Лабутин" Ну и оно рисуется в виде ромба обычно, поэтому вот. +673.74 674.74 "Анатолий Кулаков" Да. +674.74 686.10 "Анатолий Кулаков" А рисуется в виде ромба неспроста, потому что эта проблема, она очень похожа на ромб, если представить наследование в виде такой своеобразной диаграммы. +686.10 693.02 "Анатолий Кулаков" Допустим, у вас есть класс IShape, у IShape наследуется первый наследник и наследуется второй наследник. +693.02 694.90 "Анатолий Кулаков" А потом мы захотели сделать класс. +694.90 702.46 "Анатолий Кулаков" И этот класс мы хотим, чтобы он имплементировал два интерфейса, интерфейс наследник 1 и интерфейс наследник 2. +702.46 709.90 "Анатолий Кулаков" И у IShape есть метод getName, и у первого наследника есть getName, и у второго наследника есть getName. +709.90 716.42 "Анатолий Кулаков" И все эти getNames, они переопределены во всех этих трёх интерфейсах, так как мы теперь можем это делать. +716.42 717.42 "Анатолий Кулаков" Вот. +717.42 718.42 "Анатолий Кулаков" И теперь, внимание, вопрос. +718.42 733.06 "Анатолий Кулаков" Вот наш класс, последний, четвёртый, который хочет пронаследоваться и от второго, и от третьего наследника, какой у него метод getName вызовется, т.е. что вернёт, от какого наследника. +733.06 736.46 "Анатолий Кулаков" Это, в принципе, в общем случае неразрешимая проблема. +736.46 740.94 "Анатолий Кулаков" И именно поэтому и не стали делать множественное наследование в C#. +740.94 755.02 "Анатолий Кулаков" Ну, как только у нас появляется дефолтная реализация интерфейси на методах, а методов, а интерфейсов, т.е. мы можем пронаследовать сколько угодно в нашем классе, у нас вот эта ромбовинная проблема наследования, она встаёт в полный рост снова. +755.02 760.34 "Анатолий Кулаков" И здесь Микрософт пошёл самым правильным, наверное, путём. +760.34 762.94 "Анатолий Кулаков" Он на уровне компиляции запрещает такое компилировать. +762.94 767.74 "Анатолий Кулаков" Т.е. он говорит, что компилятор не может найти самый лучший метод, который вам подходит, идите и явно его укажите. +767.74 770.82 "Анатолий Кулаков" В общем, и указать явно это, естественно, можно. +770.82 781.26 "Анатолий Кулаков" Таким образом мы избавляемся от всяких проблем и в рантайме не ловим каких-то непонятных исключений или даже непонятного поведения, я бы сказал, которое вполне вас могло преследовать всю плюс-плюсе. +781.26 783.34 "Анатолий Кулаков" Так, погнали дальше. +783.34 793.34 "Анатолий Кулаков" Следующая проблема, с которой, возможно, столкнётесь, если вы захотите пронаследовать структуру от вашего интерфейса, в котором есть дефолт имплементации. +793.34 799.82 "Анатолий Кулаков" Естественно, структуры тоже могут наследовать интерфейсы, но здесь есть парочка небольших проблем. +799.82 808.78 "Анатолий Кулаков" Прежде всего, для того, чтобы использовать дефолтный метод из дефолтного этого интерфейса, вам необходимо будет структуру прикастить к интерфейсу. +808.78 818.50 "Анатолий Кулаков" Как мы уже обсуждали чуть ранее, что только интерфейс может вызывать методы, которые явно задекларированы в интерфейсе, но их нет в самом наследнике. +818.50 822.98 "Анатолий Кулаков" И как только вы кастите структуру к интерфейсу, у вас неизбежно появляется боксинг. +822.98 830.30 "Анатолий Кулаков" А боксинг у вас появляется не просто так, а вместе с избыточным потреблением памяти, то есть вызывается memory location. +830.30 838.54 "Анатолий Кулаков" И обычно, то есть в обычных программах, наверное, вам memory location может не так страшен, но здесь мы используем структуру. +838.54 841.26 "Анатолий Кулаков" И обычно структуру используют как раз там, где памяти выделять не надо. +841.26 844.70 "Анатолий Кулаков" И это высокопроизводительный и обычный оптимальный код. +844.70 846.90 "Анатолий Кулаков" Как раз где не хочется в ХИПе выделять память. +846.90 853.98 "Анатолий Кулаков" И как только вы начинаете кастить вашу структуру к интерфейсу, вы автоматически все плюсы структуры как бы теряете. +853.98 857.30 "Анатолий Кулаков" Поэтому, скорее всего, именно в этом месте вы этого не хотите. +857.30 870.50 "Анатолий Кулаков" И также нужно сказать, что дефолтные методы в интерфейсе, когда пытаются изменить структуру, они получают ее, естественно, через интерфейс. +870.50 874.54 "Анатолий Кулаков" То есть они по случаю получают забокшенную копию самой структуры. +874.54 878.02 "Анатолий Кулаков" Таким образом, чтобы они там не меняли, до оригинала они никак не дотянутся. +878.02 884.50 "Анатолий Кулаков" То есть, по сути, невозможно из дефолт имплементейшн метода обновить каким-то образом структуру. +884.50 888.38 "Анатолий Кулаков" Из этих двух минусов можно сделать только один единственный правильный вывод. +888.38 896.30 "Анатолий Кулаков" Не используйте структуры и дефолт интерфейс методы вместе, потому что вы явно этого не хотите. +896.30 904.98 "Анатолий Кулаков" Еще один неочевидный подводный камень в том, что дефолтные методы требуют изменения в рантайме. +904.98 911.06 "Анатолий Кулаков" Казалось бы, по идее, наверное, это изменение можно засунуть было в компилятор и все, и дело в шляпе. +911.06 912.06 "Анатолий Кулаков" Но нет. +912.06 913.74 "Анатолий Кулаков" Обновления компилятора вам недостаточно. +913.74 915.58 "Анатолий Кулаков" Нужно еще будет обновиться рантайм. +915.58 923.54 "Анатолий Кулаков" Они есть в рантайме после .NET третьего, поэтому можно смело на этот рантайм переходить, если вам они вдруг зачем-то нужны. +923.54 939.14 "Анатолий Кулаков" В качестве хорошего примера для оптимизации Андрю Лок приводит хорошую оптимизацию от Бена Адамса, который умудрился увеличить перформанс iHeaderDictionary в три раза. +939.14 942.42 "Анатолий Кулаков" В общем, сделал он это довольно нехитрым путем. +942.42 950.58 "Анатолий Кулаков" Раньше к iHeaderDictionary, т.е. это специальный словарик, в который мы ходили за заголовками, аж теперь и квесты, аж теперь и спонсоры. +950.58 951.58 "Анатолий Кулаков" Мы оттуда могли доставать заголовки. +951.58 956.02 "Анатолий Кулаков" Как вы понимаете, заголовков бесконечное множество, там может быть абсолютно любой строковой ключ. +956.02 959.38 "Анатолий Кулаков" В общем, мы раньше их доставали просто из дикшнери лукапом. +959.38 963.46 "Анатолий Кулаков" Ну, не просто лукапом, там умным лукапом с мегаоптимизацией и так далее. +963.46 980.42 "Анатолий Кулаков" Но все эти мегаоптимизации оказались довольно слабыми по сравнению с тем, что мы могли бы в этом iHeaderDictionary просто завести свойства для самых популярных хедров таких, там, accept, content-type, encoding и так далее, и просто обращаться к этим свойствам. +980.42 995.82 "Анатолий Кулаков" Вот именно это Эндрю сделал, т.е. Бен Адамс сделал, сделал это с помощью дефолтных методов, т.е. теперь он на этом интерфейсе смог реализовать свойства, которые напрямую ходят к тому полю, который вы захотели, без всякого лукапа в дикшнере. +995.82 997.98 "Анатолий Кулаков" И все это в три раза ускорило дикшнер. +997.98 1010.22 "Анатолий Кулаков" Вот в принципе один из примеров, как Microsoft использует эти методы не только для расширения интерфейсов, а ради каких-то непонятных методов, ну и ради прям увеличения перформанса. +1010.22 1018.10 "Анатолий Кулаков" Несмотря на то, что API там стал красивше и использовать этот дикшнер стал легче, но главная цель Бена, конечно же, была перформанс. +1018.10 1034.46 "Анатолий Кулаков" Вот такие наши старые новые друзья, может, эта статья открыла для вас какие-то новые вещи, о которых вы раньше не знали и, может быть, как раз показала, почему и не следует в последненной жизни использовать дефолт интерфейс имплементейшнсы. +1034.46 1040.34 "Игорь Лабутин" Да, звучит интересно, потому что, ну кажется, относительно простая фича всего лишь. +1040.34 1045.38 "Игорь Лабутин" Казалось бы, добавили методы в интерфейсе, а столько проблем. +1045.38 1049.14 "Игорь Лабутин" Что может быть, кстати, подчеркивает, почему сложно дизайнить все эти языковые фичи. +1049.14 1054.06 "Игорь Лабутин" Казалось бы, придумали простую штуку, а вот надо со всем совместить. +1054.06 1063.34 "Анатолий Кулаков" Наверное, главное теперь, что нужно придумать в языке или во всех новых языках, которые люди придумывают, самое главное, что нужно придумывать, это как вы будете избавляться от легоси-конструкции. +1063.34 1070.02 "Анатолий Кулаков" Потому что сейчас это бич C#, и он нам мешает такие хорошие фичи вводить полноценно, красиво, ожидаемо. +1070.02 1074.94 "Анатолий Кулаков" Вот всё это из-за обратной дурацкой совместимости, которая, в принципе-то, по большому счёту никому и не нужна. +1074.94 1077.66 "Анатолий Кулаков" Ну в таком виде, в котором мы могли бы ей пренебречь. +1077.66 1086.86 "Игорь Лабутин" Ну именно, мы вообще рассказывали, кстати, на эту тему немножко, что команда C# придумала, что они с этим будут делать. +1086.86 1105.14 "Игорь Лабутин" Напоминаю, что в новом SDK, по-моему, начиная с девятки, если вы скомпилите ваш старый код в девятом SDK с таргетом в восьмёрку, он теоретически сможет вас предупредить, что смотрите, вот эти вот фичи, которые в вашем коде, если вы поменяете таргет на девятку, они изменят поведение. +1105.14 1115.38 "Игорь Лабутин" То есть, и за счёт этого они теперь могут делать breaking changes, то есть они меняют их, но поменяют так, что если вы компилите со старым таргетом, то поведение старое, например. +1115.38 1127.22 "Игорь Лабутин" Какое-нибудь там новое ключевое слово будет считаться просто обычной переменной, идентификатором, а вот если с таргетом девятка, то всё, это уже новое поведение, новое ключевое слово и вот это всё. +1127.22 1139.10 "Игорь Лабутин" Это таки позволит, наконец-таки, не знаю, вводить ключевые слова, не боясь того, что кто-то объявил класс с именем рекорд, с маленькой буквы, в таком духе. +1139.10 1141.38 "Игорь Лабутин" Так что, надеюсь, станет лучше. +1141.38 1144.58 "Анатолий Кулаков" Да-да, это именно то решение, которое я имел в виду. +1144.58 1147.30 "Анатолий Кулаков" Посмотрим, как оно себя покажет, но кажется, это то, что нам надо. +1147.30 1148.30 "Игорь Лабутин" Да. +1148.30 1149.30 "Игорь Лабутин" Пойдём дальше. +1149.30 1151.82 "Игорь Лабутин" Дальше у нас очередной новости про Aspire. +1151.82 1159.26 "Игорь Лабутин" На их, не то чтобы вышло статья, но на их гитхабе появилось ишьё, которое называется first release scoping. +1159.26 1164.22 "Анатолий Кулаков" То есть понятно, что… Это для тех, кому не хватило до прошлого выпуска, посвящённое полностью Aspire. +1164.22 1178.42 "Игорь Лабутин" Да, я боюсь, что… ладно, боюсь неправильный термин, но я думаю, что у нас Aspire будет так или иначе в каждом выпуске появляться, потому что, похоже, это одна из самых больших фичей или компонент, не знаю, направлений того, куда сейчас работает команда ASP. +1178.42 1182.30 "Игорь Лабутин" Ну, наверное, фреймворк, да, то есть это что-то рядом с AspNet. +1182.30 1192.26 "Игорь Лабутин" Это AspNet, да, главной движухой и промоутом этого всего занимается Дэвид Фаулер, который, собственно, до этого промоутил minimal API, а теперь вот занимается Aspire. +1192.26 1197.86 "Игорь Лабутин" Вот, итак, что, собственно, должно войти в первый релиз? +1197.86 1204.10 "Игорь Лабутин" Напоминаю, что сейчас Aspire это всё-таки превью, там раннее первое, второе, ну, короче, пока это всё очень превью. +1204.10 1213.98 "Игорь Лабутин" Всё может 20 раз меняться, и оно уже меняется, но когда будет релиз, значит, scope, который сейчас себе команда очертила, он следующий. +1213.98 1234.94 "Игорь Лабутин" Напоминаю, что Aspire это такой способ запихать в ваше приложение стандартные, так скажем, хорошо проверенные временем конфигурации для широко известных компонент и добавить к этому возможность, соответственно, сервис дискавери, правильной телеметрии и вот этого всего. +1234.94 1243.22 "Игорь Лабутин" И поэтому, когда мы говорим про скопинг, во-первых, в первую очередь, конечно же, речь идёт о компонентах, ну и ресурсах. +1243.22 1260.34 "Игорь Лабутин" И здесь Microsoft говорит следующее, что из open-source, они будут ну, open-source на это громко сказано, потому что там есть SQL-сервер, но у них это называется OSS раздел, и там написано, что там будет поддержана Postgres, MySQL, SQL-сервер, Oracle, Mongo, Redis, Kafka и RabbitMQ. +1260.34 1274.46 "Игорь Лабутин" Ну, то есть, наверное, не знаю, 90% наверное не скажу, но очень существенная часть всего стандартного такого базданческого, ну, базданных, эстеков и кэшей, да? +1274.46 1278.94 "Игорь Лабутин" Точно есть ещё какие-то, вернее, точно есть ещё какие-то, но это, наверное, покроет большой процент. +1278.94 1284.46 "Анатолий Кулаков" Да, да, хороший список, прям нормальный стандартный стек-энтерпрайзер, и не только. +1284.46 1285.46 "Игорь Лабутин" Да. +1285.46 1295.94 "Игорь Лабутин" Дальше, естественно, не могли обойти вниманием Ажуру, там будет, ну, мы уже говорили про Cosmos, Storage, всякие разные, сервис-баски, Vault, OpenAI, AI-сёрч, куда же без AI? +1295.94 1299.46 "Игорь Лабутин" Azure Redis, Azure Postgres, Azure SQL, тут всё нормально. +1299.46 1309.70 "Игорь Лабутин" И Dapr мы упоминали в последнем выпуске, что они сделали заделочки под Dapr, соответственно, вот стоит Store и Pub/Sub из Dapr тоже нативно будут, ну, нативно, в смысле, в скоупе релиза будут поддержаны. +1309.70 1323.06 "Игорь Лабутин" Для дэшборда запланирован очень важный и нужный шаг, называется декаплинг, то есть так, чтобы дэшборд можно было запускать абсолютно отдельно от вашего приложения. +1323.06 1345.58 "Игорь Лабутин" Сейчас напоминаю, что вы должны, для того, чтобы вставить Aspire в ваш продукт, нужно создать отдельный проект, из него зареференсить или каким-то образом заиспользовать там через пути компоненты, еще через что-нибудь ваши основные остальные проекты, приложения, и после этого, именно из этого продукта, этот проект вы делаете стартом и из него запускается дэшборд. +1345.58 1359.62 "Игорь Лабутин" Так вот, теперь есть уже pull-request, он вмёржен, то есть последняя ветка мастера или мейна, что у них там в этом самом репозитории, уже содержит отрезанный дэшборд, который как-то можно запускать отдельно. +1359.62 1384.26 "Игорь Лабутин" Пока еще нет толковой документации, я пока не видел, может быть, уже появилось там, с момента, как я смотрел, недельку назад, но теперь дэшборд в каком-то смысле отцеплен от основного приложения, с которым он работает, и может быть это означает, что мы сможем вскоре увидеть абсолютно standalone дэшборд, который не требует каких-то, ну какой-то магии для своей работы. +1384.26 1388.78 "Игорь Лабутин" Посмотрим, что они подразумевают под декаплингом, пока просто написано. +1388.78 1389.78 "Игорь Лабутин" Дэшборд декаплинг. +1389.78 1394.74 "Анатолий Кулаков" А ты не знаешь, он будет запускаться как бы в отдельном процессе, или все равно процесс должен быть этот же? +1394.74 1396.18 "Анатолий Кулаков" То есть как он будет слушать, по сути, все эти метрики? +1396.18 1424.30 "Игорь Лабутин" Нет, процесс он и был отдельный в любом случае, он по-любому отдельный процесс, он слушает, потому что у него LP-сервер, ну оплентелеметрии и кто там еще, вот, он в любом случае слушает, просто другое дело, что если ты помнишь прошлый выпуск, то мы обсуждали, что там есть еще так называемый DCP, Data Control Plane, или нет, странное название, ну короче, Control Plane, какой-то отдельный процесс, который как раз всем управляет. +1424.30 1434.86 "Игорь Лабутин" Вот, и дэшборд – это просто отдельный процесс, из которого торчит, собственно, бэкэнд для вот этого фронт-энд-приложения, которое в браузере. +1434.86 1438.70 "Игорь Лабутин" Поэтому это будет отдельный процесс, однозначно. +1438.70 1459.70 "Игорь Лабутин" Проблема в том, как научить остальные процессы в системе, ну или в вашем продукте репортить в этот процесс, то есть будут ли какие-то там well-known-урлы, будут ли какие-то, ну короче, непонятно, поскольку он, если он отрезан от основного приложения и не используется для запуска основного приложения, то каким-то образом конфигурацию нужно будет прокинуть. +1459.70 1468.90 "Анатолий Кулаков" Ну, наверное, такой же, как и во всех остальных LTP-сервисах, ты должен подключить внешний телеметрий-провайдер и писать туда, или какой-то агент должен собирать от тебя информацию. +1468.90 1485.38 "Игорь Лабутин" Я очень надеюсь, что это ровно так, потому что тогда это позволяет использовать его вообще для чего угодно, даже для того, чего Майкрософт не предполагал, ну грубо говоря, для каких-то приложений, там, не знаю, на Java, на Python, на Rust, на Go, да, которые ты просто так из студии не запустишь. +1485.38 1490.86 "Анатолий Кулаков" Ну, я думаю, что они не зря на LTP-сервис рассчитывали на этот протокол. +1490.86 1496.14 "Анатолий Кулаков" То есть они, скорее всего, предполагают, что его можно использовать как standalone-приложение с абсолютно любыми другими приложениями. +1496.14 1501.46 "Анатолий Кулаков" То есть мы ждём конкурента Эластику, или чего-то у нас ещё есть? +1501.46 1502.46 "Анатолий Кулаков" Ну, Эластику, Графани, там, не знаю. +1502.46 1503.46 "Анатолий Кулаков" Графани, да-да-да. +1503.46 1504.46 "Игорь Лабутин" Чему-нибудь такому. +1504.46 1514.62 "Игорь Лабутин" Слушай, посмотрим, в том плане, что я думаю, что сейчас должны появиться статьи на предмет как бы, как это мы всё сделали, чтобы оно вместе заработало. +1514.62 1526.90 "Игорь Лабутин" В смысле, что такое standalone и так далее, потому что пока просто всё очень рано, в смысле, что, ну, только-только вот pull-request недавно вмёрзли, и поэтому пока рано говорить, что всё из этого получится. +1526.90 1527.90 "Игорь Лабутин" Посмотрим. 1527.90 1528.90 UNKNOWN Вот. -1528.90 1541.18 SPEAKER_01 Дальше, deployment раздел, это, соответственно, все вот эти ресурсы, которые я перечислил, да, там, пасгрегий, ажур и так далее, должны быть в состоянии задеплоины куда-либо. -1541.18 1545.02 SPEAKER_01 Ну, понятное дело, что в ажур, это однозначно. -1545.02 1564.58 SPEAKER_01 Дальше у них написано, что должен быть CI/CD scaffolding, ну, короче, command-line tool, который позволит тебе из, ну, как бы, из твоего аспайровского описания, да, которое пишется на C#, я напомню, сгенерить GitHub action, который тебе потом это всё будет собирать уже в CI где-то там. -1564.58 1580.10 SPEAKER_01 Ну и поддержка Kubernetes, есть отдельный комьюнити-проект Aspirate называется, он, соответственно, как раз умеет преобразовывать эти аспайровские манифесты из кода в нормальные, так сказать, скрипты для кубера, чтобы туда задеплоить. -1580.10 1601.42 SPEAKER_01 Tooling, ну, Visual Studio, понятное дело, Visual Studio Code обещают, и обещают тот самый scaffolding не только в виде command-line, но и в виде какой-то Visual Studio приблуды, я уж не знаю, плагин или нативная функциональность, тут уж я не знаю, ну, короче, какой-то tooling вокруг Visual Studio, Visual Studio кода. -1601.42 1613.14 SPEAKER_01 Есть ещё такой интересный раздел, называется top requests at end-to-end scenarios, то есть это, я так понимаю, те сценарии, где либо больше всего народу проголосовало, либо какие-то заказчики к ним пришли и сказали, что вот это точно надо. -1613.14 1633.58 SPEAKER_01 Они все в основном, конечно, крутятся вокруг ажура, то есть там я хочу коннектироваться к ремоутному ажурному ресурсу из своего девелоперского окружения, я хочу брать секреты, которые проставлены в моих ажурных ресурсах и прокидывать их локальным приложением, там через User Secrets или как-то. -1633.58 1649.14 SPEAKER_01 Но есть и те, которые не относятся к ажуру, например, давайте поддержите докер в VSL, чтобы можно было видимо туда там деплойт, не знаю, не деплойт, типа, в, тоже локально, но такой типа, а-ля, локальный кубер. -1649.14 1667.90 SPEAKER_01 Хочется уметь возможность оркестрировать, ну вот это как раз история с декаплингом, несколькими репозиториями, то есть сейчас Spyre предполагает, что у тебя монорепа, грубо говоря, в которой, ну плюс-минус, да, дефолтный сценарий, в который ты референсируешься на другие проекты, то есть не только монорепа, но еще и сингл солюшен, по большому счету. -1667.90 1677.02 SPEAKER_01 Ну, это понятно, что первый превью, и это самое простое, что можно было сделать, но вот end-to-end сценарий, так что можно было вообще с несколькими репозиториями работать, тоже нормально. -1677.02 1686.10 SPEAKER_01 Из того, что явно написано, что out-of-scope, точно не будет поддержан никакой там AWS, Google Cloud, не будет поддержан Azure Kubernetes. -1686.10 1691.18 SPEAKER_00 Слушай, а почему это out-of-scope, если ажура поддерживается, ну то есть кажется одного полиягоди? -1691.18 1702.50 SPEAKER_01 Там чуть-чуть разные, так скажем, видимо какие-то, ну не знаю, в мелочах требования, не знаю, вот, поэтому, ну вот пока не поддержан, out-of-scope, просто видимо ресурсов не хватит. -1702.50 1708.74 SPEAKER_00 Ну хорошо, ну так мы написали, что ресурсов не хватит, типа делайте сами, но мне кажется, что это out-of-scope. -1708.74 1709.74 SPEAKER_01 Нет, стоп. -1709.74 1729.94 SPEAKER_01 Ну так они это и написали, out-of-scope, это в смысле наша команда этим не будет заниматься, то есть это scope команды, которые они планируют, что Microsoft планирует официально зарелизить в первом релизе, но out-of-scope Microsoft не планирует, как бы запрещать, никто не запрещает, пожалуйста, делайте что хотите, но как бы Microsoft это делать не планирует, -1729.94 1735.66 SPEAKER_00 и это не только… Я думал, что это out-of-scope именно самого проекта, то есть проект под это не предназначен. -1735.66 1767.50 SPEAKER_01 Это first-release scope, напоминаю, все, что мы обсуждаем, это scope первого релиза, будет он как бы вместе с девяткой в ноябре, будет он раньше, будет он отдельно, как версионируется этот продукт пока тоже не очень понятно, ну вроде бы логично его привязать, наверное, к релизам дотнета, но с другой стороны, если они планируют это делать как отдельный стендаловый продукт под другие платформы тоже, то зачем привязывать, может быть они там летом его зарелизят, я не знаю, но вот это как раз таки все то, что я перечислял, это то, что должно войти в первый релиз. -1767.50 1808.60 SPEAKER_01 Так вот, то, что ты говоришь, если поддерживать ажуру, в первый релиз out-of-scope не только ажура, ой, в смысле AWS там, Google Cloud, но еще и Azure Kubernetes и Azure Functions, это все тоже не будет поддержано, то есть даже если у тебя есть проект, напоминаю, в студии ты можешь создать проект Azure Functions и довольно легко там в пару кликов его деплоить в ажуру, Aspire такого поддерживать пока не будет, ну, видимо, не успевают, вот, ну либо просто сознательно ограничивать на самом деле, может быть это тоже правильно, сознательно ограничить себе scope первой версии, сделать его, ее, его scope версию и зарелизить, посмотреть на фидбэк и дальше выбирать следующее, наиболее важное. -1808.60 1834.48 SPEAKER_01 Ну, в общем, примерно так, соответственно, в ссылочках будет и ссылка на pull request, где отрезали дэшборд и он теперь standalone, можно посмотреть, может быть там уже что-то появилось где-нибудь или в связанных ишах написана какая-нибудь документация, или, можно сказать, в pull request она прямо есть, я не посмотрел, вот как этим пользоваться, так что если у кого-то руки дойдут, попользуйтесь, расскажите, как он там standalone работает, у меня пока не дошли, честно говоря. -1834.48 1838.72 SPEAKER_00 Угу, ну и мы будем следить за статейчиками, если появятся, обязательно расскажем. -1838.72 1841.64 SPEAKER_01 Ну, конечно, проще прочитать, чем самому сделать, так -1841.64 1842.64 SPEAKER_00 что. -1842.64 1843.64 SPEAKER_00 Это да. -1843.64 1850.76 SPEAKER_00 Кстати, вот проще как раз было дождаться, пока кто-то найдет замещение байна реформатору, чем сделать его самому. -1850.76 1863.84 SPEAKER_00 Давай, следующая статейчика как раз про то, что один дяденька загнался тем, что начал скучать по байна реформатору, ну, у него в проекте он просто использовался, а он захотел перебежать на последний фреймворк и сильно загрустил. -1863.84 1893.38 SPEAKER_00 Давай для, как раз для молодежи вспомним, что в старинных версиях дотнет фреймворка много-много тысяч лет назад была такая прекрасная штука, как байна реформатор, и отличалась она от вот этих ваших новомодных JSON-сериалайзеров тем, что паковала, не поверите, в байнаре, то есть по сути в нечитабельную кашу из битиков и байтиков, которую естественно неудобно было дебажить и смотреть на нее глазками. -1893.38 1897.04 SPEAKER_00 Но у байна реформаторов есть другой прекрасный плюс. -1897.04 1901.00 SPEAKER_00 Они намного быстрее всегда и намного компактнее. -1901.00 1909.48 SPEAKER_00 И обычно, когда мы говорим о сериализации, это два очень весомых плюсика, которые в принципе вполне могут перебить любой текстовый сериализатор. -1909.48 1914.76 SPEAKER_00 Так вот, был у Микрософта байна реформатор рядом с XML-форматором вообще самых первых его версий. -1914.76 1918.48 SPEAKER_00 Потому что JSON-а не было, а байнаре XML был всегда. -1918.48 1928.04 SPEAKER_00 И сериализовали, сериализовали люди с помощью него и постепенно поняли, что в принципе реализация этого байна реформатора была слишком мощная. -1928.04 1935.32 SPEAKER_00 Она могла делать такие страшные вещи, что даже которые выходили за уровень ее декларируемых фич. -1935.32 1962.76 SPEAKER_00 То есть, допустим, с помощью байна реформатора, если у вас вдруг торчит какой-нибудь endpoint, VCF-endpoint или HTTP-endpoint, не суть важно, или сигнал-эр-эндпоинт, который принимает внутрь себя некий пакет, который десяти реализуется с помощью байна реформатора, то очень часто вы можете благодаря такому endpoint выполнить произвольный код на удаленном сервере. -1962.76 1966.80 SPEAKER_00 То есть, с байна реформатором очень много было о секьюрити проблем. -1966.80 1987.24 SPEAKER_00 Кому интересно, можно отдельную статейку почитать, но смысл как раз в том, что от него начали отказываться, наверное, не в основном по этой причине, это была причина главная, но как бы, понимаете, обычно программистам на секьюрити плевать, поэтому программисты начали от него отказываться, потому что он был не очень удобный, у него было много багов, он был очень медленным и прочие такие рюшечки. -1987.24 2004.40 SPEAKER_00 Но на самом деле, самая главная была причина для того, чтобы от него начать отказываться, и чтобы Микрософт его специально больше не развивал, специально не латал никакие-нибудь проблемы, это как раз в том, что сама концепция была очень сильно подвержена различным секьюрити атакам. -2004.40 2018.80 SPEAKER_00 И начиная с DotNet 7, этот байна реформатор был помечен как абсолют, при том на уровне ERROR, т.е. вы не могли скомпилить ваш проект, если вдруг почему-то использовали его до сих пор. -2018.80 2023.12 SPEAKER_00 Вот и автор наткнулся на этот ERROR и решил посмотреть, а что же такого есть на рынке. -2023.12 2028.40 SPEAKER_00 И прошло как бы 10 лет, как он решил отойти от байна реформатора. -2028.40 2036.28 SPEAKER_00 Ну, прежде всего, все микрософтовские статьи советуют переходить почему-то на текстовые форматы в виде JSON, т.е. -2036.28 2056.32 SPEAKER_00 System Text JSON, раньше до этого рекомендовали Newton Soft JSON, но выглядело для всех это довольно странно, потому что никто с драмами твердой памяти после бинарного форматора, если бы, конечно, бинарный форматор был выбран явно, никто не пойдет на JSON, потому что это всегда медленно, много и т.д. -2056.32 2069.64 SPEAKER_00 Дальше пошли смотреть на байна реформатор, также ему приглянулся Protobuf, но Protobuf требует кучу приседаний, кучу настроек, конфигурации, объявления протокола и, в общем, ему это показалось слишком сложно все. -2069.64 2076.92 SPEAKER_00 Поэтому Protobuf он скипнул и дошел до, наверное, самой очевидной вещи, на которую должен был дойти каждый, это MessagePack. -2076.92 2086.64 SPEAKER_00 MessagePack - это прекрасный сериализатор, он байнарий сериализатор, он намного быстрее, чем JSON и он намного компактнее, чем JSON. -2086.64 2101.92 SPEAKER_00 Другая прекрасная новость заключается в том, что этот MessagePack разрабатывается организацией, которая называется SciSharp и человеком, который сложно произносимым ником на GitHub'е не Uytsk, Yoshimi Kawai. -2101.92 2109.64 SPEAKER_00 Короче, чувак довольно со сложным именем, но если вы там увидите его иконку или увидите этого чувака, вы его запомните навсегда. -2109.64 2118.32 SPEAKER_00 По той простой причине, что это очень грамотный человек, который реализовал уже кучу сериализаторов, кучу парсеров. -2118.32 2125.84 SPEAKER_00 У него отличные in-memory embedded базы данных есть, у него есть там какие-то генераторы каких-то оптимизаций. -2125.84 2135.24 SPEAKER_00 В общем, это человек, который очень хорошо соображает в оптимизациях, пишет хороший код, качественный API и поддерживает свой продукт довольно хорошо. -2135.24 2146.68 SPEAKER_00 Поэтому MessagePack является одним таким и сразу дефолтным сериализатором, если вам нужен хороший, надежный, компактный, быстрый binary-series сериализатор. -2146.68 2163.52 SPEAKER_00 Про MessagePack мы уже говорили в нашем подкасте, и эта статья никогда не попала бы к нам в выпуск, если бы автор не пошел немножко дальше и нашел следующий проект вот этого товарища Kawai, который называется MemoryPack. -2163.52 2167.72 SPEAKER_00 И вот про MemoryPack мы еще не разговаривали, поэтому стоит его осветить. -2167.72 2183.52 SPEAKER_01 Но подожди, подожди, на самом деле, когда он только-только появился, про MemoryPack мы говорили, мы про него… была у нас новость, по крайней мере, про то, что вот вышла такая штука, она типа супероптимизированная, все дела, но это было что-то год назад. -2183.52 2187.80 SPEAKER_01 Я не знаю, насколько он с тех пор развивался, поэтому современная статья будет точно полезна. -2187.80 2188.80 SPEAKER_00 Давай, да. -2188.80 2195.60 SPEAKER_00 Да, наверное, когда он появился, может, и говорили, но опять же, в чем его плюсы? -2195.60 2219.12 SPEAKER_00 Плюс его заключается в том, что он использует и сразу писался на .NET 7 и C# 11, это значит, что он заюзал все возможные оптимизации, которые там ввели, а там, напомню, их было очень много, iBuffer Writer, Span, Read-only Sequence, Read-only Span, PipeWriter, PipeReader, короче, вот эти все-все-все, что только можно было. -2219.12 2222.56 SPEAKER_00 Вот он их очень плотненько заюзал, и это там как бы основная его концепция была. -2222.56 2239.56 SPEAKER_00 Это такая библиотека для Zero Encoding Extreme Performance Binary Serializator, т.е. основная его фишка в том, что он не пытается выдумать какой-то формат и в этот формат что-то записать, как делают другие сериализаторы. -2239.56 2253.12 SPEAKER_00 Он просто берет бинарный dump C# элемента, т.е. C# примитива типа, допустим, Int, и берет этот бинарный поток и просто-напросто записывает его в свой output формат. -2253.12 2254.12 SPEAKER_00 Вот как бы и все. -2254.12 2261.70 SPEAKER_00 Сериализация происходит таким же точным образом, просто-напросто массив byte замещается там, где он должен быть, и это позволяет ему как раз-таки достичь высокой скорости. -2261.70 2274.28 SPEAKER_00 Как я уже, наверное, упомянул, что одно из самых больших прелестей этого проекта в том, что он поддерживается товарищем Kawai'em, который написал уже кучу сериализаторов, в частности, кстати. -2274.28 2284.60 SPEAKER_00 ZeroFormator делая его рук, UTF-8 JSON, это был самый быстрый JSON сериализатор на тот момент, и MessagePack тоже поддерживается им. -2284.60 2290.92 SPEAKER_00 И вот весь опыт он собрал, который он делал с сериализаторами, плюс у него там, как я уже говорил, много других крутецких проектов есть. -2290.92 2294.88 SPEAKER_00 Кстати, если вы не видели его репозиторию, обязательно загляните и посмотрите. -2294.88 2298.08 SPEAKER_00 Там много всего интересного можно найти абсолютно на любой вкус. -2298.08 2307.28 SPEAKER_00 И вторая фишка после того, что он юзает самые последние структуры, которые появились для перфоманса, он полностью написан на source-генераторах. -2307.28 2312.76 SPEAKER_00 Это привело к тому, что у него появились дополнительные плюшки, которые дает source-генераторы. -2312.76 2315.80 SPEAKER_00 Мы их много раз обсуждали, но в данном разделе не грех и повториться. -2315.80 2326.28 SPEAKER_00 Это значит, что он очень дружественно настроен к native auto, т.е. к триммингу, к оптимизациям и к прочим вот этими вещам. -2326.28 2343.88 SPEAKER_00 У него отсутствует полностью рефлекшн, т.е. у него имплементация с помощью рефлекшна, т.е. весь API сделан на source-генераторах, и это ему как раз таки позволяет хорошо и триммиться, и хорошо аутиться, и хорошо и быстро запускаться под всякие оптимальные платформы. -2343.88 2373.48 SPEAKER_00 Из фишек еще у него можно диссерилизовать существующий инстанс, полиморфная диссерилизация, у него также есть TypeScript код-генератор, т.е. вы можете диссерилизовать вот этот формат не только в C#, но и в TypeScript, ну не только в дотнете, но и в TypeScript, поддержка Unity, поддерживается очень много, широкий пласт вообще всех типов, т.е. не только какие-то примитивы, но и листы, и dictionary, и mutable коллекции, и много-много всего того, чего не поддерживают обычные нормальные сериализаторы. -2373.48 2398.36 SPEAKER_00 Также есть у него специальный режим терпимости, где он может немножко ослабить свои требования к структуре ваших DTO-шек, он может позволить вам их немножко добавлять поля, переименовывать поля, но при этом диссерилизоваться это будет немножко медленнее, но если вы гарантируете, что ваши DTO-шки не изменились, там скорость вылетает просто в космос. -2398.36 2411.48 SPEAKER_00 Также у него есть поддержка Brotli, это специальный компрессор, т.е. можно вот этот весь бинарный поток, который он наделал, в то же время еще и посжимать, т.е. мало того, что он компактный сам по себе, еще и можно сжать. -2411.48 2415.68 SPEAKER_00 И все эти ухищрения дали, в принципе, немаленькие результаты. -2415.68 2425.28 SPEAKER_00 Прежде всего, если сравнивать с binary-форматором, который я уже упоминал, он мега медленный был, допустим, на бенчмарках он показал 27 попугаев, там 27 нс. -2425.28 2430.84 SPEAKER_00 Newtonsoft у нас было сразу 7 нс и System Tech JSON – 5 нс. -2430.84 2439.20 SPEAKER_00 Немножко возвращает нас к той мысли, которую мы уже упоминали в прошлых подкастах, что в принципе Newtonsoft написан с точки зрения перформанса довольно хорошо. -2439.20 2450.12 SPEAKER_00 Смотрите, у него 7 нс, а System Tech JSON, который Microsoft вкладывает все силы много последних лет, это 5 нс, т.е. не сильно быстрее, если уж на то пошло. -2450.12 2457.40 SPEAKER_00 Ну и наши лидеры – это MessagePack – 2 нс, и MemoryPack добился 1 нс на тех данных, которые там бенчмаркались. -2457.40 2471.20 SPEAKER_00 На каких-то синтезированных обычных примерах с кучей массивов, с какими-то огромными объектами, автор заявляет, что MemoryPack в 200 раз может быть быстрее любого из существующих сервизаторов. -2471.20 2474.52 SPEAKER_00 В общем, такой вот интересный наборчик. -2474.52 2482.68 SPEAKER_00 Из минуса, наверное, MemoryPack'а можно отметить то, что он будет работать между .NET-приложениями и TypeScript-овым приложением. -2482.68 2493.28 SPEAKER_00 Да, если вам нужна все-таки кросс-языковая какая-то сериализация между Python, Perl, JavaScript, Yava и т.д., то ваш выбор тогда MessagePack. -2493.28 2499.00 SPEAKER_00 Это такой же бинарный сериализатор, но поддерживается практически во всех существующих языках программирования. -2499.00 2505.88 SPEAKER_00 В общем, если вам нужна максимальная перформанс и максимальная утилизация памяти, то взгляните на MemoryPack. -2505.88 2523.44 SPEAKER_01 Ну и надо понимать, что вся эта магия перформанса нужна вам, скорее всего, именно с учетом всех тех проблем и ограничений, которые доставит MemoryPack, она нужна, конечно, только если у вас прям совсем-совсем все жестко по ресурсам. -2523.44 2532.80 SPEAKER_01 И именно поэтому, на самом деле, вот этот автор и пишет всякие такие быстрые сериализаторы туда, быстрые сериализаторы сюда, потому что они занимаются, на самом деле, разработкой игр. -2532.80 2548.56 SPEAKER_01 И в играх понятно, что чем меньше вы потратили ресурсов на один там, на отрисовку одного фрейма или на обсчет одного там типа цикла игры, тем лучше, тем плавнее все будет, тем эффективнее и так далее, тем больше можно считать. -2548.56 2551.72 SPEAKER_01 И именно поэтому у него такие довольно ограниченные штуки. -2551.72 2555.48 SPEAKER_01 Ну и почти все его проекты поддерживают Unity, как-то неудивительно. -2555.48 2557.68 SPEAKER_00 Да, что якобы намекает. -2557.68 2558.68 SPEAKER_00 Да, да. -2558.68 2564.92 SPEAKER_01 Не, ну их на самом деле прямо у организатора C# записано, что они типа Unity, game, что-то там. -2564.92 2569.40 SPEAKER_01 Так что это прям, очень прям, прям тем текстом написано. -2569.40 2574.80 SPEAKER_00 Ну то есть, если на ваших формочках вам нужно клик от кнопочки отработать, то это, естественно, подход не для вас. -2574.80 2576.36 SPEAKER_00 Джессона вам хватит за головой. -2576.36 2584.00 SPEAKER_00 А вот если вам нужно там утилизировать сетку очень сильно, у вас огромные блобы там летают, вот это вот тогда бинарь сериализаторов придет к вам очень быстро. -2584.00 2586.52 SPEAKER_01 Да, начните, наверное, с message пака, мне кажется. -2586.52 2589.84 SPEAKER_01 Если уже будет не хватать, тогда можно идти в memory pack. -2589.84 2595.04 SPEAKER_01 Ну, довольно специфический, так скажем, для очень узких ниш. -2595.04 2596.04 SPEAKER_01 Давай дальше. -2596.04 2604.00 SPEAKER_01 Дальше у нас тема, которую мы на самом деле долго-долго откладывали, потому что она довольно-таки большая. -2604.00 2613.12 SPEAKER_01 Там много чего можно смотреть, можно обсуждать, можно, наверное, несколько подкастов записать только на эту тему, но тем не менее, решил, что все-таки хватит откладывать, надо про это поговорить. -2613.12 2616.84 SPEAKER_01 Тем более, мне этот случай удачный выдался, все равно почитать все эти статейки. -2616.84 2628.44 SPEAKER_01 Речь идет о том, как же дизайнить, версионировать и вообще проектировать, дизайнить, проектировать, ну, в общем, одно и то же REST API. -2628.44 2629.88 SPEAKER_01 Масштабно замахнулся, масштабно. -2629.88 2630.88 SPEAKER_01 Масштабно. -2630.88 2706.32 SPEAKER_01 У нас в ссылочках к этому выпуску вы найдете довольно большое количество материалов на эту тему, есть огромный курс от, ну, не курс, а такой плейлист от Джеффри Рихтера, где он подробно объясняет, как Microsoft и Azure командов в частности подходят к этому вопросу, есть плюс-минус текстовая версия этих гайдлайнов, которая, понятно, я не знаю, насколько Рихтер обновляет свои видео, но гайдлайны видимо свои, они обновляют чуть быстрее, есть огромный, прямо такой монструозный, я бы даже сказал, труд от компании Золанда, у них прямо огромные гайдлайны на их open source портале, ну и есть еще ряд статей от всяких разных более или менее известных товарищей на тему, всяких разных их мыслей о том, как дизайнить правильно REST API, я попробовал это все разнести немножко по, во-первых, я попробовал все это прочитать, прочитал, ну не все, наверное, но большую часть из этого, во-вторых, я выделил для себя какие-то интересные моменты и те, которые, ну, я бы сказал так, наиболее часто возникают споры о них, либо может быть действительно какие-то неочевидные рекомендации, там есть несколько неочевидных рекомендаций, которые я, например, о которых я не задумывался. -2706.32 2710.60 SPEAKER_01 Точнее, я про них слышал, но как-то на автомате делаешь по-другому. -2710.60 2711.60 SPEAKER_01 Вот. -2711.60 2719.60 SPEAKER_01 Ну и вот мы пройдемся по ним, сколько успеем, не знаю, довольно много всего, ну и просто обсудим, кто что на эту тему думает. -2719.60 2723.80 SPEAKER_00 Может, нам стоило каждую секцию поделить на отдельную там статью? -2723.80 2730.60 SPEAKER_01 Ой, нет, слушай, обсуждать кучу выпусков подряд одно и то же мне не нравится, вот мы сейчас быстренько пробежимся. -2730.60 2747.24 SPEAKER_01 Если есть какие-то моменты по дизайну REST, которые остались не освещенными, но вам очень интересно узнать наше мнение, приходите в комменты, пишите в комментах на YouTube, и мы, если там будет очень нужен развернутый ответ, мы включим следующий выпуск, никаких проблем. -2747.24 2748.92 SPEAKER_01 Материалы у нас есть. -2748.92 2755.04 SPEAKER_00 Хорошая идея, если даже есть, присылайте ссылочки, статейки, видео, посмотрим, тоже обсудим. -2755.04 2764.12 SPEAKER_01 Ну да, если есть что-то, вот я проектирую API только вот так, согласно этой статье, никак иначе все остальные не правы, засылайте, мы почитаем, скажем, правы вы или нет. -2764.12 2766.68 SPEAKER_01 В нашем веским мнении, ну ладно. -2766.68 2780.28 SPEAKER_01 Смотри, начнем мы с простого, с принципов, то есть когда мы говорим, а давай мы спроектируем REST API, не секрет, что каждый понимает под этим нечто свое, вот. -2780.28 2850.80 SPEAKER_01 Рандомная статья из интернета, вот буквально мне просто попалось что-то типа несколько дней назад статейка из интернета с неплохим набором, с моей точки зрения, рекомендаций, говорит о том, что ну вообще подавляющее большинство народу считает за REST API, считает просто любой HTTP API, где как бы в урлах не глаголы, а существительные, вот если у тебя там плюс-минус HTTP API, плюс-минус используется там get, post, что-нибудь, и в урле у тебя не там create что-нибудь, а все-таки имена существительные, то есть каких-то ваших доменных объектов, сущностей, то все, это уже как бы REST, там 90% пользователей, которого вы спросите, скажут, да это же конечно же REST, вот, это с одной стороны, с другой стороны есть компания Zalando, которая говорит, нет, вот должен быть REST level какой-то там 2, да, самый крутой, 3 должен быть, короче, ссылки во все поля, значит, любой ответ должен подразумевать, вы можете из него куда-то уйти, в общем, вот это все. -2850.80 2862.68 SPEAKER_00 Ну подожди, тут как бы, мне кажется, это непротиворечивая вещь, если Zalando понимает, что есть REST level 3, а другие люди понимают, что есть level другие, то как бы это все покрывает. -2862.68 2867.32 SPEAKER_01 Ну, если подходить к этому вопросу академически, я с тобой соглашусь. -2867.32 2871.96 SPEAKER_01 На практике, если ты говоришь, о, это REST API, то себе не -2871.96 2872.96 SPEAKER_00 так. -2872.96 2873.96 SPEAKER_00 Технически, конечно, это REST API, почему же нет. -2873.96 2879.36 SPEAKER_01 Да, технически это REST API, но если ты спрашиваешь о какой-то level, он на тебя посмотрит и скажет, что? -2879.36 2881.44 SPEAKER_01 Ну, не все, конечно, но многие. -2881.44 2883.60 SPEAKER_00 Ну, тогда, наверное, стоит осветить, что это за левелы -2883.60 2884.60 SPEAKER_01 такие. -2884.60 2890.44 SPEAKER_01 Ну, можно осветить, да, у нас есть нулевой, вот я сейчас, кстати, не помню, определялся ли в диссертации нулевой level. -2890.44 2891.44 SPEAKER_01 Да, есть. -2891.44 2905.16 SPEAKER_00 Ну, прежде всего, это называется, схема, если вы вдруг захотите найти, это Richardson maturity model, т.е. это модель того, насколько у вас REST-овый, так сказать, и он имеет как раз 4 level, от 0 до 3. -2905.16 2909.44 SPEAKER_01 Ну, как настоящий программист писал, не с первого почитай, а от 0 до 3. -2909.44 2919.08 SPEAKER_00 Ну да, оно здесь подходит просто, потому что ибо 0, это называется вообще болото, это самое примитивное, что можно представить на нулевом уровне в виде REST. -2919.08 2921.76 SPEAKER_00 А я даже не помню, по-моему, нулевое же вообще не определяется. -2921.76 2931.80 SPEAKER_00 Не, нулевое определяется, нулевое – это когда у вас есть один endpoint, у вас есть один метод, и вы все возможные реквесты и респонсы постите в один этот метод. -2931.80 2934.32 SPEAKER_00 Ну, т.е. чтобы вы понимали… Ну, т.е. нет. -2934.32 2938.68 SPEAKER_00 Это модный GRPC, GRPC – это отстойное болото, которое считается самым простым. -2938.68 2941.56 SPEAKER_01 Не, погоди-погоди-погоди, ты путаешь, не GRPC, а GravQL. -2941.56 2947.44 SPEAKER_00 А, GravQL, точно, вот, GravQL – это болото, которое в нормальном ресте даже произносить слух страшно. -2947.44 2950.04 SPEAKER_01 Я тебе более того скажу, там еще и пост всегда. -2950.04 2954.12 SPEAKER_00 Ну вот, один единственный метод, один единственный endpoint, это называется болото. -2954.12 2967.16 SPEAKER_01 Да, значит, потом есть REST-1, когда вы начинаете разносить по урлам разным хотя бы, а потом есть REST-2, там добавляются уже глаголы HTTP, т.е. там GET, PUT, PORT, DELETE. -2967.16 2986.44 SPEAKER_00 Ну и ресурсы тоже уже на REST-2 добавляются, ресурсы, т.е. вы не просто обзываете, как вам в голову придет, т.е. не гуидами у вас теперь урлы называются, а как-то вменяемо, типа что у вас шоп, карты, мы положили товар в корзину и так далее, т.е. пытаетесь как-то натянуть это все. -2986.44 3032.24 SPEAKER_01 Да, а есть еще REST-3, и это, соответственно, уже больше про, это называется еще одним модным словом hypermedia, это когда вы в ответах на все ваши запросы, помимо собственно самой сущности, ну, т.е. например, какой-нибудь GET там, не знаю, тот самый шоп, ну, карт, да, по водичнику, т.е. получить корзину, вы помимо этого сразу в ответе не только содержимое корзины отдаете, но еще и набор мета-информации, т.е. ссылочек, что вы можете с этим сделать, т.е. например, вам очистить корзину или еще что-то сделать, и соответственно, вам не нужно, по сути, идти в документацию, вы можете посмотреть на ответ и знать полный перечень того, что можно сделать из этой ситуации с этим объектом, согласно тому состоянию, в котором этот объект находится. -3032.24 3037.44 SPEAKER_00 Как-то так, вот The Lambda как раз за последний. -3037.44 3039.24 SPEAKER_00 Прямо за третий, да? -3039.24 3043.28 SPEAKER_01 Да, ну, т.е. они сказали, он должен быть truly RESTful, вот это все. -3043.28 3047.12 SPEAKER_00 Тут нужно просто упомянуть, что до последнего доходят не все. -3047.12 3059.32 SPEAKER_00 Ну, т.е. обычно нормальные компании, нормальные люди останавливаются на втором левеле и считают, что если они там глаголы определили, ресурсы определили, и там эти ответы тоже, http-коды заиспользовали, то в принципе этого достаточно. -3059.32 3061.40 SPEAKER_00 Ну, и это, наверное, в 80% случаях правда. -3061.40 3065.72 SPEAKER_00 Ну, т.е. если вы идете дальше, все-таки вам нужна гибкая система. -3065.72 3071.68 SPEAKER_00 Ну, если вспомнить, какие у нас команды вообще дошли публичные до третьего левела, их можно посчитать там по пальцам. -3071.68 3078.28 SPEAKER_00 Я вот, на вскидку, знаю, у GitHub есть третий левел, у Vimeo есть в API третий левел, вот это что сразу в голову -3078.28 3079.28 SPEAKER_01 пришло. -3079.28 3080.28 SPEAKER_01 Ну, вот и, похоже, у Zalando. -3080.28 3086.28 SPEAKER_01 Я не пользовался, т.е. я не могу сказать, насколько они действительно соответствуют, но это же, опять же, гайдлайнс, да? -3086.28 3091.52 SPEAKER_01 Не факт, что их API написан полностью согласно гайдлайнам у всех сервисов у них, я не знаю, десятки, сотни сервисов. -3091.52 3102.04 SPEAKER_00 Не, я видел много этих лекций от Zalando, они очень много клевых практик используют, очень любят про них разговаривать, поэтому на разных конференциях это всегда одни из самых интересных спикеров. -3102.04 3104.60 SPEAKER_00 И, вроде, да, у них на практике все это используется. -3104.60 3113.12 SPEAKER_01 Я, когда мы говорим про REST Level 3, вот с этими самыми ссылочками, которые возвращаются в ответе, я не очень понимаю, зачастую, что с ними делать на клиенте. -3113.12 3122.68 SPEAKER_01 Это очень красиво, что сервер так про себя все рассказал, а вот далеко не всегда понятно, насколько умный должен быть клиент, чтобы с этим точно так же работать. -3122.68 3134.08 SPEAKER_01 Потому что в большинстве случаев все-таки, все-таки, у нас редко строится продукт по принципу, что вот тебе вернули сущность, и мы понятия не имеем, что с ней можно делать. -3134.08 3143.38 SPEAKER_01 В среднем у тебя есть какой-то бизнес-воркфлоу, который тебе нужно сделать, и тебе, в принципе, тебе достаточно понять, можно или нельзя, а не то, что все возможные вещи, которые можно. -3143.38 3147.80 SPEAKER_01 Не знаю, я вот как-то, у меня не было опыта именно с клиентской стороны общения с REST Level 3. -3147.80 3155.76 SPEAKER_00 Ну, именно поэтому, как бы, немногие компании такой запрос делают, потому что у них обычно очень узкий API, и ты там понимаешь, что ты хочешь делать. -3155.76 3163.92 SPEAKER_00 Для примера, чтобы вы понимали, что такое Hypermedia Controls, вот этот REST Level 3, вы можете вспомнить обычный HTML. -3163.92 3169.36 SPEAKER_00 Вот в обычном HTML как раз на 100% реализован Level 3. -3169.36 3172.80 SPEAKER_00 Несмотря на то, что это не API, как бы, но смысл в нем точно такой же. -3172.80 3182.88 SPEAKER_00 То есть, когда браузер загружает вам сайт, он понятия не имеет, какие на этом сайте есть экшены, то есть, какие, например, он должен дернуть URL для того, чтобы залогиниться. -3182.88 3193.32 SPEAKER_00 Но он знает, что есть некая кнопочка, и при нажатии на этой кнопочке нужно пойти на какой-то URL, и он понятия не имеет, что этот URL делает. -3193.32 3195.64 SPEAKER_00 Вот это и есть как раз Hypermedia Controls. -3195.64 3207.80 SPEAKER_00 То есть, когда вы не сообщаете вашему UI, что товарищ UI-щик, когда нажмется кнопочка, дерни вот этот метод создания юзера, потом перейди на другую страничку, там отвалидируй результат и покажи его в окошке. -3207.80 3214.28 SPEAKER_00 Вот когда вы ему это не говорите, а вы говорите, что товарищ UI-щик, вот я дал тебе API, в этом API будет специальный URL. -3214.28 3219.24 SPEAKER_00 В этом URL будет специальная ссылка, которая называется Create User. -3219.24 3225.52 SPEAKER_00 Вот ее надо показать на вот этой кнопочке, и к этой кнопочке привязывать вот это поле, куда пользователь введет там свое имя, допустим. -3225.52 3227.32 SPEAKER_00 И когда он ее нажмет, просто вызови URL. -3227.32 3243.24 SPEAKER_00 Что будет происходить дальше, мы тебе сообщим в ответе, и там тебе разложим экшены, которые можно будет сделать с этим новым юзером, отредактировать его, удалить, установить какой-то новый пароль, в общем, все это пришлется в виде списка экшенов, но не за хардкоженную UI. -3243.24 3244.24 SPEAKER_00 Вот. -3244.24 3245.24 SPEAKER_00 А теперь мы возвращаемся. -3245.24 3247.28 SPEAKER_00 В принципе, представьте браузер себе, вот обычно. -3247.28 3252.24 SPEAKER_00 У браузера как раз не за хардкоженые ни кнопки, ни менюшки, ничего, он все забирает из себя с сервера. -3252.24 3259.16 SPEAKER_01 То, что я говорил, то, что это называется словом гипермедиа, вспоминаем, что HTML, да, это гипертекст, ровно оно. -3259.16 3261.68 SPEAKER_01 А ссылки – это гиперссылки, на самом деле. -3261.68 3287.52 SPEAKER_01 То есть просто в мире современного победившего SPA, да, Single Page Applications, тот факт, что ты послал запрос на сервер про логин, означает, что сервер там что-то свое делает и когда-нибудь вернет ответ, а ты уже там это, перемалываешь какую-то логику на клиенте, который там покажет какую-нибудь анимацию логина там, еще что-нибудь, спросит тебя по пути, пока ты логинишься, еще какую-нибудь фигню про куки, ну, я сейчас фантазирую, но тем не менее. -3287.52 3294.04 SPEAKER_01 То есть у клиента своя сложная логика, и ему как бы тот факт, что ты пришлешь какой-то ответ – это просто дополнительный кирпичик. -3294.04 3295.04 SPEAKER_01 Вот. -3295.04 3300.22 SPEAKER_00 Ну да, можно назвать это богатым клиентом, да, т.е. -3300.22 3303.88 SPEAKER_00 рест и гипермедиа, они больше рассчитаны под тупого бедного клиента, под тонкого клиента. -3303.88 3311.00 SPEAKER_00 В общем, они не исключают, конечно, богатых клиентов, но в целом индустрия реста была спроектирована именно для тонких клиентов. -3311.00 3314.00 SPEAKER_00 Ну тогда да, это какой-то… Практика двинулась немножко в другую сторону. -3314.00 3315.00 SPEAKER_01 Двухтысячный год же. -3315.00 3316.00 SPEAKER_00 По-моему, диссертация. -3316.00 3317.00 SPEAKER_01 Не знаю. -3317.00 3318.00 SPEAKER_01 Диссертация Роя Филдинга. -3318.00 3319.00 SPEAKER_01 Не помню. -3319.00 3325.08 SPEAKER_01 Собственно, Роя Филдинга, который придумал эту штуку, да, по-моему, 2000 или 2001 год, сейчас могу ошибиться. -3325.08 3333.04 SPEAKER_01 И тогда, понятное дело, ну, SPA, был ли тогда Якс уже хотя бы? -3333.04 3334.04 SPEAKER_01 Да-да, был. -3334.04 3335.04 SPEAKER_01 Был, да? -3335.04 3336.04 SPEAKER_01 Ну конечно. -3336.04 3338.84 SPEAKER_01 Хорошо, я не помню, я тогда особо не программировал ещё. -3338.84 3362.00 SPEAKER_00 Кстати, можно тут сразу под шумок порекомендовать шикарный доклад от делана Бити, если вы хотите разобраться в ресте вот этих всех уровнях на очень хороших примерах, довольно лёгких, примитивных, понятных, с хорошим юмором от прекрасного автора, то доклад называется "Real World REST and Hands-On Hypermedia", который он делал на dotnext, кстати, был его самый первый доклад в России. -3362.00 3365.52 SPEAKER_00 В общем, посмотрите, доклад до сих пор не потерял свою актуальность, потому что REST никуда не делся. -3365.52 3366.52 SPEAKER_01 Да. -3366.52 3369.96 SPEAKER_01 Ну так вот, ладно, пойдём дальше. -3369.96 3373.04 SPEAKER_01 Мы потратили уже много времени на то, чтобы обсудить, что же такое REST. -3373.04 3377.56 SPEAKER_01 На самом деле, рекомендации дальше, они все очень прям конкретные. -3377.56 3401.44 SPEAKER_01 Я осмотрел, давайте так, брал три основных источника, это майкрософтская статья, это заландовская статья, и это статья неизвестного мне автора, которая мне так немножко отозвалась, что да, похожа на то, что я обычно стараюсь использовать, хотя некоторые были довольно забавные рекомендации, ну забавные, на английском есть хорошее слово "controversial", то есть противоречивые, да, наверное, правильно сказать, рекомендации, которые непонятно следуют или нет. -3401.44 3403.32 SPEAKER_01 Давай пойдём по частям. -3403.32 3404.60 SPEAKER_01 Начнём с первого, это Урлы. -3404.60 3416.52 SPEAKER_01 Это у нас, собственно, главное и первое, что видит пользователь, когда начинает работать с REST, и здесь, в принципе, все сходятся в том, что надо использовать множественное число для сущностей. -3416.52 3428.16 SPEAKER_00 Ну тут смотри, это не то, чтобы для сущностей, потому что для сущностей множественное число звучит странно, это всё-таки коллекция, это ресурсы, которые представляют собой коллекцию сущностей, и тогда понятно, почему множественное. -3428.16 3439.40 SPEAKER_01 Так а у тебя почти всегда будет сущность, это дальше ты, ну давай так, хорошо, сущность, которая имеет идентификатор, потому что почти всегда у тебя это будет потенциально коллекция сущностей. -3439.40 3454.24 SPEAKER_01 Может быть, ты не будешь иметь возможность получить коллекцию, например, если у тебя есть какой-нибудь шоппинг-карт, ну хотя вот с другой стороны, да, вот у тебя есть корзина, да, шоппинг-карт, технически в бэкэнде их много, но у каждого клиента она своя, -3454.24 3455.24 SPEAKER_00 правильно? -3455.24 3458.48 SPEAKER_00 Ну подожди, API-то всё-таки дёргается для конкретного клиента. -3458.48 3461.92 SPEAKER_01 Вот, да, для конкретного клиента она одна всегда, но у неё она… Она всегда одна. -3461.92 3464.88 SPEAKER_01 Ну если у неё… А, может быть, несколько, например. -3464.88 3470.84 SPEAKER_00 Ну обычно в магазинах нескольких не бывает, давай, может быть, конечно, может быть, но 99% у тебя всегда в магазине одна корзина. -3470.84 3475.44 SPEAKER_01 А, ну тогда у тебя не будет айдишника, да, согласен, ну тут тогда это самое, единственное число, окей. -3475.44 3493.60 SPEAKER_00 Кстати, здесь минутка весёлого, да, почему у неё не будет айдишника, потому что на заре времён, когда только начинали делать сайты, программисты именно делали вот так, что у тебя есть множество корзин и есть айдишник, и соответственно ты мог по айдишнику обратиться к своей корзине, и умные люди просто взяли, ну т.е. -3493.60 3498.08 SPEAKER_00 брали и эти айдишники перебирали, и по факту ты мог посмотреть в корзины других пользователей. -3498.08 3511.60 SPEAKER_00 Вот, и чтобы такого, таких глупостей как бы не делали, вот сделали такие вещи, что если урл относится к текущему пользователю, и этот пользователь не должен видеть никакие другие корзины, то айдишник просто не передаётся. -3511.60 3512.60 SPEAKER_00 Ну да, желательно его скрывать. -3512.60 3513.60 SPEAKER_01 Небольшой хак. -3513.60 3522.40 SPEAKER_01 Вот, очень желательно, и находите его какой-то внутренней логикой внутри у вас на сервере, там в сессии храните или просто поднимайте по юзер айди, какая же у него корзина. -3522.40 3523.40 SPEAKER_01 Это уже другое дело. -3523.40 3524.40 SPEAKER_01 Дальше. -3524.40 3553.52 SPEAKER_01 В целом все довольно, ну давай так, не очень однозначно, но в целом говорят, что не надо добавлять ненужные кусочки пути, т.е. если у вас есть ресурс и у него есть подресурс, при этом подресурс довольно уникальным образом определяется своим айдишником, т.е. его айди уникален не только в рамках родительского ресурса, а вообще в системе, то не надо тогда передавать вот этот вот топовый ресурс, айдишник его всегда в урле. -3553.52 3554.52 SPEAKER_01 Ну, грубо говоря. -3554.52 3578.76 SPEAKER_01 Если у вас есть разные сущности, которые принадлежат одному пользователю, не надо везде писать users/userid/books, что-нибудь или там /posts, что-нибудь, /comments, что-нибудь, userid, ну, в общем, во-первых, и так понятен из контекста, ну, userid в этом смысле плохой пример, но даже если он не был бы понятен из контекста, если у тебя блок-пост имеет уникальное id, достаточно сделать /posts/id. -3578.76 3607.80 SPEAKER_00 Ну, здесь, наверное, могут быть исключения, потому что иногда иерархия тебе позволяет эти урлы удобнее читать, т.е. нужно сказать, что rest level 3, он в отличие от болота, подразумевает то, что эти урлы должны быть пользователям хорошо читаемыми, и именно на это направлено большинство практик, ну, т.е. для машины наплевать, у тебя с ресурсами коллекции во множественном числе или в единственном называется, ей все равно, а вот пользователь, когда это будет читать, у него уже будет какое-то или понимание, или недопонимание. -3607.80 3611.20 SPEAKER_00 Поэтому бывают такие ресурсы, которые логичнее представить в виде иерархии. -3611.20 3625.28 SPEAKER_00 Город, страна, дом, если вы просто напишите дом 10, ну, дом с гуйдом, допустим, у вас будет смотреться не так красиво, как если бы вы написали, там, страна Россия, город Санкт-Петербург, улица такая, дом такой-то. -3625.28 3630.16 SPEAKER_01 Ну только теперь мы вспоминаем, что дом – это гуид, и поэтому это будет страна гуид, город гуид. -3630.16 3633.08 SPEAKER_01 Ну, именно так, да-да, это уже другой вопрос. -3633.08 3647.64 SPEAKER_01 Ну про это, кстати, тоже есть отдельная рекомендация, что для таких well-known штук, ну в смысле, допустим, для страны, тупо используйте, у нас есть как бы стандартная классификация этих самых двухбуквенных кодов стран, вот используйте ее, не надо ничего придумывать своего. -3647.64 3660.64 SPEAKER_01 Чем более стандартная штука, тем более стандартная, ну т.е. если на какую-то сущность есть стандартная ее репрезентация, хоть как-то классифицированная, используйте ее, облегчите жизнь потребителю гораздо больше. -3660.64 3668.24 SPEAKER_00 А еще желательно, чтобы эта стандартная стандартизация была url-френдли, потому что не все стандартизации у нас хорошо эскейпятся. -3668.24 3697.00 SPEAKER_01 Это правда, это правда, ну вот, и последнее, предпоследнее, что про урлы, тоже, кстати, мне кажется, что я не так часто это встречаю, и Майкрософт из Оландо говорит, надо предпочтительно использовать кебаб, кейзинг, это который, если у вас в урле в сущности нужно указать несколько слов подряд, ну в смысле, в одном термине, да, в одном сегменте, то нужно использовать дефис, не подчеркивая, не camel-кейзинг, когда с большой буквы пишется, а через дефис, и все, лаверкейзинг. -3697.00 3732.76 SPEAKER_00 Ну, я хочу сказать, что это правило, оно как бы довольно, сейчас скажу, не то, чтобы спорное, оно довольно поздно появилось в индустрии, т.е. уже после того, как RSTPI там хайпанул, приобрел своих последников, выпустилась куча книжек, и, к сожалению, у каждой компании раньше были свои какие-то рекомендации, именно поэтому у кого-то там Pascal, у кого-то Camel, у кого-то Kebabs, у кого-то Snake, в общем, разбродилось, разбродилось вот это все поверье, но именно, да, именно Kebab-кейс в последнее время начали писать у себя многие большие компании. -3732.76 3737.96 SPEAKER_00 Я не знаю, они там специально договорились или не специально, но вот NSC к этому явно в последнее время идет. -3737.96 3748.16 SPEAKER_01 Да, и везде написано не в формате рекомендаций, а в формате просто «не забудьте, что вообще-то та часть, которая не является доменным именем, она case-sensitive», т.е. -3748.16 3762.72 SPEAKER_01 вот весь URL, который вправо от после доменного имени, он вообще говоря case-sensitive, и надо бы его рассматривать именно так, хотя в Microsoft написано «не, но если там правда GUID передается, GUID можно и так, и сяк». -3762.72 3767.32 SPEAKER_01 Короче, там куча всяких разных но, но вообще-то case-sensitive по стандарту. -3767.32 3786.36 SPEAKER_00 Ну, кстати, да, и это довольно-таки мало людей знает почему-то, потому что в RLAC все привыкли видеть какое-то безобразие и об этом не задумываются, и иногда у нас, например, пользователи писали баги, типа я вот по ID-шнику такому запрашиваю ресурс, а он не находит, а он там ID-шник руками вбивал и немножко буковки перепутал, кейсы как раз-таки. -3786.36 3789.64 SPEAKER_00 Поэтому это правда, да, смотри на case-sensitive. -3789.64 3798.80 SPEAKER_00 Про GUID я тебе хотел немножко поправить, что это же все-таки не зависит от кейса, потому что GUID у него есть свой собственный парсер, и вот парсер сам решает, sensitive или не sensitive. -3798.80 3799.80 SPEAKER_00 Ну это да. -3799.80 3800.80 SPEAKER_00 Именно поэтому ты можешь там передать. -3800.80 3807.64 SPEAKER_01 Я понимаю, почему так происходит, но как бы у Microsoft в статье написано, что типа, мол, вообще-то оно case-sensitive. -3807.64 3816.16 SPEAKER_01 Ну там написано, но типа есть определенные сегменты с определенными типами данных, которые, ну и вот в общем дальше, да. -3816.16 3820.32 SPEAKER_01 Ну вообще да, рассчитывайте, что это всегда case-sensitive, это точно не ошибетесь. -3820.32 3860.96 SPEAKER_01 И последний момент интересный, смотри, в Rust-е level 2, ну вообще в Rust-е, да, у нас известная проблема, что у нас нет возможности делать экшены, в смысле, если у тебя через HTTP-глаголы не выражается что-либо, точнее, если тебе нужно выразить что-то, кроме create, read, update, delete, которые выражаются через HTTP-глаголы, то полноценные Rust-гайдлайны говорят, что нужно завести новый ресурс, к нему делать пост, создание операции по чему-нибудь, потом проверять ее статус, ну это типа такой, я не видел особо, чтобы таким пользовались, ну кроме действительно длинных операций. -3860.96 3865.72 SPEAKER_01 У Microsoft в этом смысле сейчас современные Azure-рекомендации довольно простая. -3865.72 3895.32 SPEAKER_01 Если вам нужно что-то сделать с какой-то сущностью, до которой вы, например, дошли по айдишнику, ну я не знаю, опубликовать блокпост, вот давай предположим, что это именно экшен, который нужно сделать, то url для такой операции будет выглядеть как там, пост, слэш, айдишник его, двоеточие, паблиш, т.е. глагол вот этого экшена делается через двоеточие, ну и естественно используется пост в этом случае, вот. -3895.32 3903.04 SPEAKER_00 Ну, ты затронул две темы, т.е. ты затронул тут асинхронные операции и связал их с постом, т.е. пост не всегда может быть асинхронный. -3903.04 3920.08 SPEAKER_01 Нет, смотри, смотри, смотри, да, я говорю, что идея в том, что, т.е. для любых асинхронных операций подход примерно понятие, да, дергаем пост, получаем какой-то айдишник, потом по нему там полим и выясняем статус асинхронной операции. -3920.08 3928.56 SPEAKER_01 Это как бы такой более-менее сложившийся паттерн, с которым примерно все согласны, насколько я вижу по статьям и в среднем по интернету. -3928.56 3943.56 SPEAKER_01 Но вот когда у тебя возникает вопрос, а вот как сделать операцию паблиш-посту, ну предположим, что это не просто обновление, да, одного и проперти, да, это некоторый процесс, который нужно запустить с какими-то дополнительными аргументами, то есть несколько техник. -3943.56 3970.96 SPEAKER_01 Ты можешь сделать что-нибудь типа пост, пост в смысле http-шный пост, там, www, что-нибудь, /blockpost/1/publish, а можешь сделать /1:publish, вот с двоеточием я, честно говоря, подхода не видел, хотя, признаться, ажурным как раз API им пользовался одно время, но что-то мне не попадались, видимо, такие действия, которые требовали прям глагола /action, вот Майкрософт говорит, давай через двоеточие, чтоб вот точно было понятно. -3970.96 3980.08 SPEAKER_00 Действительно, я думаю, это такое их довольно новомодное предложение, потому что как бы устоявшийся в индустрии подход в том, что всё, что угодно можно выразить через REST. -3980.08 3994.92 SPEAKER_00 В данном конкретном твоём случае, когда мы хотим опубликовать блокпост, мы всего лишь навсего находим url, ресурс, который называется публикации, и добавляем в ресурс публикации новый пост, вот таким образом ты публикуешь пост, вот и всё. -3994.92 3999.80 SPEAKER_00 То есть сводишь это всё к пустому чайнику первому случаю. -3999.80 4005.68 SPEAKER_00 У тебя для всего могут быть ресурсы, и для публикаций, и для запусков, и для скедурингов, и для чего угодно. -4005.68 4007.92 SPEAKER_01 Да, но проблема в том, что публикация не имеет айтишника -4007.92 4008.92 SPEAKER_00 своего. -4008.92 4009.92 SPEAKER_00 Ну почему это проблема? -4009.92 4016.84 SPEAKER_00 Ты же можешь в публикацию запульнуть пост, можешь, о том, что тебе не нужно публикации все считывать по айтишнику, ну не нужно, ну не считывай. -4016.84 4018.48 SPEAKER_01 Что здесь проблема? -4018.48 4062.20 SPEAKER_01 Ну проблема в том, что мне, например, такой подход кажется прям контринтуинтивным, в смысле, что мы привыкли, то есть сейчас сформулирую, во многих доменах мы привыкли к действию, прямому действию над объектом, в данном случае это как бы косвенное действие над объектом, ты не, у тебя главный объект, к которому ты обращаешься в урле, это пост, я хочу обратиться в урле к посту и с ним что-то сделать, а не я хочу обратиться в урле к публикации, а передать пост где-то там в аргументах, то есть вот этот вот переход, очень многих, меня в том числе, на самом деле сильно замедляет, когда я пытаюсь понять или осознать какой-то API, это прям вот. -4062.20 4085.04 SPEAKER_00 Смотри, мне кажется, ты сделаешь следующую ошибку, ты зря смешиваешь домен и транспортный уровень, то есть по сути HTTP это у тебя транспортный уровень, ну например, когда ты там по сигналеру передаешь, это все в хабе летает по кусочкам как бы бинарного протокола, ты же не пытаешься все в голове уложить в какой-то бизнес логичный процесс, ты понятия не имеешь там, как листанер это листанет, HTTP сокетит, это сосокетит. -4085.04 4086.04 SPEAKER_00 Все так. -4086.04 4099.40 SPEAKER_00 Так здесь у тебя нужно делить, что действительно в бизнес домене ты обращаешься к терминам поста, но это транспортный протокол, это REST, он тебе не призван идеально описывать бизнес домен, он не про то, он не про описание домена вообще, он про протокол общения. -4099.40 4118.00 SPEAKER_01 С этим я с тобой согласен, но, к сожалению, процентов, пандомное число, 60 API-шек, с которыми я встречаюсь, единственное, что содержит, это свагерспеку без описания того, что если вы хотите сделать вот такой бизнес процесс, вам нужно подергать API-методы в таком-то порядке. -4118.00 4122.64 SPEAKER_01 И ты понимаешь бизнес процесс только глядя на свагерспеку. -4122.64 4124.20 SPEAKER_00 Ну, на OpenAPI-спеку. -4124.20 4127.32 SPEAKER_00 Ну, опять же, может это проблемы документации или проблемы -4127.32 4128.32 SPEAKER_01 еще чего-то. -4128.32 4145.68 SPEAKER_01 Это может быть проблемы документации, то есть понятно, что было бы здорово, если бы REST API был чисто технической штукой, и мне просто было понятно, окей, и мне нужно сначала создать блокпост, отредактировать его, добавить черновики, картинок довесить, и потом опубликовать. -4145.68 4154.56 SPEAKER_01 И рядышком с этим описанием бизнес процесса, у меня было бы, типа, для этого сделай PUT такой-то, для этого сделай POST такой-то, для этого сделай POST такой-то. -4154.56 4159.36 SPEAKER_01 Мне тогда не важно, тогда я просто беру механически, что мне сказали сделать, то и делаю. -4159.36 4165.52 SPEAKER_01 Проблема в том, что API-шек, где написано так, в моей практике, по крайней мере, катастрофически мало. -4165.52 4174.44 SPEAKER_00 Кстати, вот эту самую штуку делает гипермедия, потому что гипермедия тебе возвращает абстрактные экшены, которые тебе нужно просто вызывать, не задумываясь о том, по какому урлу она там находится. -4174.44 4177.48 SPEAKER_01 Не совсем, гипермедия не возвратит тебе контент-боди. -4177.48 4186.64 SPEAKER_00 Ну почему же это не возвратит, конечно, возвратит, но это же такой же обычный урл, ты его можешь дернуть и что-то оттуда получить. -4186.64 4197.52 SPEAKER_01 Нет, нет, нет, в смысле, я не уверен, что ты можешь в гипермедии передать ожидаемый боди-реквеста. -4197.52 4203.36 SPEAKER_00 Ты можешь передать там боди, ты можешь передать там форматор, которым ты хочешь отформатировать, и можешь передать там другие ожидания. -4203.36 4209.36 SPEAKER_00 Это обычная HTTP, грубо говоря, запрос, просто более высокоуровневый, в терминах бизнеса, а не в терминах какой-то транспорта. -4209.36 4215.68 SPEAKER_01 Слушай, может быть, но возвращаемся к вопросу, цена, так сказать, и польза. -4215.68 4229.08 SPEAKER_01 Я такие API-шки, скажем так, не понимаю и не люблю, потому что это сильно, когда у меня домен сильно совпадает с транспортным уровнем, это очень, ну как бы, ценно и легко. -4229.08 4230.08 SPEAKER_00 Потом в отладке. -4230.08 4237.12 SPEAKER_00 Мне кажется, смотри, если мы возьмем какие-нибудь статьи, которые пропагандирует gRPC, вот это как раз один эндпоинт, и делай там с ними что хочешь. -4237.12 4238.12 SPEAKER_00 GraphQL. -4238.12 4239.12 SPEAKER_00 GraphQL. -4239.12 4244.12 SPEAKER_00 То у них как раз-таки вот это, что мы сейчас обсуждаем, вот это проблема. -4244.12 4253.92 SPEAKER_00 Ну то есть нужно признать, что у HTTP-транспорта, у REST давай так, это проблема, что не всё выражается довольно интуитивными бизнес-терминами. -4253.92 4257.94 SPEAKER_00 А вот если мы берём GraphQL, то там ты у любой сущности можешь, по сути, дёрнуть любой метод. -4257.94 4261.72 SPEAKER_00 То есть они это ставят как свой плюс, если мы сравним с REST. -4261.72 4263.84 SPEAKER_00 Ну да, есть у них такой плюс, есть у REST-а такой минус. -4263.84 4272.76 SPEAKER_01 Ну вот тут скорее, да, про то, что вопрос, надо ли стремиться к тому самому REST-левел, 2 или 3, с точки зрения вообще всех операций. -4272.76 4279.52 SPEAKER_01 Кажется, что, с моей точки зрения, нет, не надо, но кажется, что индустрия куда-нибудь пойдёт в другое место. -4279.52 4284.14 SPEAKER_01 Ладно, давай с урлами плюс-минус закончим и пойдём к следующей части. -4284.14 4287.72 SPEAKER_01 Это контракты, там про эти глаголы мы поговорим чуть позднее. -4287.72 4290.56 SPEAKER_01 Давай немножко про контракты, что тут все говорят. -4290.56 4297.92 SPEAKER_01 Ну, в среднем все там плюс-минус сходятся в том, как нужно делать контракты. -4297.92 4306.16 SPEAKER_01 То есть почти все говорят, что не надо возвращать массивы в качестве топ-левел сущности, потому что это не расширяемый контракт вообще. -4306.16 4313.88 SPEAKER_01 Массив всегда должен быть под ключиком каким-нибудь, потому что иначе вы не сможете ничего дополнительно вернуть, помимо массива. -4313.88 4326.52 SPEAKER_00 Ну, то есть, допустим, если массив у вас вырос, и вы хотели сделать пейджинг, и хотите теперь возвращать в этом объекте count, сколько всего элементов в этом общем массиве, а не только то, что вы сейчас вернули, сколько элементов на этой странице. -4326.52 4334.52 SPEAKER_00 Это вполне нормальная эволюция процесса и, скорее всего, в больших коллекциях, когда они у вас вырастут, вы с этим столкнётесь. -4334.52 4343.32 SPEAKER_00 И вот такое изменение вы не сможете сделать, если вы возвращали массив топ-левелом, а если вы это запихивали под ключиком как отдельное какое-то одно поле, то там добавляете вообще всё, что хотите. -4343.32 4344.32 SPEAKER_01 Да. -4344.32 4354.76 SPEAKER_01 Интересная рекомендация как раз из статей, неизвестной статьи из интернета, которая не встречается ни в The London, ни в Microsoft, по крайней мере, я не нашёл, может, пропустил там много их. -4354.76 4365.20 SPEAKER_01 Это про то, что момент номер один, всегда для всех идентификаторов в контракте используйте строки, т.е. даже если у вас в BD число, отдавайте всё равно строку. -4365.20 4376.60 SPEAKER_01 Потому что кто знает, как что изменится, а строки точно всё сожрут внутри себя, т.е. если вы потом решите перейти на Гуиды, то не надо будет менять контракт на Пишки, по сути. -4376.60 4390.20 SPEAKER_00 Да, вот это, кстати, очень полезное правило, которое почему-то очень редко встречается, я тебя поддержу и сам пользуюсь именно таким подходом, потому что, опять же, обычно, когда вы возвращаете айтишники, это идентификаторы из базы данных. -4390.20 4395.16 SPEAKER_00 А то, какую базу данных сейчас использует приложение, это личное дело любого микросервиса. -4395.16 4398.24 SPEAKER_00 Т.е. если он сейчас это в памяти хранил, у него там могут быть инты. -4398.24 4408.08 SPEAKER_00 Завтра он подрос, у него там будет какой-нибудь пастгря, потом он перейдет на какой-нибудь MS SQL, там у него должны быть Гуиды, при том не просто Гуиды, а сортированные Гуиды и так далее, и тому подобное. -4408.08 4412.96 SPEAKER_00 Потом, если нужны шарды, то там желательно ещё добавить номер кластера перед каждым этим айтишником. -4412.96 4423.64 SPEAKER_00 В общем, и внутри самого сервиса, сервис обязан мочь переходить на любую базу данных, на ту, которая полностью удовлетворяет его как бы системам, его системам. -4423.64 4424.64 SPEAKER_00 А требования могут меняться, как вы все понимаете. -4424.64 4430.32 SPEAKER_00 И сервис как раз-таки не должен наружу декларировать, а какого типа у него идентификаторы. -4430.32 4435.12 SPEAKER_00 Поэтому в JSON строка – это как раз не декларирование типа, это там object. -4435.12 4446.12 SPEAKER_00 Вот если вы в коде возвращали бы object, то в JSON вы должны возвращать string, и вот как раз идентификатор – это та внутренняя логика, которую сервис обязан как бы контролировать самостоятельно. -4446.12 4452.40 SPEAKER_00 И никто снаружи не может эти айтишники, по сути, никак их интерпретировать и никак на них рассчитывать. -4452.40 4453.40 SPEAKER_01 Вот. -4453.40 4460.12 SPEAKER_01 А теперь есть второй кусочек этой рекомендации, который на самом деле я встречал несколько раз, не у больших ребят, но во многих статьях. -4460.12 4463.20 SPEAKER_01 Называется «используйте префиксы для ваших идентификаторов». -4463.20 4465.24 SPEAKER_01 То есть, о чем речь? -4465.24 4471.72 SPEAKER_01 Это поможет, то есть это как бы для облегчения жизни клиентским разработчикам и в каком-то смысле саппорту. -4471.72 4485.68 SPEAKER_01 То есть если у вас, например, есть, не знаю, возвращаемся к нашему традиционному примеру про блокпосты и комменты, у каждого из них, предположим, есть уникальный идентификатор, да, сквозной, ну потому что они лежат в каждой своей табличке в BD, допустим, и там сквозная нумерация. -4485.68 4505.48 SPEAKER_01 Так вот, вы возвращаете не просто строчку с содержимым 1, строчку с содержимым 2, строчку с содержимым 3, а для всех постов вы возвращаете строчку с содержимым p1, p2, p3, то есть с префиксом p, типа что это посты, а для комментов вы возвращаете строчку с префиксом c, да, c1, c2, c3. -4505.48 4524.40 SPEAKER_01 Клиенту пофигу, потому что это строка все равно, он не должен ее парсить, он не должен с ней ничего делать, это просто прозрачная для него строка, но во-первых он сам понимает, что ага, тут мне вернулись, там, идентификатор на p, значит окей, типа это наверное про посты, а тут на c, значит это наверное про комменты, в таком духе. -4524.40 4526.00 SPEAKER_01 Чисто просто понятнее становится. -4526.00 4540.28 SPEAKER_01 При этом, при этом автор говорит, что ну вообще-то, вообще-то не нужно обязательно считать, что вот этот вот айдишник, который вы возвращаете пользователю, должен совпадать с primary ключиком вашей базы. -4540.28 4557.96 SPEAKER_01 Вообще говоря, вы можете использовать юиды для хранения в базе, а пользователю возвращать что-то более осмысленное, например, или еще каким-то образом там компаунд ключ собранный, как ты говоришь, из шарда или еще из чего-нибудь, это не обязательно так, не надо всегда возвращать primary key наружу. -4557.96 4571.16 SPEAKER_00 Смотри, наверное более распространенный пример это когда у вас в базе все хранится все-таки синтами, потому что это должно быть красивенько и все такое, но наружу вы не хотите отдавать инты, потому что они легко подбираются, и пользователь может подобрать их просто чисто перебором. -4571.16 4582.88 SPEAKER_00 Поэтому существуют специальные библиотечки, которые превращают ваши инты, то есть хешируют их по словарю в какой-то хеш, которых перебирать в принципе бесполезно, но при этом он у вас остается довольно читабельным, коротким и так далее. -4582.88 4587.36 SPEAKER_01 Надо сказать, не хешируют здесь важно, а именно конвертируют, потому что обратная конвертация тоже возможна. -4587.36 4590.96 SPEAKER_01 Вам же нужно из этого айдишника обратно-то свою чиселку получить, когда к вам придут. -4590.96 4593.96 SPEAKER_00 Да, да, ты прав, именно так. -4593.96 4596.56 SPEAKER_00 Я ещё хотел добавить про префиксы. -4596.56 4610.64 SPEAKER_00 Я тоже эту технику с префиксами очень много использую, и действительно, может быть, многие из вас, кто особенно любит гуйды, встречались с такими, что приходишь в базу данных какой-нибудь, а там есть 10 колонок, и во всех этих колонках написано «айдишники», и всё это гуйдами забито. -4610.64 4624.08 SPEAKER_00 И ты, естественно, без какой-то чёрной магии недели, проведённой над этим дампом, никогда не сможешь понять, а чьи это гуйды, откуда они прилетели, и что они там лежат, потому что название колонок тоже имеет свойство переименовываться, записаться не туда и так далее. -4624.08 4627.00 SPEAKER_00 В общем, по названию иногда бывает не добраться. -4627.00 4630.18 SPEAKER_01 Ну подожди, ты хочешь сказать, что ты префикс даже в базу положишь? -4630.18 4631.18 SPEAKER_01 А как же? -4631.18 4632.18 SPEAKER_01 Смотри. -4632.18 4634.92 SPEAKER_01 Там юидные типы колонок, там вот это всё. -4634.92 4636.92 SPEAKER_00 Не-не-не, немножко не так. -4636.92 4640.20 SPEAKER_00 Или вот смотри, более, наверное, такой правильный пример, это в логах. -4640.20 4648.36 SPEAKER_00 Вот ты в логах видишь сообщение «сущность такая не может быть там вставлена», и айдишник этой сущности, и всё, и больше у тебя никакой информации о ней нет. -4648.36 4649.36 SPEAKER_00 Ну там, наверное, логер. -4649.36 4655.08 SPEAKER_00 Наверное, ты можешь пойти, достать код, достать какой-то проект, найти где там логеры, посмотреть, а что же за сущность была вставлена. -4655.08 4670.20 SPEAKER_00 А вот если у тебя есть префиксы, которые рассказывают, что это, в принципе, айдишник поста был, то есть по правде в айдишник добавляется там, допустим, «п» или можно просто «пост», если это слово небольшое, то ты сразу по айдишнику видишь, что в логах у тебя залогировано. -4670.20 4671.20 SPEAKER_00 То есть айдишник какой сущности. -4671.20 4677.76 SPEAKER_00 И про базы данных пример я тебе привел, это когда у тебя внешняя база данных хранит ссылки на твои сущности. -4677.76 4682.40 SPEAKER_00 То есть внешняя база данных воспринимает твои айдишники как строки. -4682.40 4684.20 SPEAKER_00 Она не может оттуда выделить ни префикс, ничего. -4684.20 4689.92 SPEAKER_00 Она взяла строку, как-то я дал, и положила к себе как бы референс к этому пользователю, я его люблю, завтра я к нему схожу. -4689.92 4692.52 SPEAKER_00 И у нее в базе, да, хранятся это все именно с префиксами. -4692.52 4697.96 SPEAKER_00 И ты, когда на ее базу смотришь, ты видишь сразу все вот эти внешние зависимости, ты понимаешь, откуда они. -4697.96 4702.72 SPEAKER_00 То есть я в свой префикс добавляю не только имя сущности, я добавляю еще имя сервиса. -4702.72 4708.72 SPEAKER_00 Естественно, сокращённое, но я по айдишнику могу определить, во-первых, сервис, а во-вторых, сущность из этого сервиса. -4708.72 4710.40 SPEAKER_00 И только потом его ГУИД. -4710.40 4711.40 SPEAKER_00 Прикольно. -4711.40 4712.40 SPEAKER_00 Прикольно. -4712.40 4713.40 SPEAKER_01 Окей. -4713.40 4714.40 SPEAKER_01 Хорошо. -4714.40 4715.40 SPEAKER_01 Давай еще поговорим. -4715.40 4716.40 SPEAKER_01 А, смотри. -4716.40 4717.40 SPEAKER_00 Еще одна мелочь. -4717.40 4724.92 SPEAKER_00 Многих людей коробит, потому что, когда ты добавишь имя сервиса, потом еще имя сущности, а потом еще ГУИД, у тебя превращается в ГУИД очень большой. -4724.92 4727.54 SPEAKER_00 То есть айдишник превращается в что-то очень большое. -4727.54 4728.68 SPEAKER_00 Здесь есть небольшой лайфхак. -4728.68 4734.64 SPEAKER_00 На самом деле ГУИД шифруется шестнадцатиличным числом. -4734.64 4736.20 SPEAKER_00 Шестнадцатиличная система измерения. -4736.20 4738.36 SPEAKER_00 Это никакого смысла вообще не имеет. -4738.36 4744.44 SPEAKER_00 Берете стандартный какой-нибудь Base64 или еще что-то лучшее и шифруете по полному алфавиту. -4744.44 4750.28 SPEAKER_00 Как я уже сказал, URL он case-sensitive, поэтому никаких проблем у вас не будет, если у вас там даже все буквы будут скакать. -4750.28 4754.04 SPEAKER_00 И у вас ГУИД уменьшается прямо легко в пару раз вообще. -4754.04 4759.20 SPEAKER_00 Не надо шифровать шестнадцатиличную систему, это не имеет никакого смысла. -4759.20 4766.24 SPEAKER_01 Да, либо есть всякие там Snowflake ID, вот эти все, которые аналоги такие же, плюс-минус сортируемые, но которые занимают существенно меньше места. -4766.24 4767.24 SPEAKER_00 Можно на них посмотреть. -4767.24 4775.00 SPEAKER_00 То есть если вы ГУИД по размеру уменьшаете, то то, что вы добавляете префикс, грубо говоря, сохраняет вам примерно ту же самую длину и вас это будет меньше коррубить. -4775.00 4777.16 SPEAKER_01 Так, что еще интересного? -4777.16 4786.96 SPEAKER_01 Ну понятно, используйте структурированные ROR, это все говорят, ISO 8601 для timestamps и для всяких других дат и прочего. -4786.96 4795.32 SPEAKER_01 Причем сказано, что когда вы форматируете это все потом в JSON, в ISO 8601, не доверяйте вашей, короче, платформе про то, что она корректно сделает. -4795.32 4809.16 SPEAKER_01 Лучше напишите явную спецификацию формата, что вы хотите, потому что дефолты меняются, подходы меняются, а вот если вы точно напишете, что там yyyy, mm, dd, вот это все, то точно не поменяется. -4809.16 4810.32 SPEAKER_01 Лучше пишите явно. -4810.32 4825.32 SPEAKER_01 Так, для строк, да, вот это, кстати, у Майкрософта прям очень большой раздел указан, для любых строк, которые встречаются в вашем контракте, напишите четкий контракт. -4825.32 4832.60 SPEAKER_01 То есть для каждого поля, которое строка, напишите, если там, ну типа если это а-ля Unum, то напишите какие значения там могут быть. -4832.60 4837.28 SPEAKER_01 Это не значит, что там не может быть других, но хотя бы вот эти точно могут быть. -4837.28 4843.76 SPEAKER_01 Если это поле ограничено по длине, напишите, если оно там, ну понятно, что всякие обязательности точно нужно указывать и так далее. -4843.76 4848.84 SPEAKER_01 То есть не должно быть в контракте поля, в котором просто написано "строка". -4848.84 4856.52 SPEAKER_00 Ну это немножко напоминает языки со слабой типизацией типа Питона, да, где там всё на свете может храниться во всём, чем угодно. -4856.52 4859.24 SPEAKER_00 Или, допустим, если бы у нас в шарпе все поля были бы object. -4859.24 4867.72 SPEAKER_00 Ну конечно, если бы поля все были бы object, мы бы всё в комментариях писали, что этот object, это на самом деле Unum, этот object – это data, а JSON – это та же самая фигня. -4867.72 4873.92 SPEAKER_00 Там всё это, грубо говоря, строки, там буквально 5 типов, и в основной части это, конечно, строки, да, их надо написать, надо документировать. -4873.92 4875.60 SPEAKER_00 По-моему, там три типа, что там? -4875.60 4877.16 SPEAKER_00 Там bool, int, ну number. -4877.16 4878.92 SPEAKER_01 Bool, number, string, всё. -4878.92 4882.08 SPEAKER_01 Ну не берём листы, всякие вот эти array, это уже понятно. -4882.08 4883.08 SPEAKER_01 Да-да, элемент примитива. -4883.08 4884.08 SPEAKER_01 Коллекция. -4884.08 4886.80 SPEAKER_01 Ну да-да, наверное, в три, если только примитивы брать. -4886.80 4888.72 SPEAKER_01 Так, что ещё у нас по контрактам? -4888.72 4899.68 SPEAKER_01 А, ну у Майкрософта, кстати, явно написано, используйте одинаковые JSON-схемы для put-ов, патчей, ну, респонсов, понятно, get-ов, респонсов, и для пост-ов, request-ов, респонсов. -4899.68 4921.48 SPEAKER_01 Максимально делайте похожую схему, чтобы в идеальном случае то, что вы получили из get-а, нужно было немножко поменять, что вы там хотите поменять, например, отправить в put, вот, или в post, если вы хотите, например, копию создать объекта, вот, вы получили какой-то объект из get-а, отдали в post, его же будет копия, вот, в таком духе. -4921.48 4927.40 SPEAKER_01 То есть, ну, понятно, не плодите там, там где ожидается одинаковый плюс-минус схемы, используйте реально одинаковую плюс-минус схему. -4927.40 4937.92 SPEAKER_01 Так, так, так, так, так, довольно много всяких разных рекомендаций про error-коды, что-то пешные, то есть там 400, 404, вот это все. -4937.92 4956.88 SPEAKER_01 Одна из интересных дискуссий, которую я много где слышал, это вопрос, вот смотри, берем мы url, делаем мы get, поэтому url-у по какому-то конкретному idшнику, ну, допустим, у нас есть там блог-пост, мы хотим получить блог-пост с idшником 999, а его никогда не было, что мы должны вернуть? -4956.88 4961.92 SPEAKER_00 Ну, опять же, здесь в зависимости от договоренности, никакого единого стандарта по рынку нет. -4961.92 4983.08 SPEAKER_01 Вот, и как раз, у Microsoft, кстати, у Zalando каких-то особых нет, по-моему, они там говорят, ну, 404 и все, что-то как бы not found, вот, а вот неизвестный автор из интернета говорит, нет, 404 not found подразумевает, что, короче, это вы прям в url-е ошиблись, вот это все, типа, нельзя возвращать not found в этом случае, используйте что-нибудь другое. -4983.08 5001.36 SPEAKER_01 Я, говорит, использую 410, вот, это, а что-то по код-ган, ну, что, типа, ресурс был, но больше нет, вот, чтобы как бы пользователь понимал, что он 404 в смысле он в url ошибся или в смысле он в url-у написал правильно все, но, ну, там не найдено ничего. -5001.36 5026.24 SPEAKER_00 Смотри, я насчет ошибок я очень часто сталкивался случаями, когда компании нагораживали нам очень большое число ошибок, ну, то есть у них там использовалось 20 или там 25, чуть ли не ячайник они могли когда-нибудь вернуть, ну, потому что сидят там какие-то большолобые бэкэндеры и начинают выдумывать для себя, вот здесь был конфликт, вот здесь я обновил, но конфликта не было, но он мог бы быть, поэтому я вот вернул вот такой вот нашел интересный код. -5026.24 5031.60 SPEAKER_00 В общем, здесь прежде всего нужно задумываться, а кто эти ошибки у вас будут читать, то есть кто ваши клиенты. -5031.60 5067.84 SPEAKER_00 И если у вас клиент действительно способен обрабатывать ваши 25 типов статус кодов, то, конечно, пуляйте, но в большинстве случаев ваши клиенты – это вот тупые какие-нибудь React HTTP клиенты, которые знают буквально там 5 кодов по пальцам, и вот 404 они поймут, я вам 100% гарантирую, а вот 410 нет, ну или каждый будет понимать по-своему, и вам придется ходить из команды в команду и договариваться, что у меня вот 410, поэтому в таком случае я бы здесь больше склонился к 404, потому что это стандартная вещь, ее понимают многие клиенты, ее понимают там кэши, логи, как стандартные мидлвари, которые там метрики отсылают и прочее-прочее-прочее. -5067.84 5073.48 SPEAKER_00 Здесь больше нужно идти к стандартизации и к пониманию клиентами, т.е. кто вас будет интерпретировать. -5073.48 5104.68 SPEAKER_01 Да, и, кстати, Zalando здесь во всем, что касается в этих error-кодах, у них прямо есть огромная большая табличка по каждому из этих error-кодов, ну в смысле табличка с error-кодами, и на каждой есть признак, а надо ли его вообще документировать в API, т.е. они говорят, что очень часто бывает такая ситуация, что вы видите там, не знаю, API-шку, в ней 10 методов, и на каждом методе написано, он может вернуть 200, он может вернуть 500, он может вернуть 400, он может вернуть 404, и везде написано одно и то же. -5104.68 5107.36 SPEAKER_01 Да-да, есть такие API-шки, да-да-да. -5107.36 5121.48 SPEAKER_01 У Zalando в рекомендациях написано, все well-known стандартные коды, которые возвращаются в известных обычных случаях, типа не надо документировать 500, все знают, что 500 может прийти от сервера, не надо вообще этого OpenAPI-спеку даже включать. -5121.48 5141.72 SPEAKER_00 Ну вот видишь, как программисты, они когда видят дублирование у себя в коде, у них почему-то мозг включается, что нужно вот это дублирование вынести метод, куда-нибудь обозначить, а когда они видят дублирование в тексте одного и того же, мозг у них очень медленно включается, что блин, ну нафига вы дублируете одно и то же, ну это же можно или в одном месте записать где-нибудь на общей странице документации, или еще где-то, ну не нужно это дублировать, -5141.72 5142.72 SPEAKER_01 конечно же. -5142.72 5143.72 SPEAKER_01 Ну да, да-да-да. -5143.72 5157.80 SPEAKER_01 Ну и еще один момент касательно контрактов, последний, который я хотел бы отметить, это что, опять же, мне кажется, в индустрии нет какого-то единого стандарта, как в проперти в JSON, вот ты к чему склоняешься, к CamelCase, к SnakeCase? -5157.80 5160.64 SPEAKER_01 Наверное, это два самых популярных, пожалуй, да, наверное? -5160.64 5166.64 SPEAKER_00 CamelCase и SnakeCase, через подчеркивание, либо с… Подожди, мы как нормальные C#-исты, мы должны склоняться к PascalCase, я считаю. -5166.64 5167.64 SPEAKER_00 В пропертях? -5167.64 5168.64 SPEAKER_00 Нет. -5168.64 5169.64 SPEAKER_00 Конечно. -5169.64 5170.64 SPEAKER_00 Да почему Camel? -5170.64 5171.64 SPEAKER_00 Давай Pascal. -5171.64 5174.76 SPEAKER_00 Ну у нас проперти называются в Pascal же, пусть и JSON-чики -5174.76 5175.76 SPEAKER_01 страдают. -5175.76 5192.24 SPEAKER_01 Ну проперти в Pascal, я согласен, ну не знаю, короче, традиционно я, конечно, больше CamelCase встречаю, но вот тут Microsoft говорит, короче, Майкрософт считает, что нужно обязательно CamelCase, ничего другого, Zalando считает, что обязательно SnakeCase, ничего другого, я так понимаю, что тут каждая компания, как договорится, лишь бы весь ваш API выглядел одинаково. -5192.24 5199.16 SPEAKER_00 Ну типа того, мне кажется, у нас CamelCase просто по дефолту включены, поэтому большинство API в C#, они именно CamelCase-овые. -5199.16 5217.96 SPEAKER_00 Тут и другой интересный вопрос есть, потому что на самом деле проперти в JSON не существует, в JSON все это дикшнери, и существует, это дикшнери-ключ на самом деле, а не проперти, и существует отдельная настройка в сериализаторе, типа проперти, окей, у вас будут вот такие, а что будет, если дикшнери вы передадите? -5217.96 5224.44 SPEAKER_00 Ведь, по сути, в JSON и проперти, и дикшнери будут приведены к JSON-дикшнери, потому что это все дикшнери, вот. -5224.44 5244.64 SPEAKER_00 И бывает такая ситуация, когда у вас проперти написаны в одном кейсе, а дикшнери, по сути, настройка стоит в другом кейсе, типа обычно даже ключи дикшнери стараются не менять, то есть они там, допустим, лежат в Pascal кейсе, а все остальное у вас там в Camel кейсе, вот, и сам JSON, соответственно, уже будет не соответствовать этому правилу, потому что на уровне JSON это одно и то же. -5244.64 5259.80 SPEAKER_00 То есть вот здесь довольно большая проблема встречается, вот здесь надо еще договориться, а просто так модифицировать ключи в дикшнере обычно бывает не очень хорошо, потому что некоторые API спроектированы так, что воспринимаются ключи в дикшнере именно case-sensitive, ну потому что это ключи, это не свойства. -5259.80 5265.48 SPEAKER_00 В общем, здесь тоже большой интересный вопрос, на который индустрия до сих пор, к сожалению, не договорилась. -5265.48 5269.12 SPEAKER_01 Ну я думаю, что на самом деле и не договорится, все равно слишком у нас много. -5269.12 5278.92 SPEAKER_00 Так и есть, вы поэтому договоритесь на уровне своей компании, т.е. у каждой компании должен быть по каждому вот такому спорному пункту свой гайдлайн, как так положено делать у вас. -5278.92 5289.72 SPEAKER_01 Пойдем дальше, секция под названием HTTP-глаголы и идемпотентность, они идут вместе, потому что довольно сильно связаны. -5289.72 5299.96 SPEAKER_01 Ну, во-первых, все, в общем-то, сходятся мысли, что в современном мире нужно обязательно предоставлять механизмы обеспечения идемпотентности. -5299.96 5329.64 SPEAKER_01 Напомню, что такое идемпотентность, у вас есть разные HTTP-глаголы, и некоторые вы можете достаточно безболезненно при правильном спроектированном API повторять, т.е. например, вы можете вызвать GET много раз и, в принципе, на состояние системы с той стороны это не повлияет, оттого что вы вызвали, вам могут вернуться, естественно, разные немножко данные, потому что, возможно, как-то объект живет, меняется, у него там меняются статусы, но в целом вы можете без болезненно повторять GET-реквесты, не боясь что-то респортить. -5329.64 5346.72 SPEAKER_01 Вы точно также можете безболезненно повторять DELETE-реквесты, а вот если вы повторите, например, POST, то это может привести к нехорошим последствиям, потому что POST по дефолту не идемпотентен, и сервер как бы аккуратно его выполнит и создаст еще один объект, например, если вы POST создаете -5346.72 5347.72 SPEAKER_00 объект. -5347.72 5351.64 SPEAKER_00 Ну, это стандартный вопрос на собеседовании, чем отличается PUT от POST. -5351.64 5352.64 SPEAKER_00 Да-да-да. -5352.64 5355.68 SPEAKER_00 Единственное отличие в том, что POST не идемпотентен, а PUT идемпотентен. -5355.68 5360.28 SPEAKER_01 Да, ну их всего два, короче, точно не идемпотентных, это PATCH и POST, соответственно. -5360.28 5361.28 SPEAKER_01 Вот. -5361.28 5365.36 SPEAKER_00 Ну, подожди-подожди, PATCH вполне идемпотентен. -5365.36 5366.36 SPEAKER_00 Почему? -5366.36 5370.84 SPEAKER_00 Ну, если ты в PATCH меняешь имя пользователя и ты поменял его 100 раз, то имя там будет одно и то же. -5370.84 5373.80 SPEAKER_00 Да, но если я в PATCH делаю EDD в коллекцию. -5373.80 5374.80 SPEAKER_00 В PATCH EDD? -5374.80 5376.36 SPEAKER_00 Да, там есть такой вариант. -5376.36 5379.36 SPEAKER_00 Ну да-да, потому что PATCH это, по сути, модификация. -5379.36 5383.28 SPEAKER_00 В модификации ты как можешь поле поменять, так и можешь добавить некий элемент, поэтому непредсказуемо. -5383.28 5386.56 SPEAKER_01 В PUT ты обязан коллекцию целиком передать, и поэтому он идемпотентен. -5386.56 5390.36 SPEAKER_01 А в PATCH можно кусочек, там есть EDD и remove, по-моему, даже там есть. -5390.36 5391.36 SPEAKER_01 Что-то мне казалось, что есть. -5391.36 5392.36 SPEAKER_01 Ну ладно. -5392.36 5394.88 SPEAKER_01 Ну ты же точно так же в PUT можешь коллекцию добавлять? -5394.88 5395.88 SPEAKER_01 В PATCH? -5395.88 5398.24 SPEAKER_01 Добавлять не могу в PUT, в PUT она целиком перезапишется. -5398.24 5401.76 SPEAKER_00 Опять же, бывают разные имплементации, кто как -5401.76 5402.76 SPEAKER_01 интерпретирует PUT. -5402.76 5406.88 SPEAKER_01 Ладно, да, хорошо, давай мы это, не будем углубляться в эту область. -5406.88 5414.96 SPEAKER_01 Короче, есть, в принципе, три таких способа, что ли, да, обеспечить эту самую демпотентность. -5414.96 5431.56 SPEAKER_01 Один вариант – это ключи демпотентности, т.е. вы вместе с POST просто посылаете заголовочки, отдельный еще ID-шник, там GUID, грубо говоря, и даже если… и сервер, соответственно, трекает, он будет знать, что операцию с таким GUID он уже выполнял. -5431.56 5433.88 SPEAKER_00 Смотри, здесь, наверное, стоит сказать, а в чем проблема-то? -5433.88 5436.96 SPEAKER_00 Ну допустим, у нас все урлы не демпотентны, и к чему это приводит? -5436.96 5464.56 SPEAKER_01 Ну проблема в том, что, например, если мы берем POST, да, традиционно он используется для создания сущности, вы попробовали вызвать метод, вам вернулся там тайм-аут, вы не знаете, вам вернулся тайм-аут, потому что ответ к вам не пришел, а сервер уже выполнил запрос, или ваш реквест не дошел, а даже если, например, не дошел ответ, сущность-то уже создана на сервере, сервер ее обработал, создал, получил какой-то ID-шник, но вы этот ID-шник не узнали. -5464.56 5469.04 SPEAKER_01 Вы, естественно, делаете retry, как положено в современном облаке. -5469.04 5484.60 SPEAKER_01 Допустим, второй retry проходит, но в итоге у вас созданы две сущности, но первая никуда ни к чему не привязана, потому что ее ID-шник потерян, или наоборот, она в каком-нибудь списке будет видеться, и вы, когда получите список сущностей, увидите, что, оказывается, вы создали две. -5484.60 5503.56 SPEAKER_01 А если бы был способ понять, что вот создание сущности вы повторяете, на самом деле, то тогда сервер мог бы сообразить, ага, он хочет создать сущность снова, но он же уже пробовал, я уже это обработал, можно не обрабатывать второй раз. -5503.56 5527.68 SPEAKER_01 Так вот, способов это сделать, два хороших, это либо вы передаете ключ ID-патентности, то есть некоторые просто искусственный идентификатор, грубо говоря, уникальный идентификатор запроса, который сервер помнит какое-то время у себя и знает, что если к нему повторно придутся таким идентификатором, то просто можно ничего не делать, а вернуть, соответственно, созданную уже там сущность. -5527.68 5556.00 SPEAKER_01 Либо же надо просто отдать, то есть нельзя делать никакой генерации, условно говоря, ID-шников на клиенте, то есть этим самым уникальным идентификатором будет являться нечто сгенеренное на клиенте, то есть в этом случае ID-шники генерятся на клиенте, в пост передаются они, вы точно так же трекайте, но вы знаете, что поскольку не вы генерите ID-шник, вы просто увидите, что объект с таким ID уже создан, ну как бы и просто скажите, ну окей, да, уже создан. -5556.00 5567.08 SPEAKER_00 Ну немножко учтите, что этот подход противоречит тому, что после этого вы уже не выбираете хранилище, если у вас ID-шники будут генерироваться на клиенте, уже клиент выбирает в каком хранилище и как вам хранить эти ID-шники. -5567.08 5568.08 SPEAKER_01 Да. -5568.08 5583.84 SPEAKER_01 И здесь на самом деле, а еще, кстати, есть такой интересный момент, а что делать, допустим, мы используем ключи демпотенности, вы делаете пост и говорите, что сервер понимает, что ага, такой пост я уже обрабатывал. -5583.84 5587.88 SPEAKER_01 На самом деле существует два способа обработать такую штуку. -5587.88 5601.00 SPEAKER_01 Способ один — вернуть специальный что-то по коду 409, это конфликт, и в принципе вы можете вместе с этим error-кодом вернуть прошлый ответ, да, ID-шник прошлого созданного, например, созданной сущности. -5601.00 5610.32 SPEAKER_01 Таким образом клиент поймет, что ну да, он уже созданный, вот конфликт вот с этой сущностью, ага, ну то есть как бы ее мы, этот ID мы и возьмем за создание. -5610.32 5620.32 SPEAKER_01 Либо вы можете сделать вид, что вы обрабатываете этот реквест как будто в первый раз и вернуть тот же самый респонс, который вы бы вернули, если бы первый реквест не затаймаутился. -5620.32 5633.44 SPEAKER_00 Я бы тут как раз предложил обратиться к правилу, а клиенту это надо, т.е. клиенту ваши различные результаты нужны, т.е. ему важно, конфликт это или не конфликт, и в большинстве случаев ему не важно, ему нужно получить обратную сущность. -5633.44 5645.76 SPEAKER_01 Да, но с другой стороны, нагрузка, ну т.е. как бы программировать сложнее второй вариант, когда нужно получить сущность, потому что вам нужно помнить не только тот факт, что вы этот вопрос обрабатывали, а собственно и полный ответ. -5645.76 5652.72 SPEAKER_00 Ну у тебя есть ключи на импотентности, да, ты по этому ключу на импотентность должен знать, какую сущность породила этот ключ на импотентность, ну какой ответ породил. -5652.72 5653.72 SPEAKER_00 Да-да-да, какой ответ. -5653.72 5661.20 SPEAKER_00 Тут еще один интересный вопрос, ни в какой ли спецификации не сказано, сколько нужно хранить ключи на импотентности, потому что… В спеках я этого нигде не видел. -5661.20 5666.02 SPEAKER_00 Ретрай может прийти через секунду, а может через неделю прийти, и что нам делать, не вечно же их хранить? -5666.02 5675.70 SPEAKER_01 В спеках я этого не видел, Золанда, кстати, говорит, что возвращайте заголовки, где будет сказано, сколько он живет у вас. -5675.70 5680.34 SPEAKER_00 Это хорошо, если твои заголовки кто-то прочитал, а если мы говорим, что у нас оборвалась связь, и клиент ретрает. -5680.34 5685.22 SPEAKER_01 Все правда, ну я так понимаю, что какой-то стандарт я не видел. -5685.22 5691.12 SPEAKER_00 То есть тут плохо, конечно, что наши ретрай-библиотеки никак не договорились с кэширующими импотентными серверами. -5691.12 5696.76 SPEAKER_00 Было бы неплохо, какой-нибудь стандартный таймаут, после которого чувак не ретрай, не надо. -5696.76 5698.12 SPEAKER_01 Ну да. -5698.12 5701.36 SPEAKER_01 Так, что у нас ещё интересного? -5701.36 5702.92 SPEAKER_01 А вот, про глаголы. -5702.92 5711.04 SPEAKER_01 У Майкрософта есть интересная рекомендация, я ей, я бы сказал, никогда не пользуюсь, но, в принципе, подход интересный. -5711.04 5713.52 SPEAKER_01 Ажура, я так понимаю, ей пользуется всё время. -5713.52 5720.18 SPEAKER_01 Для того, чтобы вы, для создания ресурсов используете только патч или пут. -5720.18 5721.18 SPEAKER_01 Пост использовать нельзя. -5721.18 5722.80 SPEAKER_01 А почему? -5722.80 5734.66 SPEAKER_01 Ну, потому что он типа, ну у них написано, что типа may use post, если вы сделали, короче, всю импотентность, вот это всё, короче, пост не надо. -5734.66 5735.66 SPEAKER_01 А патч... -5735.66 5737.46 SPEAKER_01 Ну то есть потому, что без импотентности он по-дефритному? -5737.46 5742.78 SPEAKER_01 Да, патч тоже же без импотентности, но у патча есть несколько вариаций. -5742.78 5754.74 SPEAKER_01 Вот там вот body, который вы передаёте, он может быть разных немножко форматов, и там есть специальный тип, называется то ли мерч патч, мерч патч, по-моему, это называется, короче. -5754.74 5761.46 SPEAKER_01 Вот он как раз не будет позволять добавлению коллекции вот этого всего, и за счёт чего он становится и демпатентным. -5761.46 5762.46 SPEAKER_00 Вот. -5762.46 5767.42 SPEAKER_00 Ты говоришь про какой-то стандартный имплементатор и накатыватель патчей, да? -5767.42 5768.42 SPEAKER_01 РФЦ 5789. -5768.42 5777.10 SPEAKER_00 Нет, хорошо, а есть ли у нас в дотнете какой-нибудь классик, который возьмёт тебе патчи, поэтому РФЦ его накатит без добавлений, без ничего вот этого? -5777.10 5781.30 SPEAKER_01 Наверняка есть библиотечка, не искал, честно говоря, я говорю, что я никогда так не пользовался. -5781.30 5788.62 SPEAKER_00 Ну вот сложно, рекомендовать такие вещи, когда у тебя нет простого способа вот это заиспользовать, а у нас в индустрии пока простого способа чуть ли не полно. -5788.62 5795.26 SPEAKER_01 Но с другой стороны, разажур, как бы на этом ажур написан, в частности на шарпе местами, должно быть что-то, наверняка. -5795.26 5800.78 SPEAKER_00 Ну наверное должно, но пока оно не станет как бы стандартом везде, рассчитывать на него довольно странно. -5800.78 5805.66 SPEAKER_01 В среднем, конечно, все создают через пост, ну иногда через пуд, такое встречал. -5805.66 5810.06 SPEAKER_01 Ну в общем-то всё по методам. -5810.06 5815.98 SPEAKER_00 Смотри, я как раз больше встречал, что люди предпочитают не использовать патч, как раз таки потому, что охрень знает, как его реализовать. -5815.98 5819.98 SPEAKER_01 Да он сложный, да, и со стороны фронта в том числе, то есть непонятно как. -5819.98 5829.22 SPEAKER_01 Особенно этот стандартный патч, который там с эдремувами, он там очень хитро собирается, этот джейсончик, мы один раз делали такое, нам не понравилось. -5829.22 5841.82 SPEAKER_01 Мерч патч, он попроще, но тоже непонятно, то есть может быть действительно пока еще не появилось удобных тулов, так скажем, библиотек и всего остального. -5841.82 5854.46 SPEAKER_01 Давай дальше, по заголовкам, ШТТП заголовка имеется в виду, каких-то интересных рекомендаций нет, все говорят ну используйте стандартные, что как бы, они стандартные, не используйте. -5854.46 5868.10 SPEAKER_01 А, ну единственное, рекомендации, сейчас в РФЦ уже написано, в РФЦ специальной, в котором написано не используйте префикс x для кастомных заголовков, в долгое время считалось, что нужно все ваши кастомные заголовки начинать с символа x, то есть x-дефис и что-нибудь. -5868.10 5870.74 SPEAKER_01 Вот, последняя рекомендация говорит не надо. -5870.74 5873.10 SPEAKER_01 А что, вместо него надо? -5873.10 5884.94 SPEAKER_01 Написано в РФЦ, я РФЦ почитал, там написано, просто придумайте имя, которое наверняка, про которое вы с достаточной уверенностью можете сказать, что оно не используется, -5884.94 5885.94 SPEAKER_00 точка. -5885.94 5889.62 SPEAKER_00 Ну обычно в такие вещи вставляют или имя продукта, или имя компании. -5889.62 5890.62 SPEAKER_00 Ну да, да. -5890.62 5896.06 SPEAKER_00 Для того, чтобы можно было сразу сказать, что вот этот заголовок, он наверняка относится к этому продукту, потому что заголовков много и так далее. -5896.06 5897.06 SPEAKER_00 Всё так. -5897.06 5899.06 SPEAKER_00 Ну это примерно уникальность тебе какую-то гарантирует. -5899.06 5907.14 SPEAKER_01 Да, там в РФЦ что-то такое написано, типа company name, там что-то такое, можно, но при этом у Майкрософта все их стандартные заголовки, они xms, что-то там, но видимо -5907.14 5908.14 SPEAKER_00 исторически. -5908.14 5912.58 SPEAKER_00 Да и, насколько я помню, у всех, и у Гуглова, и у Гитхаба, как бы у всех. -5912.58 5913.58 SPEAKER_01 Да. -5913.58 5919.94 SPEAKER_01 Ну и примерно осталось два раздела, это версионирование и тот самый пейджинг. -5919.94 5920.94 SPEAKER_01 Вот. -5920.94 5927.02 SPEAKER_01 Давай про пейджинг сначала немножко, рядом с контрактом пока это самое. -5927.02 5948.50 SPEAKER_01 Значит, про пейджинг сказано следующее, что Майкрософт говорит, бывает client-сайт и server-сайт, ну то есть client-сайт это offset-base, когда вам с клиента приходит, хочу там, не знаю, пятую страницу 20 сущностей, а server-сайт это когда вы запрашиваете список, вам сервер возвращает начало этого списка и ссылочка про то, что, а продолжение вот по этой ссылке. -5948.50 5949.50 SPEAKER_01 Вот. -5949.50 5956.20 SPEAKER_01 Соответственно клиент просто запрашивает, не зная, что там дальше, сколько там будет еще страниц, не страниц и так далее. -5956.20 5971.58 SPEAKER_01 Майкрософт говорит, что ну постарайтесь никогда не отдавать total в списках, независимо от как бы пейджинга, не надо считать total, если вам очень надо, сделайте отдельный query-опцию, что типа. -5971.58 5977.66 SPEAKER_00 Слушай, ну сложно не отдавать total, когда ты первый вид используешь, когда тебе перед клиентом нужно показать количество страниц. -5977.66 5982.26 SPEAKER_01 Это правда, но тем не менее старайтесь не отдавать -5982.26 5983.26 SPEAKER_00 total. -5983.26 5984.26 SPEAKER_01 Тем не менее не отдавать, да. -5984.26 5985.26 SPEAKER_01 Да. -5985.26 5987.50 SPEAKER_01 Ну типа там, напишите, что там 1, 2, 3 и многоточие. -5987.50 5989.66 SPEAKER_01 Так а если он 1? -5989.66 5990.66 SPEAKER_01 Вот. -5990.66 6009.90 SPEAKER_01 Ну правда, я согласен, да, что скорее всего, конечно, в таком случае вы будете, но рекомендация говорит, что старайтесь избежать total, ну отправьте какой-нибудь там has_next_true, знаешь как это в итераторах C#, has_next и move_next, все. -6009.90 6010.90 SPEAKER_00 Это cursor based по сути. -6010.90 6011.90 SPEAKER_00 Да. -6011.90 6023.38 SPEAKER_00 У этих двух способов есть плюсы и минусы, да, и один как раз таки из минусов того, что тебе в принципе всегда в первом случае приходится total отправлять, но зато во втором не нужно, это его плюс. -6023.38 6034.82 SPEAKER_01 Ну и во втором вы можете, да, чуть более стабильные может быть даже результаты возвращать, если вы, например, что-то там, ну хотя в первом тоже теоретически, но… -6034.82 6039.18 SPEAKER_00 Слушай, нам по идее, мне кажется, по версионированию вообще надо отдельную статейку сделать. -6039.18 6040.18 SPEAKER_00 Давай как-нибудь, да. -6040.18 6041.18 SPEAKER_00 Отдельную тему. -6041.18 6042.18 SPEAKER_00 Не по версионированию, это pagination. -6042.18 6054.22 SPEAKER_00 По пейджингу, да, да, потому что оба этих подхода, они прям стоят того, чтобы их обсудить, плюсы, минусы и так далее, потому что там второй у него больше плюсов, но его не всегда можно сделать, там для него есть определённые хаки, в общем, хорошая тема. -6054.22 6055.22 SPEAKER_00 Да. -6055.22 6056.22 SPEAKER_01 Можно как-нибудь отдельно её сделать. -6056.22 6058.94 SPEAKER_01 Давай посмотрим потом отдельно, ну и давай про версионирование. -6058.94 6073.90 SPEAKER_01 В общем, все сходятся из тех статей, которые я читал в основном, вот крупных компаний, все сходятся к тому, что типа не надо использовать версию в Урле, ну хотя Nuget использует, например, да, там API Nuget, там v1, v2, v3. -6073.90 6076.22 SPEAKER_00 Да мне кажется, тоже все большие все используют, -6076.22 6077.22 SPEAKER_01 именно в Урле. -6077.22 6078.82 SPEAKER_01 Ну вот Microsoft не использует. -6078.82 6079.82 SPEAKER_01 Уже молодец. -6079.82 6086.26 SPEAKER_01 Да, Zalando не использует, а у Zalando вообще прикольное это самое, у них просто рекомендация, should avoid +1528.90 1541.18 "Игорь Лабутин" Дальше, deployment раздел, это, соответственно, все вот эти ресурсы, которые я перечислил, да, там, пасгрегий, ажур и так далее, должны быть в состоянии задеплоины куда-либо. +1541.18 1545.02 "Игорь Лабутин" Ну, понятное дело, что в ажур, это однозначно. +1545.02 1564.58 "Игорь Лабутин" Дальше у них написано, что должен быть CI/CD scaffolding, ну, короче, command-line tool, который позволит тебе из, ну, как бы, из твоего аспайровского описания, да, которое пишется на C#, я напомню, сгенерить GitHub action, который тебе потом это всё будет собирать уже в CI где-то там. +1564.58 1580.10 "Игорь Лабутин" Ну и поддержка Kubernetes, есть отдельный комьюнити-проект Aspirate называется, он, соответственно, как раз умеет преобразовывать эти аспайровские манифесты из кода в нормальные, так сказать, скрипты для кубера, чтобы туда задеплоить. +1580.10 1601.42 "Игорь Лабутин" Tooling, ну, Visual Studio, понятное дело, Visual Studio Code обещают, и обещают тот самый scaffolding не только в виде command-line, но и в виде какой-то Visual Studio приблуды, я уж не знаю, плагин или нативная функциональность, тут уж я не знаю, ну, короче, какой-то tooling вокруг Visual Studio, Visual Studio кода. +1601.42 1613.14 "Игорь Лабутин" Есть ещё такой интересный раздел, называется top requests at end-to-end scenarios, то есть это, я так понимаю, те сценарии, где либо больше всего народу проголосовало, либо какие-то заказчики к ним пришли и сказали, что вот это точно надо. +1613.14 1633.58 "Игорь Лабутин" Они все в основном, конечно, крутятся вокруг ажура, то есть там я хочу коннектироваться к ремоутному ажурному ресурсу из своего девелоперского окружения, я хочу брать секреты, которые проставлены в моих ажурных ресурсах и прокидывать их локальным приложением, там через User Secrets или как-то. +1633.58 1649.14 "Игорь Лабутин" Но есть и те, которые не относятся к ажуру, например, давайте поддержите докер в VSL, чтобы можно было видимо туда там деплойт, не знаю, не деплойт, типа, в, тоже локально, но такой типа, а-ля, локальный кубер. +1649.14 1667.90 "Игорь Лабутин" Хочется уметь возможность оркестрировать, ну вот это как раз история с декаплингом, несколькими репозиториями, то есть сейчас Spyre предполагает, что у тебя монорепа, грубо говоря, в которой, ну плюс-минус, да, дефолтный сценарий, в который ты референсируешься на другие проекты, то есть не только монорепа, но еще и сингл солюшен, по большому счету. +1667.90 1677.02 "Игорь Лабутин" Ну, это понятно, что первый превью, и это самое простое, что можно было сделать, но вот end-to-end сценарий, так что можно было вообще с несколькими репозиториями работать, тоже нормально. +1677.02 1686.10 "Игорь Лабутин" Из того, что явно написано, что out-of-scope, точно не будет поддержан никакой там AWS, Google Cloud, не будет поддержан Azure Kubernetes. +1686.10 1691.18 "Анатолий Кулаков" Слушай, а почему это out-of-scope, если ажура поддерживается, ну то есть кажется одного полиягоди? +1691.18 1702.50 "Игорь Лабутин" Там чуть-чуть разные, так скажем, видимо какие-то, ну не знаю, в мелочах требования, не знаю, вот, поэтому, ну вот пока не поддержан, out-of-scope, просто видимо ресурсов не хватит. +1702.50 1708.74 "Анатолий Кулаков" Ну хорошо, ну так мы написали, что ресурсов не хватит, типа делайте сами, но мне кажется, что это out-of-scope. +1708.74 1709.74 "Игорь Лабутин" Нет, стоп. +1709.74 1729.94 "Игорь Лабутин" Ну так они это и написали, out-of-scope, это в смысле наша команда этим не будет заниматься, то есть это scope команды, которые они планируют, что Microsoft планирует официально зарелизить в первом релизе, но out-of-scope Microsoft не планирует, как бы запрещать, никто не запрещает, пожалуйста, делайте что хотите, но как бы Microsoft это делать не планирует, +1729.94 1735.66 "Анатолий Кулаков" и это не только… Я думал, что это out-of-scope именно самого проекта, то есть проект под это не предназначен. +1735.66 1767.50 "Игорь Лабутин" Это first-release scope, напоминаю, все, что мы обсуждаем, это scope первого релиза, будет он как бы вместе с девяткой в ноябре, будет он раньше, будет он отдельно, как версионируется этот продукт пока тоже не очень понятно, ну вроде бы логично его привязать, наверное, к релизам дотнета, но с другой стороны, если они планируют это делать как отдельный стендаловый продукт под другие платформы тоже, то зачем привязывать, может быть они там летом его зарелизят, я не знаю, но вот это как раз таки все то, что я перечислял, это то, что должно войти в первый релиз. +1767.50 1808.60 "Игорь Лабутин" Так вот, то, что ты говоришь, если поддерживать ажуру, в первый релиз out-of-scope не только ажура, ой, в смысле AWS там, Google Cloud, но еще и Azure Kubernetes и Azure Functions, это все тоже не будет поддержано, то есть даже если у тебя есть проект, напоминаю, в студии ты можешь создать проект Azure Functions и довольно легко там в пару кликов его деплоить в ажуру, Aspire такого поддерживать пока не будет, ну, видимо, не успевают, вот, ну либо просто сознательно ограничивать на самом деле, может быть это тоже правильно, сознательно ограничить себе scope первой версии, сделать его, ее, его scope версию и зарелизить, посмотреть на фидбэк и дальше выбирать следующее, наиболее важное. +1808.60 1834.48 "Игорь Лабутин" Ну, в общем, примерно так, соответственно, в ссылочках будет и ссылка на pull request, где отрезали дэшборд и он теперь standalone, можно посмотреть, может быть там уже что-то появилось где-нибудь или в связанных ишах написана какая-нибудь документация, или, можно сказать, в pull request она прямо есть, я не посмотрел, вот как этим пользоваться, так что если у кого-то руки дойдут, попользуйтесь, расскажите, как он там standalone работает, у меня пока не дошли, честно говоря. +1834.48 1838.72 "Анатолий Кулаков" Угу, ну и мы будем следить за статейчиками, если появятся, обязательно расскажем. +1838.72 1841.64 "Игорь Лабутин" Ну, конечно, проще прочитать, чем самому сделать, так +1841.64 1842.64 "Анатолий Кулаков" что. +1842.64 1843.64 "Анатолий Кулаков" Это да. +1843.64 1850.76 "Анатолий Кулаков" Кстати, вот проще как раз было дождаться, пока кто-то найдет замещение байна реформатору, чем сделать его самому. +1850.76 1863.84 "Анатолий Кулаков" Давай, следующая статейчика как раз про то, что один дяденька загнался тем, что начал скучать по байна реформатору, ну, у него в проекте он просто использовался, а он захотел перебежать на последний фреймворк и сильно загрустил. +1863.84 1893.38 "Анатолий Кулаков" Давай для, как раз для молодежи вспомним, что в старинных версиях дотнет фреймворка много-много тысяч лет назад была такая прекрасная штука, как байна реформатор, и отличалась она от вот этих ваших новомодных JSON-сериалайзеров тем, что паковала, не поверите, в байнаре, то есть по сути в нечитабельную кашу из битиков и байтиков, которую естественно неудобно было дебажить и смотреть на нее глазками. +1893.38 1897.04 "Анатолий Кулаков" Но у байна реформаторов есть другой прекрасный плюс. +1897.04 1901.00 "Анатолий Кулаков" Они намного быстрее всегда и намного компактнее. +1901.00 1909.48 "Анатолий Кулаков" И обычно, когда мы говорим о сериализации, это два очень весомых плюсика, которые в принципе вполне могут перебить любой текстовый сериализатор. +1909.48 1914.76 "Анатолий Кулаков" Так вот, был у Микрософта байна реформатор рядом с XML-форматором вообще самых первых его версий. +1914.76 1918.48 "Анатолий Кулаков" Потому что JSON-а не было, а байнаре XML был всегда. +1918.48 1928.04 "Анатолий Кулаков" И сериализовали, сериализовали люди с помощью него и постепенно поняли, что в принципе реализация этого байна реформатора была слишком мощная. +1928.04 1935.32 "Анатолий Кулаков" Она могла делать такие страшные вещи, что даже которые выходили за уровень ее декларируемых фич. +1935.32 1962.76 "Анатолий Кулаков" То есть, допустим, с помощью байна реформатора, если у вас вдруг торчит какой-нибудь endpoint, VCF-endpoint или HTTP-endpoint, не суть важно, или сигнал-эр-эндпоинт, который принимает внутрь себя некий пакет, который десяти реализуется с помощью байна реформатора, то очень часто вы можете благодаря такому endpoint выполнить произвольный код на удаленном сервере. +1962.76 1966.80 "Анатолий Кулаков" То есть, с байна реформатором очень много было о секьюрити проблем. +1966.80 1987.24 "Анатолий Кулаков" Кому интересно, можно отдельную статейку почитать, но смысл как раз в том, что от него начали отказываться, наверное, не в основном по этой причине, это была причина главная, но как бы, понимаете, обычно программистам на секьюрити плевать, поэтому программисты начали от него отказываться, потому что он был не очень удобный, у него было много багов, он был очень медленным и прочие такие рюшечки. +1987.24 2004.40 "Анатолий Кулаков" Но на самом деле, самая главная была причина для того, чтобы от него начать отказываться, и чтобы Микрософт его специально больше не развивал, специально не латал никакие-нибудь проблемы, это как раз в том, что сама концепция была очень сильно подвержена различным секьюрити атакам. +2004.40 2018.80 "Анатолий Кулаков" И начиная с DotNet 7, этот байна реформатор был помечен как абсолют, при том на уровне ERROR, т.е. вы не могли скомпилить ваш проект, если вдруг почему-то использовали его до сих пор. +2018.80 2023.12 "Анатолий Кулаков" Вот и автор наткнулся на этот ERROR и решил посмотреть, а что же такого есть на рынке. +2023.12 2028.40 "Анатолий Кулаков" И прошло как бы 10 лет, как он решил отойти от байна реформатора. +2028.40 2036.28 "Анатолий Кулаков" Ну, прежде всего, все микрософтовские статьи советуют переходить почему-то на текстовые форматы в виде JSON, т.е. +2036.28 2056.32 "Анатолий Кулаков" System Text JSON, раньше до этого рекомендовали Newton Soft JSON, но выглядело для всех это довольно странно, потому что никто с драмами твердой памяти после бинарного форматора, если бы, конечно, бинарный форматор был выбран явно, никто не пойдет на JSON, потому что это всегда медленно, много и т.д. +2056.32 2069.64 "Анатолий Кулаков" Дальше пошли смотреть на байна реформатор, также ему приглянулся Protobuf, но Protobuf требует кучу приседаний, кучу настроек, конфигурации, объявления протокола и, в общем, ему это показалось слишком сложно все. +2069.64 2076.92 "Анатолий Кулаков" Поэтому Protobuf он скипнул и дошел до, наверное, самой очевидной вещи, на которую должен был дойти каждый, это MessagePack. +2076.92 2086.64 "Анатолий Кулаков" MessagePack - это прекрасный сериализатор, он байнарий сериализатор, он намного быстрее, чем JSON и он намного компактнее, чем JSON. +2086.64 2101.92 "Анатолий Кулаков" Другая прекрасная новость заключается в том, что этот MessagePack разрабатывается организацией, которая называется SciSharp и человеком, который сложно произносимым ником на GitHub'е не Uytsk, Yoshimi Kawai. +2101.92 2109.64 "Анатолий Кулаков" Короче, чувак довольно со сложным именем, но если вы там увидите его иконку или увидите этого чувака, вы его запомните навсегда. +2109.64 2118.32 "Анатолий Кулаков" По той простой причине, что это очень грамотный человек, который реализовал уже кучу сериализаторов, кучу парсеров. +2118.32 2125.84 "Анатолий Кулаков" У него отличные in-memory embedded базы данных есть, у него есть там какие-то генераторы каких-то оптимизаций. +2125.84 2135.24 "Анатолий Кулаков" В общем, это человек, который очень хорошо соображает в оптимизациях, пишет хороший код, качественный API и поддерживает свой продукт довольно хорошо. +2135.24 2146.68 "Анатолий Кулаков" Поэтому MessagePack является одним таким и сразу дефолтным сериализатором, если вам нужен хороший, надежный, компактный, быстрый binary-series сериализатор. +2146.68 2163.52 "Анатолий Кулаков" Про MessagePack мы уже говорили в нашем подкасте, и эта статья никогда не попала бы к нам в выпуск, если бы автор не пошел немножко дальше и нашел следующий проект вот этого товарища Kawai, который называется MemoryPack. +2163.52 2167.72 "Анатолий Кулаков" И вот про MemoryPack мы еще не разговаривали, поэтому стоит его осветить. +2167.72 2183.52 "Игорь Лабутин" Но подожди, подожди, на самом деле, когда он только-только появился, про MemoryPack мы говорили, мы про него… была у нас новость, по крайней мере, про то, что вот вышла такая штука, она типа супероптимизированная, все дела, но это было что-то год назад. +2183.52 2187.80 "Игорь Лабутин" Я не знаю, насколько он с тех пор развивался, поэтому современная статья будет точно полезна. +2187.80 2188.80 "Анатолий Кулаков" Давай, да. +2188.80 2195.60 "Анатолий Кулаков" Да, наверное, когда он появился, может, и говорили, но опять же, в чем его плюсы? +2195.60 2219.12 "Анатолий Кулаков" Плюс его заключается в том, что он использует и сразу писался на .NET 7 и C# 11, это значит, что он заюзал все возможные оптимизации, которые там ввели, а там, напомню, их было очень много, iBuffer Writer, Span, Read-only Sequence, Read-only Span, PipeWriter, PipeReader, короче, вот эти все-все-все, что только можно было. +2219.12 2222.56 "Анатолий Кулаков" Вот он их очень плотненько заюзал, и это там как бы основная его концепция была. +2222.56 2239.56 "Анатолий Кулаков" Это такая библиотека для Zero Encoding Extreme Performance Binary Serializator, т.е. основная его фишка в том, что он не пытается выдумать какой-то формат и в этот формат что-то записать, как делают другие сериализаторы. +2239.56 2253.12 "Анатолий Кулаков" Он просто берет бинарный dump C# элемента, т.е. C# примитива типа, допустим, Int, и берет этот бинарный поток и просто-напросто записывает его в свой output формат. +2253.12 2254.12 "Анатолий Кулаков" Вот как бы и все. +2254.12 2261.70 "Анатолий Кулаков" Сериализация происходит таким же точным образом, просто-напросто массив byte замещается там, где он должен быть, и это позволяет ему как раз-таки достичь высокой скорости. +2261.70 2274.28 "Анатолий Кулаков" Как я уже, наверное, упомянул, что одно из самых больших прелестей этого проекта в том, что он поддерживается товарищем Kawai'em, который написал уже кучу сериализаторов, в частности, кстати. +2274.28 2284.60 "Анатолий Кулаков" ZeroFormator делая его рук, UTF-8 JSON, это был самый быстрый JSON сериализатор на тот момент, и MessagePack тоже поддерживается им. +2284.60 2290.92 "Анатолий Кулаков" И вот весь опыт он собрал, который он делал с сериализаторами, плюс у него там, как я уже говорил, много других крутецких проектов есть. +2290.92 2294.88 "Анатолий Кулаков" Кстати, если вы не видели его репозиторию, обязательно загляните и посмотрите. +2294.88 2298.08 "Анатолий Кулаков" Там много всего интересного можно найти абсолютно на любой вкус. +2298.08 2307.28 "Анатолий Кулаков" И вторая фишка после того, что он юзает самые последние структуры, которые появились для перфоманса, он полностью написан на source-генераторах. +2307.28 2312.76 "Анатолий Кулаков" Это привело к тому, что у него появились дополнительные плюшки, которые дает source-генераторы. +2312.76 2315.80 "Анатолий Кулаков" Мы их много раз обсуждали, но в данном разделе не грех и повториться. +2315.80 2326.28 "Анатолий Кулаков" Это значит, что он очень дружественно настроен к native auto, т.е. к триммингу, к оптимизациям и к прочим вот этими вещам. +2326.28 2343.88 "Анатолий Кулаков" У него отсутствует полностью рефлекшн, т.е. у него имплементация с помощью рефлекшна, т.е. весь API сделан на source-генераторах, и это ему как раз таки позволяет хорошо и триммиться, и хорошо аутиться, и хорошо и быстро запускаться под всякие оптимальные платформы. +2343.88 2373.48 "Анатолий Кулаков" Из фишек еще у него можно диссерилизовать существующий инстанс, полиморфная диссерилизация, у него также есть TypeScript код-генератор, т.е. вы можете диссерилизовать вот этот формат не только в C#, но и в TypeScript, ну не только в дотнете, но и в TypeScript, поддержка Unity, поддерживается очень много, широкий пласт вообще всех типов, т.е. не только какие-то примитивы, но и листы, и dictionary, и mutable коллекции, и много-много всего того, чего не поддерживают обычные нормальные сериализаторы. +2373.48 2398.36 "Анатолий Кулаков" Также есть у него специальный режим терпимости, где он может немножко ослабить свои требования к структуре ваших DTO-шек, он может позволить вам их немножко добавлять поля, переименовывать поля, но при этом диссерилизоваться это будет немножко медленнее, но если вы гарантируете, что ваши DTO-шки не изменились, там скорость вылетает просто в космос. +2398.36 2411.48 "Анатолий Кулаков" Также у него есть поддержка Brotli, это специальный компрессор, т.е. можно вот этот весь бинарный поток, который он наделал, в то же время еще и посжимать, т.е. мало того, что он компактный сам по себе, еще и можно сжать. +2411.48 2415.68 "Анатолий Кулаков" И все эти ухищрения дали, в принципе, немаленькие результаты. +2415.68 2425.28 "Анатолий Кулаков" Прежде всего, если сравнивать с binary-форматором, который я уже упоминал, он мега медленный был, допустим, на бенчмарках он показал 27 попугаев, там 27 нс. +2425.28 2430.84 "Анатолий Кулаков" Newtonsoft у нас было сразу 7 нс и System Tech JSON – 5 нс. +2430.84 2439.20 "Анатолий Кулаков" Немножко возвращает нас к той мысли, которую мы уже упоминали в прошлых подкастах, что в принципе Newtonsoft написан с точки зрения перформанса довольно хорошо. +2439.20 2450.12 "Анатолий Кулаков" Смотрите, у него 7 нс, а System Tech JSON, который Microsoft вкладывает все силы много последних лет, это 5 нс, т.е. не сильно быстрее, если уж на то пошло. +2450.12 2457.40 "Анатолий Кулаков" Ну и наши лидеры – это MessagePack – 2 нс, и MemoryPack добился 1 нс на тех данных, которые там бенчмаркались. +2457.40 2471.20 "Анатолий Кулаков" На каких-то синтезированных обычных примерах с кучей массивов, с какими-то огромными объектами, автор заявляет, что MemoryPack в 200 раз может быть быстрее любого из существующих сервизаторов. +2471.20 2474.52 "Анатолий Кулаков" В общем, такой вот интересный наборчик. +2474.52 2482.68 "Анатолий Кулаков" Из минуса, наверное, MemoryPack'а можно отметить то, что он будет работать между .NET-приложениями и TypeScript-овым приложением. +2482.68 2493.28 "Анатолий Кулаков" Да, если вам нужна все-таки кросс-языковая какая-то сериализация между Python, Perl, JavaScript, Yava и т.д., то ваш выбор тогда MessagePack. +2493.28 2499.00 "Анатолий Кулаков" Это такой же бинарный сериализатор, но поддерживается практически во всех существующих языках программирования. +2499.00 2505.88 "Анатолий Кулаков" В общем, если вам нужна максимальная перформанс и максимальная утилизация памяти, то взгляните на MemoryPack. +2505.88 2523.44 "Игорь Лабутин" Ну и надо понимать, что вся эта магия перформанса нужна вам, скорее всего, именно с учетом всех тех проблем и ограничений, которые доставит MemoryPack, она нужна, конечно, только если у вас прям совсем-совсем все жестко по ресурсам. +2523.44 2532.80 "Игорь Лабутин" И именно поэтому, на самом деле, вот этот автор и пишет всякие такие быстрые сериализаторы туда, быстрые сериализаторы сюда, потому что они занимаются, на самом деле, разработкой игр. +2532.80 2548.56 "Игорь Лабутин" И в играх понятно, что чем меньше вы потратили ресурсов на один там, на отрисовку одного фрейма или на обсчет одного там типа цикла игры, тем лучше, тем плавнее все будет, тем эффективнее и так далее, тем больше можно считать. +2548.56 2551.72 "Игорь Лабутин" И именно поэтому у него такие довольно ограниченные штуки. +2551.72 2555.48 "Игорь Лабутин" Ну и почти все его проекты поддерживают Unity, как-то неудивительно. +2555.48 2557.68 "Анатолий Кулаков" Да, что якобы намекает. +2557.68 2558.68 "Анатолий Кулаков" Да, да. +2558.68 2564.92 "Игорь Лабутин" Не, ну их на самом деле прямо у организатора C# записано, что они типа Unity, game, что-то там. +2564.92 2569.40 "Игорь Лабутин" Так что это прям, очень прям, прям тем текстом написано. +2569.40 2574.80 "Анатолий Кулаков" Ну то есть, если на ваших формочках вам нужно клик от кнопочки отработать, то это, естественно, подход не для вас. +2574.80 2576.36 "Анатолий Кулаков" Джессона вам хватит за головой. +2576.36 2584.00 "Анатолий Кулаков" А вот если вам нужно там утилизировать сетку очень сильно, у вас огромные блобы там летают, вот это вот тогда бинарь сериализаторов придет к вам очень быстро. +2584.00 2586.52 "Игорь Лабутин" Да, начните, наверное, с message пака, мне кажется. +2586.52 2589.84 "Игорь Лабутин" Если уже будет не хватать, тогда можно идти в memory pack. +2589.84 2595.04 "Игорь Лабутин" Ну, довольно специфический, так скажем, для очень узких ниш. +2595.04 2596.04 "Игорь Лабутин" Давай дальше. +2596.04 2604.00 "Игорь Лабутин" Дальше у нас тема, которую мы на самом деле долго-долго откладывали, потому что она довольно-таки большая. +2604.00 2613.12 "Игорь Лабутин" Там много чего можно смотреть, можно обсуждать, можно, наверное, несколько подкастов записать только на эту тему, но тем не менее, решил, что все-таки хватит откладывать, надо про это поговорить. +2613.12 2616.84 "Игорь Лабутин" Тем более, мне этот случай удачный выдался, все равно почитать все эти статейки. +2616.84 2628.44 "Игорь Лабутин" Речь идет о том, как же дизайнить, версионировать и вообще проектировать, дизайнить, проектировать, ну, в общем, одно и то же REST API. +2628.44 2629.88 "Игорь Лабутин" Масштабно замахнулся, масштабно. +2629.88 2630.88 "Игорь Лабутин" Масштабно. +2630.88 2706.32 "Игорь Лабутин" У нас в ссылочках к этому выпуску вы найдете довольно большое количество материалов на эту тему, есть огромный курс от, ну, не курс, а такой плейлист от Джеффри Рихтера, где он подробно объясняет, как Microsoft и Azure командов в частности подходят к этому вопросу, есть плюс-минус текстовая версия этих гайдлайнов, которая, понятно, я не знаю, насколько Рихтер обновляет свои видео, но гайдлайны видимо свои, они обновляют чуть быстрее, есть огромный, прямо такой монструозный, я бы даже сказал, труд от компании Золанда, у них прямо огромные гайдлайны на их open source портале, ну и есть еще ряд статей от всяких разных более или менее известных товарищей на тему, всяких разных их мыслей о том, как дизайнить правильно REST API, я попробовал это все разнести немножко по, во-первых, я попробовал все это прочитать, прочитал, ну не все, наверное, но большую часть из этого, во-вторых, я выделил для себя какие-то интересные моменты и те, которые, ну, я бы сказал так, наиболее часто возникают споры о них, либо может быть действительно какие-то неочевидные рекомендации, там есть несколько неочевидных рекомендаций, которые я, например, о которых я не задумывался. +2706.32 2710.60 "Игорь Лабутин" Точнее, я про них слышал, но как-то на автомате делаешь по-другому. +2710.60 2711.60 "Игорь Лабутин" Вот. +2711.60 2719.60 "Игорь Лабутин" Ну и вот мы пройдемся по ним, сколько успеем, не знаю, довольно много всего, ну и просто обсудим, кто что на эту тему думает. +2719.60 2723.80 "Анатолий Кулаков" Может, нам стоило каждую секцию поделить на отдельную там статью? +2723.80 2730.60 "Игорь Лабутин" Ой, нет, слушай, обсуждать кучу выпусков подряд одно и то же мне не нравится, вот мы сейчас быстренько пробежимся. +2730.60 2747.24 "Игорь Лабутин" Если есть какие-то моменты по дизайну REST, которые остались не освещенными, но вам очень интересно узнать наше мнение, приходите в комменты, пишите в комментах на YouTube, и мы, если там будет очень нужен развернутый ответ, мы включим следующий выпуск, никаких проблем. +2747.24 2748.92 "Игорь Лабутин" Материалы у нас есть. +2748.92 2755.04 "Анатолий Кулаков" Хорошая идея, если даже есть, присылайте ссылочки, статейки, видео, посмотрим, тоже обсудим. +2755.04 2764.12 "Игорь Лабутин" Ну да, если есть что-то, вот я проектирую API только вот так, согласно этой статье, никак иначе все остальные не правы, засылайте, мы почитаем, скажем, правы вы или нет. +2764.12 2766.68 "Игорь Лабутин" В нашем веским мнении, ну ладно. +2766.68 2780.28 "Игорь Лабутин" Смотри, начнем мы с простого, с принципов, то есть когда мы говорим, а давай мы спроектируем REST API, не секрет, что каждый понимает под этим нечто свое, вот. +2780.28 2850.80 "Игорь Лабутин" Рандомная статья из интернета, вот буквально мне просто попалось что-то типа несколько дней назад статейка из интернета с неплохим набором, с моей точки зрения, рекомендаций, говорит о том, что ну вообще подавляющее большинство народу считает за REST API, считает просто любой HTTP API, где как бы в урлах не глаголы, а существительные, вот если у тебя там плюс-минус HTTP API, плюс-минус используется там get, post, что-нибудь, и в урле у тебя не там create что-нибудь, а все-таки имена существительные, то есть каких-то ваших доменных объектов, сущностей, то все, это уже как бы REST, там 90% пользователей, которого вы спросите, скажут, да это же конечно же REST, вот, это с одной стороны, с другой стороны есть компания Zalando, которая говорит, нет, вот должен быть REST level какой-то там 2, да, самый крутой, 3 должен быть, короче, ссылки во все поля, значит, любой ответ должен подразумевать, вы можете из него куда-то уйти, в общем, вот это все. +2850.80 2862.68 "Анатолий Кулаков" Ну подожди, тут как бы, мне кажется, это непротиворечивая вещь, если Zalando понимает, что есть REST level 3, а другие люди понимают, что есть level другие, то как бы это все покрывает. +2862.68 2867.32 "Игорь Лабутин" Ну, если подходить к этому вопросу академически, я с тобой соглашусь. +2867.32 2871.96 "Игорь Лабутин" На практике, если ты говоришь, о, это REST API, то себе не +2871.96 2872.96 "Анатолий Кулаков" так. +2872.96 2873.96 "Анатолий Кулаков" Технически, конечно, это REST API, почему же нет. +2873.96 2879.36 "Игорь Лабутин" Да, технически это REST API, но если ты спрашиваешь о какой-то level, он на тебя посмотрит и скажет, что? +2879.36 2881.44 "Игорь Лабутин" Ну, не все, конечно, но многие. +2881.44 2883.60 "Анатолий Кулаков" Ну, тогда, наверное, стоит осветить, что это за левелы +2883.60 2884.60 "Игорь Лабутин" такие. +2884.60 2890.44 "Игорь Лабутин" Ну, можно осветить, да, у нас есть нулевой, вот я сейчас, кстати, не помню, определялся ли в диссертации нулевой level. +2890.44 2891.44 "Игорь Лабутин" Да, есть. +2891.44 2905.16 "Анатолий Кулаков" Ну, прежде всего, это называется, схема, если вы вдруг захотите найти, это Richardson maturity model, т.е. это модель того, насколько у вас REST-овый, так сказать, и он имеет как раз 4 level, от 0 до 3. +2905.16 2909.44 "Игорь Лабутин" Ну, как настоящий программист писал, не с первого почитай, а от 0 до 3. +2909.44 2919.08 "Анатолий Кулаков" Ну да, оно здесь подходит просто, потому что ибо 0, это называется вообще болото, это самое примитивное, что можно представить на нулевом уровне в виде REST. +2919.08 2921.76 "Анатолий Кулаков" А я даже не помню, по-моему, нулевое же вообще не определяется. +2921.76 2931.80 "Анатолий Кулаков" Не, нулевое определяется, нулевое – это когда у вас есть один endpoint, у вас есть один метод, и вы все возможные реквесты и респонсы постите в один этот метод. +2931.80 2934.32 "Анатолий Кулаков" Ну, т.е. чтобы вы понимали… Ну, т.е. нет. +2934.32 2938.68 "Анатолий Кулаков" Это модный GRPC, GRPC – это отстойное болото, которое считается самым простым. +2938.68 2941.56 "Игорь Лабутин" Не, погоди-погоди-погоди, ты путаешь, не GRPC, а GravQL. +2941.56 2947.44 "Анатолий Кулаков" А, GravQL, точно, вот, GravQL – это болото, которое в нормальном ресте даже произносить слух страшно. +2947.44 2950.04 "Игорь Лабутин" Я тебе более того скажу, там еще и пост всегда. +2950.04 2954.12 "Анатолий Кулаков" Ну вот, один единственный метод, один единственный endpoint, это называется болото. +2954.12 2967.16 "Игорь Лабутин" Да, значит, потом есть REST-1, когда вы начинаете разносить по урлам разным хотя бы, а потом есть REST-2, там добавляются уже глаголы HTTP, т.е. там GET, PUT, PORT, DELETE. +2967.16 2986.44 "Анатолий Кулаков" Ну и ресурсы тоже уже на REST-2 добавляются, ресурсы, т.е. вы не просто обзываете, как вам в голову придет, т.е. не гуидами у вас теперь урлы называются, а как-то вменяемо, типа что у вас шоп, карты, мы положили товар в корзину и так далее, т.е. пытаетесь как-то натянуть это все. +2986.44 3032.24 "Игорь Лабутин" Да, а есть еще REST-3, и это, соответственно, уже больше про, это называется еще одним модным словом hypermedia, это когда вы в ответах на все ваши запросы, помимо собственно самой сущности, ну, т.е. например, какой-нибудь GET там, не знаю, тот самый шоп, ну, карт, да, по водичнику, т.е. получить корзину, вы помимо этого сразу в ответе не только содержимое корзины отдаете, но еще и набор мета-информации, т.е. ссылочек, что вы можете с этим сделать, т.е. например, вам очистить корзину или еще что-то сделать, и соответственно, вам не нужно, по сути, идти в документацию, вы можете посмотреть на ответ и знать полный перечень того, что можно сделать из этой ситуации с этим объектом, согласно тому состоянию, в котором этот объект находится. +3032.24 3037.44 "Анатолий Кулаков" Как-то так, вот The Lambda как раз за последний. +3037.44 3039.24 "Анатолий Кулаков" Прямо за третий, да? +3039.24 3043.28 "Игорь Лабутин" Да, ну, т.е. они сказали, он должен быть truly RESTful, вот это все. +3043.28 3047.12 "Анатолий Кулаков" Тут нужно просто упомянуть, что до последнего доходят не все. +3047.12 3059.32 "Анатолий Кулаков" Ну, т.е. обычно нормальные компании, нормальные люди останавливаются на втором левеле и считают, что если они там глаголы определили, ресурсы определили, и там эти ответы тоже, http-коды заиспользовали, то в принципе этого достаточно. +3059.32 3061.40 "Анатолий Кулаков" Ну, и это, наверное, в 80% случаях правда. +3061.40 3065.72 "Анатолий Кулаков" Ну, т.е. если вы идете дальше, все-таки вам нужна гибкая система. +3065.72 3071.68 "Анатолий Кулаков" Ну, если вспомнить, какие у нас команды вообще дошли публичные до третьего левела, их можно посчитать там по пальцам. +3071.68 3078.28 "Анатолий Кулаков" Я вот, на вскидку, знаю, у GitHub есть третий левел, у Vimeo есть в API третий левел, вот это что сразу в голову +3078.28 3079.28 "Игорь Лабутин" пришло. +3079.28 3080.28 "Игорь Лабутин" Ну, вот и, похоже, у Zalando. +3080.28 3086.28 "Игорь Лабутин" Я не пользовался, т.е. я не могу сказать, насколько они действительно соответствуют, но это же, опять же, гайдлайнс, да? +3086.28 3091.52 "Игорь Лабутин" Не факт, что их API написан полностью согласно гайдлайнам у всех сервисов у них, я не знаю, десятки, сотни сервисов. +3091.52 3102.04 "Анатолий Кулаков" Не, я видел много этих лекций от Zalando, они очень много клевых практик используют, очень любят про них разговаривать, поэтому на разных конференциях это всегда одни из самых интересных спикеров. +3102.04 3104.60 "Анатолий Кулаков" И, вроде, да, у них на практике все это используется. +3104.60 3113.12 "Игорь Лабутин" Я, когда мы говорим про REST Level 3, вот с этими самыми ссылочками, которые возвращаются в ответе, я не очень понимаю, зачастую, что с ними делать на клиенте. +3113.12 3122.68 "Игорь Лабутин" Это очень красиво, что сервер так про себя все рассказал, а вот далеко не всегда понятно, насколько умный должен быть клиент, чтобы с этим точно так же работать. +3122.68 3134.08 "Игорь Лабутин" Потому что в большинстве случаев все-таки, все-таки, у нас редко строится продукт по принципу, что вот тебе вернули сущность, и мы понятия не имеем, что с ней можно делать. +3134.08 3143.38 "Игорь Лабутин" В среднем у тебя есть какой-то бизнес-воркфлоу, который тебе нужно сделать, и тебе, в принципе, тебе достаточно понять, можно или нельзя, а не то, что все возможные вещи, которые можно. +3143.38 3147.80 "Игорь Лабутин" Не знаю, я вот как-то, у меня не было опыта именно с клиентской стороны общения с REST Level 3. +3147.80 3155.76 "Анатолий Кулаков" Ну, именно поэтому, как бы, немногие компании такой запрос делают, потому что у них обычно очень узкий API, и ты там понимаешь, что ты хочешь делать. +3155.76 3163.92 "Анатолий Кулаков" Для примера, чтобы вы понимали, что такое Hypermedia Controls, вот этот REST Level 3, вы можете вспомнить обычный HTML. +3163.92 3169.36 "Анатолий Кулаков" Вот в обычном HTML как раз на 100% реализован Level 3. +3169.36 3172.80 "Анатолий Кулаков" Несмотря на то, что это не API, как бы, но смысл в нем точно такой же. +3172.80 3182.88 "Анатолий Кулаков" То есть, когда браузер загружает вам сайт, он понятия не имеет, какие на этом сайте есть экшены, то есть, какие, например, он должен дернуть URL для того, чтобы залогиниться. +3182.88 3193.32 "Анатолий Кулаков" Но он знает, что есть некая кнопочка, и при нажатии на этой кнопочке нужно пойти на какой-то URL, и он понятия не имеет, что этот URL делает. +3193.32 3195.64 "Анатолий Кулаков" Вот это и есть как раз Hypermedia Controls. +3195.64 3207.80 "Анатолий Кулаков" То есть, когда вы не сообщаете вашему UI, что товарищ UI-щик, когда нажмется кнопочка, дерни вот этот метод создания юзера, потом перейди на другую страничку, там отвалидируй результат и покажи его в окошке. +3207.80 3214.28 "Анатолий Кулаков" Вот когда вы ему это не говорите, а вы говорите, что товарищ UI-щик, вот я дал тебе API, в этом API будет специальный URL. +3214.28 3219.24 "Анатолий Кулаков" В этом URL будет специальная ссылка, которая называется Create User. +3219.24 3225.52 "Анатолий Кулаков" Вот ее надо показать на вот этой кнопочке, и к этой кнопочке привязывать вот это поле, куда пользователь введет там свое имя, допустим. +3225.52 3227.32 "Анатолий Кулаков" И когда он ее нажмет, просто вызови URL. +3227.32 3243.24 "Анатолий Кулаков" Что будет происходить дальше, мы тебе сообщим в ответе, и там тебе разложим экшены, которые можно будет сделать с этим новым юзером, отредактировать его, удалить, установить какой-то новый пароль, в общем, все это пришлется в виде списка экшенов, но не за хардкоженную UI. +3243.24 3244.24 "Анатолий Кулаков" Вот. +3244.24 3245.24 "Анатолий Кулаков" А теперь мы возвращаемся. +3245.24 3247.28 "Анатолий Кулаков" В принципе, представьте браузер себе, вот обычно. +3247.28 3252.24 "Анатолий Кулаков" У браузера как раз не за хардкоженые ни кнопки, ни менюшки, ничего, он все забирает из себя с сервера. +3252.24 3259.16 "Игорь Лабутин" То, что я говорил, то, что это называется словом гипермедиа, вспоминаем, что HTML, да, это гипертекст, ровно оно. +3259.16 3261.68 "Игорь Лабутин" А ссылки – это гиперссылки, на самом деле. +3261.68 3287.52 "Игорь Лабутин" То есть просто в мире современного победившего SPA, да, Single Page Applications, тот факт, что ты послал запрос на сервер про логин, означает, что сервер там что-то свое делает и когда-нибудь вернет ответ, а ты уже там это, перемалываешь какую-то логику на клиенте, который там покажет какую-нибудь анимацию логина там, еще что-нибудь, спросит тебя по пути, пока ты логинишься, еще какую-нибудь фигню про куки, ну, я сейчас фантазирую, но тем не менее. +3287.52 3294.04 "Игорь Лабутин" То есть у клиента своя сложная логика, и ему как бы тот факт, что ты пришлешь какой-то ответ – это просто дополнительный кирпичик. +3294.04 3295.04 "Игорь Лабутин" Вот. +3295.04 3300.22 "Анатолий Кулаков" Ну да, можно назвать это богатым клиентом, да, т.е. +3300.22 3303.88 "Анатолий Кулаков" рест и гипермедиа, они больше рассчитаны под тупого бедного клиента, под тонкого клиента. +3303.88 3311.00 "Анатолий Кулаков" В общем, они не исключают, конечно, богатых клиентов, но в целом индустрия реста была спроектирована именно для тонких клиентов. +3311.00 3314.00 "Анатолий Кулаков" Ну тогда да, это какой-то… Практика двинулась немножко в другую сторону. +3314.00 3315.00 "Игорь Лабутин" Двухтысячный год же. +3315.00 3316.00 "Анатолий Кулаков" По-моему, диссертация. +3316.00 3317.00 "Игорь Лабутин" Не знаю. +3317.00 3318.00 "Игорь Лабутин" Диссертация Роя Филдинга. +3318.00 3319.00 "Игорь Лабутин" Не помню. +3319.00 3325.08 "Игорь Лабутин" Собственно, Роя Филдинга, который придумал эту штуку, да, по-моему, 2000 или 2001 год, сейчас могу ошибиться. +3325.08 3333.04 "Игорь Лабутин" И тогда, понятное дело, ну, SPA, был ли тогда Якс уже хотя бы? +3333.04 3334.04 "Игорь Лабутин" Да-да, был. +3334.04 3335.04 "Игорь Лабутин" Был, да? +3335.04 3336.04 "Игорь Лабутин" Ну конечно. +3336.04 3338.84 "Игорь Лабутин" Хорошо, я не помню, я тогда особо не программировал ещё. +3338.84 3362.00 "Анатолий Кулаков" Кстати, можно тут сразу под шумок порекомендовать шикарный доклад от делана Бити, если вы хотите разобраться в ресте вот этих всех уровнях на очень хороших примерах, довольно лёгких, примитивных, понятных, с хорошим юмором от прекрасного автора, то доклад называется "Real World REST and Hands-On Hypermedia", который он делал на dotnext, кстати, был его самый первый доклад в России. +3362.00 3365.52 "Анатолий Кулаков" В общем, посмотрите, доклад до сих пор не потерял свою актуальность, потому что REST никуда не делся. +3365.52 3366.52 "Игорь Лабутин" Да. +3366.52 3369.96 "Игорь Лабутин" Ну так вот, ладно, пойдём дальше. +3369.96 3373.04 "Игорь Лабутин" Мы потратили уже много времени на то, чтобы обсудить, что же такое REST. +3373.04 3377.56 "Игорь Лабутин" На самом деле, рекомендации дальше, они все очень прям конкретные. +3377.56 3401.44 "Игорь Лабутин" Я осмотрел, давайте так, брал три основных источника, это майкрософтская статья, это заландовская статья, и это статья неизвестного мне автора, которая мне так немножко отозвалась, что да, похожа на то, что я обычно стараюсь использовать, хотя некоторые были довольно забавные рекомендации, ну забавные, на английском есть хорошее слово "controversial", то есть противоречивые, да, наверное, правильно сказать, рекомендации, которые непонятно следуют или нет. +3401.44 3403.32 "Игорь Лабутин" Давай пойдём по частям. +3403.32 3404.60 "Игорь Лабутин" Начнём с первого, это Урлы. +3404.60 3416.52 "Игорь Лабутин" Это у нас, собственно, главное и первое, что видит пользователь, когда начинает работать с REST, и здесь, в принципе, все сходятся в том, что надо использовать множественное число для сущностей. +3416.52 3428.16 "Анатолий Кулаков" Ну тут смотри, это не то, чтобы для сущностей, потому что для сущностей множественное число звучит странно, это всё-таки коллекция, это ресурсы, которые представляют собой коллекцию сущностей, и тогда понятно, почему множественное. +3428.16 3439.40 "Игорь Лабутин" Так а у тебя почти всегда будет сущность, это дальше ты, ну давай так, хорошо, сущность, которая имеет идентификатор, потому что почти всегда у тебя это будет потенциально коллекция сущностей. +3439.40 3454.24 "Игорь Лабутин" Может быть, ты не будешь иметь возможность получить коллекцию, например, если у тебя есть какой-нибудь шоппинг-карт, ну хотя вот с другой стороны, да, вот у тебя есть корзина, да, шоппинг-карт, технически в бэкэнде их много, но у каждого клиента она своя, +3454.24 3455.24 "Анатолий Кулаков" правильно? +3455.24 3458.48 "Анатолий Кулаков" Ну подожди, API-то всё-таки дёргается для конкретного клиента. +3458.48 3461.92 "Игорь Лабутин" Вот, да, для конкретного клиента она одна всегда, но у неё она… Она всегда одна. +3461.92 3464.88 "Игорь Лабутин" Ну если у неё… А, может быть, несколько, например. +3464.88 3470.84 "Анатолий Кулаков" Ну обычно в магазинах нескольких не бывает, давай, может быть, конечно, может быть, но 99% у тебя всегда в магазине одна корзина. +3470.84 3475.44 "Игорь Лабутин" А, ну тогда у тебя не будет айдишника, да, согласен, ну тут тогда это самое, единственное число, окей. +3475.44 3493.60 "Анатолий Кулаков" Кстати, здесь минутка весёлого, да, почему у неё не будет айдишника, потому что на заре времён, когда только начинали делать сайты, программисты именно делали вот так, что у тебя есть множество корзин и есть айдишник, и соответственно ты мог по айдишнику обратиться к своей корзине, и умные люди просто взяли, ну т.е. +3493.60 3498.08 "Анатолий Кулаков" брали и эти айдишники перебирали, и по факту ты мог посмотреть в корзины других пользователей. +3498.08 3511.60 "Анатолий Кулаков" Вот, и чтобы такого, таких глупостей как бы не делали, вот сделали такие вещи, что если урл относится к текущему пользователю, и этот пользователь не должен видеть никакие другие корзины, то айдишник просто не передаётся. +3511.60 3512.60 "Анатолий Кулаков" Ну да, желательно его скрывать. +3512.60 3513.60 "Игорь Лабутин" Небольшой хак. +3513.60 3522.40 "Игорь Лабутин" Вот, очень желательно, и находите его какой-то внутренней логикой внутри у вас на сервере, там в сессии храните или просто поднимайте по юзер айди, какая же у него корзина. +3522.40 3523.40 "Игорь Лабутин" Это уже другое дело. +3523.40 3524.40 "Игорь Лабутин" Дальше. +3524.40 3553.52 "Игорь Лабутин" В целом все довольно, ну давай так, не очень однозначно, но в целом говорят, что не надо добавлять ненужные кусочки пути, т.е. если у вас есть ресурс и у него есть подресурс, при этом подресурс довольно уникальным образом определяется своим айдишником, т.е. его айди уникален не только в рамках родительского ресурса, а вообще в системе, то не надо тогда передавать вот этот вот топовый ресурс, айдишник его всегда в урле. +3553.52 3554.52 "Игорь Лабутин" Ну, грубо говоря. +3554.52 3578.76 "Игорь Лабутин" Если у вас есть разные сущности, которые принадлежат одному пользователю, не надо везде писать users/userid/books, что-нибудь или там /posts, что-нибудь, /comments, что-нибудь, userid, ну, в общем, во-первых, и так понятен из контекста, ну, userid в этом смысле плохой пример, но даже если он не был бы понятен из контекста, если у тебя блок-пост имеет уникальное id, достаточно сделать /posts/id. +3578.76 3607.80 "Анатолий Кулаков" Ну, здесь, наверное, могут быть исключения, потому что иногда иерархия тебе позволяет эти урлы удобнее читать, т.е. нужно сказать, что rest level 3, он в отличие от болота, подразумевает то, что эти урлы должны быть пользователям хорошо читаемыми, и именно на это направлено большинство практик, ну, т.е. для машины наплевать, у тебя с ресурсами коллекции во множественном числе или в единственном называется, ей все равно, а вот пользователь, когда это будет читать, у него уже будет какое-то или понимание, или недопонимание. +3607.80 3611.20 "Анатолий Кулаков" Поэтому бывают такие ресурсы, которые логичнее представить в виде иерархии. +3611.20 3625.28 "Анатолий Кулаков" Город, страна, дом, если вы просто напишите дом 10, ну, дом с гуйдом, допустим, у вас будет смотреться не так красиво, как если бы вы написали, там, страна Россия, город Санкт-Петербург, улица такая, дом такой-то. +3625.28 3630.16 "Игорь Лабутин" Ну только теперь мы вспоминаем, что дом – это гуид, и поэтому это будет страна гуид, город гуид. +3630.16 3633.08 "Игорь Лабутин" Ну, именно так, да-да, это уже другой вопрос. +3633.08 3647.64 "Игорь Лабутин" Ну про это, кстати, тоже есть отдельная рекомендация, что для таких well-known штук, ну в смысле, допустим, для страны, тупо используйте, у нас есть как бы стандартная классификация этих самых двухбуквенных кодов стран, вот используйте ее, не надо ничего придумывать своего. +3647.64 3660.64 "Игорь Лабутин" Чем более стандартная штука, тем более стандартная, ну т.е. если на какую-то сущность есть стандартная ее репрезентация, хоть как-то классифицированная, используйте ее, облегчите жизнь потребителю гораздо больше. +3660.64 3668.24 "Анатолий Кулаков" А еще желательно, чтобы эта стандартная стандартизация была url-френдли, потому что не все стандартизации у нас хорошо эскейпятся. +3668.24 3697.00 "Игорь Лабутин" Это правда, это правда, ну вот, и последнее, предпоследнее, что про урлы, тоже, кстати, мне кажется, что я не так часто это встречаю, и Майкрософт из Оландо говорит, надо предпочтительно использовать кебаб, кейзинг, это который, если у вас в урле в сущности нужно указать несколько слов подряд, ну в смысле, в одном термине, да, в одном сегменте, то нужно использовать дефис, не подчеркивая, не camel-кейзинг, когда с большой буквы пишется, а через дефис, и все, лаверкейзинг. +3697.00 3732.76 "Анатолий Кулаков" Ну, я хочу сказать, что это правило, оно как бы довольно, сейчас скажу, не то, чтобы спорное, оно довольно поздно появилось в индустрии, т.е. уже после того, как RSTPI там хайпанул, приобрел своих последников, выпустилась куча книжек, и, к сожалению, у каждой компании раньше были свои какие-то рекомендации, именно поэтому у кого-то там Pascal, у кого-то Camel, у кого-то Kebabs, у кого-то Snake, в общем, разбродилось, разбродилось вот это все поверье, но именно, да, именно Kebab-кейс в последнее время начали писать у себя многие большие компании. +3732.76 3737.96 "Анатолий Кулаков" Я не знаю, они там специально договорились или не специально, но вот NSC к этому явно в последнее время идет. +3737.96 3748.16 "Игорь Лабутин" Да, и везде написано не в формате рекомендаций, а в формате просто «не забудьте, что вообще-то та часть, которая не является доменным именем, она case-sensitive», т.е. +3748.16 3762.72 "Игорь Лабутин" вот весь URL, который вправо от после доменного имени, он вообще говоря case-sensitive, и надо бы его рассматривать именно так, хотя в Microsoft написано «не, но если там правда GUID передается, GUID можно и так, и сяк». +3762.72 3767.32 "Игорь Лабутин" Короче, там куча всяких разных но, но вообще-то case-sensitive по стандарту. +3767.32 3786.36 "Анатолий Кулаков" Ну, кстати, да, и это довольно-таки мало людей знает почему-то, потому что в RLAC все привыкли видеть какое-то безобразие и об этом не задумываются, и иногда у нас, например, пользователи писали баги, типа я вот по ID-шнику такому запрашиваю ресурс, а он не находит, а он там ID-шник руками вбивал и немножко буковки перепутал, кейсы как раз-таки. +3786.36 3789.64 "Анатолий Кулаков" Поэтому это правда, да, смотри на case-sensitive. +3789.64 3798.80 "Анатолий Кулаков" Про GUID я тебе хотел немножко поправить, что это же все-таки не зависит от кейса, потому что GUID у него есть свой собственный парсер, и вот парсер сам решает, sensitive или не sensitive. +3798.80 3799.80 "Анатолий Кулаков" Ну это да. +3799.80 3800.80 "Анатолий Кулаков" Именно поэтому ты можешь там передать. +3800.80 3807.64 "Игорь Лабутин" Я понимаю, почему так происходит, но как бы у Microsoft в статье написано, что типа, мол, вообще-то оно case-sensitive. +3807.64 3816.16 "Игорь Лабутин" Ну там написано, но типа есть определенные сегменты с определенными типами данных, которые, ну и вот в общем дальше, да. +3816.16 3820.32 "Игорь Лабутин" Ну вообще да, рассчитывайте, что это всегда case-sensitive, это точно не ошибетесь. +3820.32 3860.96 "Игорь Лабутин" И последний момент интересный, смотри, в Rust-е level 2, ну вообще в Rust-е, да, у нас известная проблема, что у нас нет возможности делать экшены, в смысле, если у тебя через HTTP-глаголы не выражается что-либо, точнее, если тебе нужно выразить что-то, кроме create, read, update, delete, которые выражаются через HTTP-глаголы, то полноценные Rust-гайдлайны говорят, что нужно завести новый ресурс, к нему делать пост, создание операции по чему-нибудь, потом проверять ее статус, ну это типа такой, я не видел особо, чтобы таким пользовались, ну кроме действительно длинных операций. +3860.96 3865.72 "Игорь Лабутин" У Microsoft в этом смысле сейчас современные Azure-рекомендации довольно простая. +3865.72 3895.32 "Игорь Лабутин" Если вам нужно что-то сделать с какой-то сущностью, до которой вы, например, дошли по айдишнику, ну я не знаю, опубликовать блокпост, вот давай предположим, что это именно экшен, который нужно сделать, то url для такой операции будет выглядеть как там, пост, слэш, айдишник его, двоеточие, паблиш, т.е. глагол вот этого экшена делается через двоеточие, ну и естественно используется пост в этом случае, вот. +3895.32 3903.04 "Анатолий Кулаков" Ну, ты затронул две темы, т.е. ты затронул тут асинхронные операции и связал их с постом, т.е. пост не всегда может быть асинхронный. +3903.04 3920.08 "Игорь Лабутин" Нет, смотри, смотри, смотри, да, я говорю, что идея в том, что, т.е. для любых асинхронных операций подход примерно понятие, да, дергаем пост, получаем какой-то айдишник, потом по нему там полим и выясняем статус асинхронной операции. +3920.08 3928.56 "Игорь Лабутин" Это как бы такой более-менее сложившийся паттерн, с которым примерно все согласны, насколько я вижу по статьям и в среднем по интернету. +3928.56 3943.56 "Игорь Лабутин" Но вот когда у тебя возникает вопрос, а вот как сделать операцию паблиш-посту, ну предположим, что это не просто обновление, да, одного и проперти, да, это некоторый процесс, который нужно запустить с какими-то дополнительными аргументами, то есть несколько техник. +3943.56 3970.96 "Игорь Лабутин" Ты можешь сделать что-нибудь типа пост, пост в смысле http-шный пост, там, www, что-нибудь, /blockpost/1/publish, а можешь сделать /1:publish, вот с двоеточием я, честно говоря, подхода не видел, хотя, признаться, ажурным как раз API им пользовался одно время, но что-то мне не попадались, видимо, такие действия, которые требовали прям глагола /action, вот Майкрософт говорит, давай через двоеточие, чтоб вот точно было понятно. +3970.96 3980.08 "Анатолий Кулаков" Действительно, я думаю, это такое их довольно новомодное предложение, потому что как бы устоявшийся в индустрии подход в том, что всё, что угодно можно выразить через REST. +3980.08 3994.92 "Анатолий Кулаков" В данном конкретном твоём случае, когда мы хотим опубликовать блокпост, мы всего лишь навсего находим url, ресурс, который называется публикации, и добавляем в ресурс публикации новый пост, вот таким образом ты публикуешь пост, вот и всё. +3994.92 3999.80 "Анатолий Кулаков" То есть сводишь это всё к пустому чайнику первому случаю. +3999.80 4005.68 "Анатолий Кулаков" У тебя для всего могут быть ресурсы, и для публикаций, и для запусков, и для скедурингов, и для чего угодно. +4005.68 4007.92 "Игорь Лабутин" Да, но проблема в том, что публикация не имеет айтишника +4007.92 4008.92 "Анатолий Кулаков" своего. +4008.92 4009.92 "Анатолий Кулаков" Ну почему это проблема? +4009.92 4016.84 "Анатолий Кулаков" Ты же можешь в публикацию запульнуть пост, можешь, о том, что тебе не нужно публикации все считывать по айтишнику, ну не нужно, ну не считывай. +4016.84 4018.48 "Игорь Лабутин" Что здесь проблема? +4018.48 4062.20 "Игорь Лабутин" Ну проблема в том, что мне, например, такой подход кажется прям контринтуинтивным, в смысле, что мы привыкли, то есть сейчас сформулирую, во многих доменах мы привыкли к действию, прямому действию над объектом, в данном случае это как бы косвенное действие над объектом, ты не, у тебя главный объект, к которому ты обращаешься в урле, это пост, я хочу обратиться в урле к посту и с ним что-то сделать, а не я хочу обратиться в урле к публикации, а передать пост где-то там в аргументах, то есть вот этот вот переход, очень многих, меня в том числе, на самом деле сильно замедляет, когда я пытаюсь понять или осознать какой-то API, это прям вот. +4062.20 4085.04 "Анатолий Кулаков" Смотри, мне кажется, ты сделаешь следующую ошибку, ты зря смешиваешь домен и транспортный уровень, то есть по сути HTTP это у тебя транспортный уровень, ну например, когда ты там по сигналеру передаешь, это все в хабе летает по кусочкам как бы бинарного протокола, ты же не пытаешься все в голове уложить в какой-то бизнес логичный процесс, ты понятия не имеешь там, как листанер это листанет, HTTP сокетит, это сосокетит. +4085.04 4086.04 "Анатолий Кулаков" Все так. +4086.04 4099.40 "Анатолий Кулаков" Так здесь у тебя нужно делить, что действительно в бизнес домене ты обращаешься к терминам поста, но это транспортный протокол, это REST, он тебе не призван идеально описывать бизнес домен, он не про то, он не про описание домена вообще, он про протокол общения. +4099.40 4118.00 "Игорь Лабутин" С этим я с тобой согласен, но, к сожалению, процентов, пандомное число, 60 API-шек, с которыми я встречаюсь, единственное, что содержит, это свагерспеку без описания того, что если вы хотите сделать вот такой бизнес процесс, вам нужно подергать API-методы в таком-то порядке. +4118.00 4122.64 "Игорь Лабутин" И ты понимаешь бизнес процесс только глядя на свагерспеку. +4122.64 4124.20 "Анатолий Кулаков" Ну, на OpenAPI-спеку. +4124.20 4127.32 "Анатолий Кулаков" Ну, опять же, может это проблемы документации или проблемы +4127.32 4128.32 "Игорь Лабутин" еще чего-то. +4128.32 4145.68 "Игорь Лабутин" Это может быть проблемы документации, то есть понятно, что было бы здорово, если бы REST API был чисто технической штукой, и мне просто было понятно, окей, и мне нужно сначала создать блокпост, отредактировать его, добавить черновики, картинок довесить, и потом опубликовать. +4145.68 4154.56 "Игорь Лабутин" И рядышком с этим описанием бизнес процесса, у меня было бы, типа, для этого сделай PUT такой-то, для этого сделай POST такой-то, для этого сделай POST такой-то. +4154.56 4159.36 "Игорь Лабутин" Мне тогда не важно, тогда я просто беру механически, что мне сказали сделать, то и делаю. +4159.36 4165.52 "Игорь Лабутин" Проблема в том, что API-шек, где написано так, в моей практике, по крайней мере, катастрофически мало. +4165.52 4174.44 "Анатолий Кулаков" Кстати, вот эту самую штуку делает гипермедия, потому что гипермедия тебе возвращает абстрактные экшены, которые тебе нужно просто вызывать, не задумываясь о том, по какому урлу она там находится. +4174.44 4177.48 "Игорь Лабутин" Не совсем, гипермедия не возвратит тебе контент-боди. +4177.48 4186.64 "Анатолий Кулаков" Ну почему же это не возвратит, конечно, возвратит, но это же такой же обычный урл, ты его можешь дернуть и что-то оттуда получить. +4186.64 4197.52 "Игорь Лабутин" Нет, нет, нет, в смысле, я не уверен, что ты можешь в гипермедии передать ожидаемый боди-реквеста. +4197.52 4203.36 "Анатолий Кулаков" Ты можешь передать там боди, ты можешь передать там форматор, которым ты хочешь отформатировать, и можешь передать там другие ожидания. +4203.36 4209.36 "Анатолий Кулаков" Это обычная HTTP, грубо говоря, запрос, просто более высокоуровневый, в терминах бизнеса, а не в терминах какой-то транспорта. +4209.36 4215.68 "Игорь Лабутин" Слушай, может быть, но возвращаемся к вопросу, цена, так сказать, и польза. +4215.68 4229.08 "Игорь Лабутин" Я такие API-шки, скажем так, не понимаю и не люблю, потому что это сильно, когда у меня домен сильно совпадает с транспортным уровнем, это очень, ну как бы, ценно и легко. +4229.08 4230.08 "Анатолий Кулаков" Потом в отладке. +4230.08 4237.12 "Анатолий Кулаков" Мне кажется, смотри, если мы возьмем какие-нибудь статьи, которые пропагандирует gRPC, вот это как раз один эндпоинт, и делай там с ними что хочешь. +4237.12 4238.12 "Анатолий Кулаков" GraphQL. +4238.12 4239.12 "Анатолий Кулаков" GraphQL. +4239.12 4244.12 "Анатолий Кулаков" То у них как раз-таки вот это, что мы сейчас обсуждаем, вот это проблема. +4244.12 4253.92 "Анатолий Кулаков" Ну то есть нужно признать, что у HTTP-транспорта, у REST давай так, это проблема, что не всё выражается довольно интуитивными бизнес-терминами. +4253.92 4257.94 "Анатолий Кулаков" А вот если мы берём GraphQL, то там ты у любой сущности можешь, по сути, дёрнуть любой метод. +4257.94 4261.72 "Анатолий Кулаков" То есть они это ставят как свой плюс, если мы сравним с REST. +4261.72 4263.84 "Анатолий Кулаков" Ну да, есть у них такой плюс, есть у REST-а такой минус. +4263.84 4272.76 "Игорь Лабутин" Ну вот тут скорее, да, про то, что вопрос, надо ли стремиться к тому самому REST-левел, 2 или 3, с точки зрения вообще всех операций. +4272.76 4279.52 "Игорь Лабутин" Кажется, что, с моей точки зрения, нет, не надо, но кажется, что индустрия куда-нибудь пойдёт в другое место. +4279.52 4284.14 "Игорь Лабутин" Ладно, давай с урлами плюс-минус закончим и пойдём к следующей части. +4284.14 4287.72 "Игорь Лабутин" Это контракты, там про эти глаголы мы поговорим чуть позднее. +4287.72 4290.56 "Игорь Лабутин" Давай немножко про контракты, что тут все говорят. +4290.56 4297.92 "Игорь Лабутин" Ну, в среднем все там плюс-минус сходятся в том, как нужно делать контракты. +4297.92 4306.16 "Игорь Лабутин" То есть почти все говорят, что не надо возвращать массивы в качестве топ-левел сущности, потому что это не расширяемый контракт вообще. +4306.16 4313.88 "Игорь Лабутин" Массив всегда должен быть под ключиком каким-нибудь, потому что иначе вы не сможете ничего дополнительно вернуть, помимо массива. +4313.88 4326.52 "Анатолий Кулаков" Ну, то есть, допустим, если массив у вас вырос, и вы хотели сделать пейджинг, и хотите теперь возвращать в этом объекте count, сколько всего элементов в этом общем массиве, а не только то, что вы сейчас вернули, сколько элементов на этой странице. +4326.52 4334.52 "Анатолий Кулаков" Это вполне нормальная эволюция процесса и, скорее всего, в больших коллекциях, когда они у вас вырастут, вы с этим столкнётесь. +4334.52 4343.32 "Анатолий Кулаков" И вот такое изменение вы не сможете сделать, если вы возвращали массив топ-левелом, а если вы это запихивали под ключиком как отдельное какое-то одно поле, то там добавляете вообще всё, что хотите. +4343.32 4344.32 "Игорь Лабутин" Да. +4344.32 4354.76 "Игорь Лабутин" Интересная рекомендация как раз из статей, неизвестной статьи из интернета, которая не встречается ни в The London, ни в Microsoft, по крайней мере, я не нашёл, может, пропустил там много их. +4354.76 4365.20 "Игорь Лабутин" Это про то, что момент номер один, всегда для всех идентификаторов в контракте используйте строки, т.е. даже если у вас в BD число, отдавайте всё равно строку. +4365.20 4376.60 "Игорь Лабутин" Потому что кто знает, как что изменится, а строки точно всё сожрут внутри себя, т.е. если вы потом решите перейти на Гуиды, то не надо будет менять контракт на Пишки, по сути. +4376.60 4390.20 "Анатолий Кулаков" Да, вот это, кстати, очень полезное правило, которое почему-то очень редко встречается, я тебя поддержу и сам пользуюсь именно таким подходом, потому что, опять же, обычно, когда вы возвращаете айтишники, это идентификаторы из базы данных. +4390.20 4395.16 "Анатолий Кулаков" А то, какую базу данных сейчас использует приложение, это личное дело любого микросервиса. +4395.16 4398.24 "Анатолий Кулаков" Т.е. если он сейчас это в памяти хранил, у него там могут быть инты. +4398.24 4408.08 "Анатолий Кулаков" Завтра он подрос, у него там будет какой-нибудь пастгря, потом он перейдет на какой-нибудь MS SQL, там у него должны быть Гуиды, при том не просто Гуиды, а сортированные Гуиды и так далее, и тому подобное. +4408.08 4412.96 "Анатолий Кулаков" Потом, если нужны шарды, то там желательно ещё добавить номер кластера перед каждым этим айтишником. +4412.96 4423.64 "Анатолий Кулаков" В общем, и внутри самого сервиса, сервис обязан мочь переходить на любую базу данных, на ту, которая полностью удовлетворяет его как бы системам, его системам. +4423.64 4424.64 "Анатолий Кулаков" А требования могут меняться, как вы все понимаете. +4424.64 4430.32 "Анатолий Кулаков" И сервис как раз-таки не должен наружу декларировать, а какого типа у него идентификаторы. +4430.32 4435.12 "Анатолий Кулаков" Поэтому в JSON строка – это как раз не декларирование типа, это там object. +4435.12 4446.12 "Анатолий Кулаков" Вот если вы в коде возвращали бы object, то в JSON вы должны возвращать string, и вот как раз идентификатор – это та внутренняя логика, которую сервис обязан как бы контролировать самостоятельно. +4446.12 4452.40 "Анатолий Кулаков" И никто снаружи не может эти айтишники, по сути, никак их интерпретировать и никак на них рассчитывать. +4452.40 4453.40 "Игорь Лабутин" Вот. +4453.40 4460.12 "Игорь Лабутин" А теперь есть второй кусочек этой рекомендации, который на самом деле я встречал несколько раз, не у больших ребят, но во многих статьях. +4460.12 4463.20 "Игорь Лабутин" Называется «используйте префиксы для ваших идентификаторов». +4463.20 4465.24 "Игорь Лабутин" То есть, о чем речь? +4465.24 4471.72 "Игорь Лабутин" Это поможет, то есть это как бы для облегчения жизни клиентским разработчикам и в каком-то смысле саппорту. +4471.72 4485.68 "Игорь Лабутин" То есть если у вас, например, есть, не знаю, возвращаемся к нашему традиционному примеру про блокпосты и комменты, у каждого из них, предположим, есть уникальный идентификатор, да, сквозной, ну потому что они лежат в каждой своей табличке в BD, допустим, и там сквозная нумерация. +4485.68 4505.48 "Игорь Лабутин" Так вот, вы возвращаете не просто строчку с содержимым 1, строчку с содержимым 2, строчку с содержимым 3, а для всех постов вы возвращаете строчку с содержимым p1, p2, p3, то есть с префиксом p, типа что это посты, а для комментов вы возвращаете строчку с префиксом c, да, c1, c2, c3. +4505.48 4524.40 "Игорь Лабутин" Клиенту пофигу, потому что это строка все равно, он не должен ее парсить, он не должен с ней ничего делать, это просто прозрачная для него строка, но во-первых он сам понимает, что ага, тут мне вернулись, там, идентификатор на p, значит окей, типа это наверное про посты, а тут на c, значит это наверное про комменты, в таком духе. +4524.40 4526.00 "Игорь Лабутин" Чисто просто понятнее становится. +4526.00 4540.28 "Игорь Лабутин" При этом, при этом автор говорит, что ну вообще-то, вообще-то не нужно обязательно считать, что вот этот вот айдишник, который вы возвращаете пользователю, должен совпадать с primary ключиком вашей базы. +4540.28 4557.96 "Игорь Лабутин" Вообще говоря, вы можете использовать юиды для хранения в базе, а пользователю возвращать что-то более осмысленное, например, или еще каким-то образом там компаунд ключ собранный, как ты говоришь, из шарда или еще из чего-нибудь, это не обязательно так, не надо всегда возвращать primary key наружу. +4557.96 4571.16 "Анатолий Кулаков" Смотри, наверное более распространенный пример это когда у вас в базе все хранится все-таки синтами, потому что это должно быть красивенько и все такое, но наружу вы не хотите отдавать инты, потому что они легко подбираются, и пользователь может подобрать их просто чисто перебором. +4571.16 4582.88 "Анатолий Кулаков" Поэтому существуют специальные библиотечки, которые превращают ваши инты, то есть хешируют их по словарю в какой-то хеш, которых перебирать в принципе бесполезно, но при этом он у вас остается довольно читабельным, коротким и так далее. +4582.88 4587.36 "Игорь Лабутин" Надо сказать, не хешируют здесь важно, а именно конвертируют, потому что обратная конвертация тоже возможна. +4587.36 4590.96 "Игорь Лабутин" Вам же нужно из этого айдишника обратно-то свою чиселку получить, когда к вам придут. +4590.96 4593.96 "Анатолий Кулаков" Да, да, ты прав, именно так. +4593.96 4596.56 "Анатолий Кулаков" Я ещё хотел добавить про префиксы. +4596.56 4610.64 "Анатолий Кулаков" Я тоже эту технику с префиксами очень много использую, и действительно, может быть, многие из вас, кто особенно любит гуйды, встречались с такими, что приходишь в базу данных какой-нибудь, а там есть 10 колонок, и во всех этих колонках написано «айдишники», и всё это гуйдами забито. +4610.64 4624.08 "Анатолий Кулаков" И ты, естественно, без какой-то чёрной магии недели, проведённой над этим дампом, никогда не сможешь понять, а чьи это гуйды, откуда они прилетели, и что они там лежат, потому что название колонок тоже имеет свойство переименовываться, записаться не туда и так далее. +4624.08 4627.00 "Анатолий Кулаков" В общем, по названию иногда бывает не добраться. +4627.00 4630.18 "Игорь Лабутин" Ну подожди, ты хочешь сказать, что ты префикс даже в базу положишь? +4630.18 4631.18 "Игорь Лабутин" А как же? +4631.18 4632.18 "Игорь Лабутин" Смотри. +4632.18 4634.92 "Игорь Лабутин" Там юидные типы колонок, там вот это всё. +4634.92 4636.92 "Анатолий Кулаков" Не-не-не, немножко не так. +4636.92 4640.20 "Анатолий Кулаков" Или вот смотри, более, наверное, такой правильный пример, это в логах. +4640.20 4648.36 "Анатолий Кулаков" Вот ты в логах видишь сообщение «сущность такая не может быть там вставлена», и айдишник этой сущности, и всё, и больше у тебя никакой информации о ней нет. +4648.36 4649.36 "Анатолий Кулаков" Ну там, наверное, логер. +4649.36 4655.08 "Анатолий Кулаков" Наверное, ты можешь пойти, достать код, достать какой-то проект, найти где там логеры, посмотреть, а что же за сущность была вставлена. +4655.08 4670.20 "Анатолий Кулаков" А вот если у тебя есть префиксы, которые рассказывают, что это, в принципе, айдишник поста был, то есть по правде в айдишник добавляется там, допустим, «п» или можно просто «пост», если это слово небольшое, то ты сразу по айдишнику видишь, что в логах у тебя залогировано. +4670.20 4671.20 "Анатолий Кулаков" То есть айдишник какой сущности. +4671.20 4677.76 "Анатолий Кулаков" И про базы данных пример я тебе привел, это когда у тебя внешняя база данных хранит ссылки на твои сущности. +4677.76 4682.40 "Анатолий Кулаков" То есть внешняя база данных воспринимает твои айдишники как строки. +4682.40 4684.20 "Анатолий Кулаков" Она не может оттуда выделить ни префикс, ничего. +4684.20 4689.92 "Анатолий Кулаков" Она взяла строку, как-то я дал, и положила к себе как бы референс к этому пользователю, я его люблю, завтра я к нему схожу. +4689.92 4692.52 "Анатолий Кулаков" И у нее в базе, да, хранятся это все именно с префиксами. +4692.52 4697.96 "Анатолий Кулаков" И ты, когда на ее базу смотришь, ты видишь сразу все вот эти внешние зависимости, ты понимаешь, откуда они. +4697.96 4702.72 "Анатолий Кулаков" То есть я в свой префикс добавляю не только имя сущности, я добавляю еще имя сервиса. +4702.72 4708.72 "Анатолий Кулаков" Естественно, сокращённое, но я по айдишнику могу определить, во-первых, сервис, а во-вторых, сущность из этого сервиса. +4708.72 4710.40 "Анатолий Кулаков" И только потом его ГУИД. +4710.40 4711.40 "Анатолий Кулаков" Прикольно. +4711.40 4712.40 "Анатолий Кулаков" Прикольно. +4712.40 4713.40 "Игорь Лабутин" Окей. +4713.40 4714.40 "Игорь Лабутин" Хорошо. +4714.40 4715.40 "Игорь Лабутин" Давай еще поговорим. +4715.40 4716.40 "Игорь Лабутин" А, смотри. +4716.40 4717.40 "Анатолий Кулаков" Еще одна мелочь. +4717.40 4724.92 "Анатолий Кулаков" Многих людей коробит, потому что, когда ты добавишь имя сервиса, потом еще имя сущности, а потом еще ГУИД, у тебя превращается в ГУИД очень большой. +4724.92 4727.54 "Анатолий Кулаков" То есть айдишник превращается в что-то очень большое. +4727.54 4728.68 "Анатолий Кулаков" Здесь есть небольшой лайфхак. +4728.68 4734.64 "Анатолий Кулаков" На самом деле ГУИД шифруется шестнадцатиличным числом. +4734.64 4736.20 "Анатолий Кулаков" Шестнадцатиличная система измерения. +4736.20 4738.36 "Анатолий Кулаков" Это никакого смысла вообще не имеет. +4738.36 4744.44 "Анатолий Кулаков" Берете стандартный какой-нибудь Base64 или еще что-то лучшее и шифруете по полному алфавиту. +4744.44 4750.28 "Анатолий Кулаков" Как я уже сказал, URL он case-sensitive, поэтому никаких проблем у вас не будет, если у вас там даже все буквы будут скакать. +4750.28 4754.04 "Анатолий Кулаков" И у вас ГУИД уменьшается прямо легко в пару раз вообще. +4754.04 4759.20 "Анатолий Кулаков" Не надо шифровать шестнадцатиличную систему, это не имеет никакого смысла. +4759.20 4766.24 "Игорь Лабутин" Да, либо есть всякие там Snowflake ID, вот эти все, которые аналоги такие же, плюс-минус сортируемые, но которые занимают существенно меньше места. +4766.24 4767.24 "Анатолий Кулаков" Можно на них посмотреть. +4767.24 4775.00 "Анатолий Кулаков" То есть если вы ГУИД по размеру уменьшаете, то то, что вы добавляете префикс, грубо говоря, сохраняет вам примерно ту же самую длину и вас это будет меньше коррубить. +4775.00 4777.16 "Игорь Лабутин" Так, что еще интересного? +4777.16 4786.96 "Игорь Лабутин" Ну понятно, используйте структурированные ROR, это все говорят, ISO 8601 для timestamps и для всяких других дат и прочего. +4786.96 4795.32 "Игорь Лабутин" Причем сказано, что когда вы форматируете это все потом в JSON, в ISO 8601, не доверяйте вашей, короче, платформе про то, что она корректно сделает. +4795.32 4809.16 "Игорь Лабутин" Лучше напишите явную спецификацию формата, что вы хотите, потому что дефолты меняются, подходы меняются, а вот если вы точно напишете, что там yyyy, mm, dd, вот это все, то точно не поменяется. +4809.16 4810.32 "Игорь Лабутин" Лучше пишите явно. +4810.32 4825.32 "Игорь Лабутин" Так, для строк, да, вот это, кстати, у Майкрософта прям очень большой раздел указан, для любых строк, которые встречаются в вашем контракте, напишите четкий контракт. +4825.32 4832.60 "Игорь Лабутин" То есть для каждого поля, которое строка, напишите, если там, ну типа если это а-ля Unum, то напишите какие значения там могут быть. +4832.60 4837.28 "Игорь Лабутин" Это не значит, что там не может быть других, но хотя бы вот эти точно могут быть. +4837.28 4843.76 "Игорь Лабутин" Если это поле ограничено по длине, напишите, если оно там, ну понятно, что всякие обязательности точно нужно указывать и так далее. +4843.76 4848.84 "Игорь Лабутин" То есть не должно быть в контракте поля, в котором просто написано "строка". +4848.84 4856.52 "Анатолий Кулаков" Ну это немножко напоминает языки со слабой типизацией типа Питона, да, где там всё на свете может храниться во всём, чем угодно. +4856.52 4859.24 "Анатолий Кулаков" Или, допустим, если бы у нас в шарпе все поля были бы object. +4859.24 4867.72 "Анатолий Кулаков" Ну конечно, если бы поля все были бы object, мы бы всё в комментариях писали, что этот object, это на самом деле Unum, этот object – это data, а JSON – это та же самая фигня. +4867.72 4873.92 "Анатолий Кулаков" Там всё это, грубо говоря, строки, там буквально 5 типов, и в основной части это, конечно, строки, да, их надо написать, надо документировать. +4873.92 4875.60 "Анатолий Кулаков" По-моему, там три типа, что там? +4875.60 4877.16 "Анатолий Кулаков" Там bool, int, ну number. +4877.16 4878.92 "Игорь Лабутин" Bool, number, string, всё. +4878.92 4882.08 "Игорь Лабутин" Ну не берём листы, всякие вот эти array, это уже понятно. +4882.08 4883.08 "Игорь Лабутин" Да-да, элемент примитива. +4883.08 4884.08 "Игорь Лабутин" Коллекция. +4884.08 4886.80 "Игорь Лабутин" Ну да-да, наверное, в три, если только примитивы брать. +4886.80 4888.72 "Игорь Лабутин" Так, что ещё у нас по контрактам? +4888.72 4899.68 "Игорь Лабутин" А, ну у Майкрософта, кстати, явно написано, используйте одинаковые JSON-схемы для put-ов, патчей, ну, респонсов, понятно, get-ов, респонсов, и для пост-ов, request-ов, респонсов. +4899.68 4921.48 "Игорь Лабутин" Максимально делайте похожую схему, чтобы в идеальном случае то, что вы получили из get-а, нужно было немножко поменять, что вы там хотите поменять, например, отправить в put, вот, или в post, если вы хотите, например, копию создать объекта, вот, вы получили какой-то объект из get-а, отдали в post, его же будет копия, вот, в таком духе. +4921.48 4927.40 "Игорь Лабутин" То есть, ну, понятно, не плодите там, там где ожидается одинаковый плюс-минус схемы, используйте реально одинаковую плюс-минус схему. +4927.40 4937.92 "Игорь Лабутин" Так, так, так, так, так, довольно много всяких разных рекомендаций про error-коды, что-то пешные, то есть там 400, 404, вот это все. +4937.92 4956.88 "Игорь Лабутин" Одна из интересных дискуссий, которую я много где слышал, это вопрос, вот смотри, берем мы url, делаем мы get, поэтому url-у по какому-то конкретному idшнику, ну, допустим, у нас есть там блог-пост, мы хотим получить блог-пост с idшником 999, а его никогда не было, что мы должны вернуть? +4956.88 4961.92 "Анатолий Кулаков" Ну, опять же, здесь в зависимости от договоренности, никакого единого стандарта по рынку нет. +4961.92 4983.08 "Игорь Лабутин" Вот, и как раз, у Microsoft, кстати, у Zalando каких-то особых нет, по-моему, они там говорят, ну, 404 и все, что-то как бы not found, вот, а вот неизвестный автор из интернета говорит, нет, 404 not found подразумевает, что, короче, это вы прям в url-е ошиблись, вот это все, типа, нельзя возвращать not found в этом случае, используйте что-нибудь другое. +4983.08 5001.36 "Игорь Лабутин" Я, говорит, использую 410, вот, это, а что-то по код-ган, ну, что, типа, ресурс был, но больше нет, вот, чтобы как бы пользователь понимал, что он 404 в смысле он в url ошибся или в смысле он в url-у написал правильно все, но, ну, там не найдено ничего. +5001.36 5026.24 "Анатолий Кулаков" Смотри, я насчет ошибок я очень часто сталкивался случаями, когда компании нагораживали нам очень большое число ошибок, ну, то есть у них там использовалось 20 или там 25, чуть ли не ячайник они могли когда-нибудь вернуть, ну, потому что сидят там какие-то большолобые бэкэндеры и начинают выдумывать для себя, вот здесь был конфликт, вот здесь я обновил, но конфликта не было, но он мог бы быть, поэтому я вот вернул вот такой вот нашел интересный код. +5026.24 5031.60 "Анатолий Кулаков" В общем, здесь прежде всего нужно задумываться, а кто эти ошибки у вас будут читать, то есть кто ваши клиенты. +5031.60 5067.84 "Анатолий Кулаков" И если у вас клиент действительно способен обрабатывать ваши 25 типов статус кодов, то, конечно, пуляйте, но в большинстве случаев ваши клиенты – это вот тупые какие-нибудь React HTTP клиенты, которые знают буквально там 5 кодов по пальцам, и вот 404 они поймут, я вам 100% гарантирую, а вот 410 нет, ну или каждый будет понимать по-своему, и вам придется ходить из команды в команду и договариваться, что у меня вот 410, поэтому в таком случае я бы здесь больше склонился к 404, потому что это стандартная вещь, ее понимают многие клиенты, ее понимают там кэши, логи, как стандартные мидлвари, которые там метрики отсылают и прочее-прочее-прочее. +5067.84 5073.48 "Анатолий Кулаков" Здесь больше нужно идти к стандартизации и к пониманию клиентами, т.е. кто вас будет интерпретировать. +5073.48 5104.68 "Игорь Лабутин" Да, и, кстати, Zalando здесь во всем, что касается в этих error-кодах, у них прямо есть огромная большая табличка по каждому из этих error-кодов, ну в смысле табличка с error-кодами, и на каждой есть признак, а надо ли его вообще документировать в API, т.е. они говорят, что очень часто бывает такая ситуация, что вы видите там, не знаю, API-шку, в ней 10 методов, и на каждом методе написано, он может вернуть 200, он может вернуть 500, он может вернуть 400, он может вернуть 404, и везде написано одно и то же. +5104.68 5107.36 "Игорь Лабутин" Да-да, есть такие API-шки, да-да-да. +5107.36 5121.48 "Игорь Лабутин" У Zalando в рекомендациях написано, все well-known стандартные коды, которые возвращаются в известных обычных случаях, типа не надо документировать 500, все знают, что 500 может прийти от сервера, не надо вообще этого OpenAPI-спеку даже включать. +5121.48 5141.72 "Анатолий Кулаков" Ну вот видишь, как программисты, они когда видят дублирование у себя в коде, у них почему-то мозг включается, что нужно вот это дублирование вынести метод, куда-нибудь обозначить, а когда они видят дублирование в тексте одного и того же, мозг у них очень медленно включается, что блин, ну нафига вы дублируете одно и то же, ну это же можно или в одном месте записать где-нибудь на общей странице документации, или еще где-то, ну не нужно это дублировать, +5141.72 5142.72 "Игорь Лабутин" конечно же. +5142.72 5143.72 "Игорь Лабутин" Ну да, да-да-да. +5143.72 5157.80 "Игорь Лабутин" Ну и еще один момент касательно контрактов, последний, который я хотел бы отметить, это что, опять же, мне кажется, в индустрии нет какого-то единого стандарта, как в проперти в JSON, вот ты к чему склоняешься, к CamelCase, к SnakeCase? +5157.80 5160.64 "Игорь Лабутин" Наверное, это два самых популярных, пожалуй, да, наверное? +5160.64 5166.64 "Анатолий Кулаков" CamelCase и SnakeCase, через подчеркивание, либо с… Подожди, мы как нормальные C#-исты, мы должны склоняться к PascalCase, я считаю. +5166.64 5167.64 "Анатолий Кулаков" В пропертях? +5167.64 5168.64 "Анатолий Кулаков" Нет. +5168.64 5169.64 "Анатолий Кулаков" Конечно. +5169.64 5170.64 "Анатолий Кулаков" Да почему Camel? +5170.64 5171.64 "Анатолий Кулаков" Давай Pascal. +5171.64 5174.76 "Анатолий Кулаков" Ну у нас проперти называются в Pascal же, пусть и JSON-чики +5174.76 5175.76 "Игорь Лабутин" страдают. +5175.76 5192.24 "Игорь Лабутин" Ну проперти в Pascal, я согласен, ну не знаю, короче, традиционно я, конечно, больше CamelCase встречаю, но вот тут Microsoft говорит, короче, Майкрософт считает, что нужно обязательно CamelCase, ничего другого, Zalando считает, что обязательно SnakeCase, ничего другого, я так понимаю, что тут каждая компания, как договорится, лишь бы весь ваш API выглядел одинаково. +5192.24 5199.16 "Анатолий Кулаков" Ну типа того, мне кажется, у нас CamelCase просто по дефолту включены, поэтому большинство API в C#, они именно CamelCase-овые. +5199.16 5217.96 "Анатолий Кулаков" Тут и другой интересный вопрос есть, потому что на самом деле проперти в JSON не существует, в JSON все это дикшнери, и существует, это дикшнери-ключ на самом деле, а не проперти, и существует отдельная настройка в сериализаторе, типа проперти, окей, у вас будут вот такие, а что будет, если дикшнери вы передадите? +5217.96 5224.44 "Анатолий Кулаков" Ведь, по сути, в JSON и проперти, и дикшнери будут приведены к JSON-дикшнери, потому что это все дикшнери, вот. +5224.44 5244.64 "Анатолий Кулаков" И бывает такая ситуация, когда у вас проперти написаны в одном кейсе, а дикшнери, по сути, настройка стоит в другом кейсе, типа обычно даже ключи дикшнери стараются не менять, то есть они там, допустим, лежат в Pascal кейсе, а все остальное у вас там в Camel кейсе, вот, и сам JSON, соответственно, уже будет не соответствовать этому правилу, потому что на уровне JSON это одно и то же. +5244.64 5259.80 "Анатолий Кулаков" То есть вот здесь довольно большая проблема встречается, вот здесь надо еще договориться, а просто так модифицировать ключи в дикшнере обычно бывает не очень хорошо, потому что некоторые API спроектированы так, что воспринимаются ключи в дикшнере именно case-sensitive, ну потому что это ключи, это не свойства. +5259.80 5265.48 "Анатолий Кулаков" В общем, здесь тоже большой интересный вопрос, на который индустрия до сих пор, к сожалению, не договорилась. +5265.48 5269.12 "Игорь Лабутин" Ну я думаю, что на самом деле и не договорится, все равно слишком у нас много. +5269.12 5278.92 "Анатолий Кулаков" Так и есть, вы поэтому договоритесь на уровне своей компании, т.е. у каждой компании должен быть по каждому вот такому спорному пункту свой гайдлайн, как так положено делать у вас. +5278.92 5289.72 "Игорь Лабутин" Пойдем дальше, секция под названием HTTP-глаголы и идемпотентность, они идут вместе, потому что довольно сильно связаны. +5289.72 5299.96 "Игорь Лабутин" Ну, во-первых, все, в общем-то, сходятся мысли, что в современном мире нужно обязательно предоставлять механизмы обеспечения идемпотентности. +5299.96 5329.64 "Игорь Лабутин" Напомню, что такое идемпотентность, у вас есть разные HTTP-глаголы, и некоторые вы можете достаточно безболезненно при правильном спроектированном API повторять, т.е. например, вы можете вызвать GET много раз и, в принципе, на состояние системы с той стороны это не повлияет, оттого что вы вызвали, вам могут вернуться, естественно, разные немножко данные, потому что, возможно, как-то объект живет, меняется, у него там меняются статусы, но в целом вы можете без болезненно повторять GET-реквесты, не боясь что-то респортить. +5329.64 5346.72 "Игорь Лабутин" Вы точно также можете безболезненно повторять DELETE-реквесты, а вот если вы повторите, например, POST, то это может привести к нехорошим последствиям, потому что POST по дефолту не идемпотентен, и сервер как бы аккуратно его выполнит и создаст еще один объект, например, если вы POST создаете +5346.72 5347.72 "Анатолий Кулаков" объект. +5347.72 5351.64 "Анатолий Кулаков" Ну, это стандартный вопрос на собеседовании, чем отличается PUT от POST. +5351.64 5352.64 "Анатолий Кулаков" Да-да-да. +5352.64 5355.68 "Анатолий Кулаков" Единственное отличие в том, что POST не идемпотентен, а PUT идемпотентен. +5355.68 5360.28 "Игорь Лабутин" Да, ну их всего два, короче, точно не идемпотентных, это PATCH и POST, соответственно. +5360.28 5361.28 "Игорь Лабутин" Вот. +5361.28 5365.36 "Анатолий Кулаков" Ну, подожди-подожди, PATCH вполне идемпотентен. +5365.36 5366.36 "Анатолий Кулаков" Почему? +5366.36 5370.84 "Анатолий Кулаков" Ну, если ты в PATCH меняешь имя пользователя и ты поменял его 100 раз, то имя там будет одно и то же. +5370.84 5373.80 "Анатолий Кулаков" Да, но если я в PATCH делаю EDD в коллекцию. +5373.80 5374.80 "Анатолий Кулаков" В PATCH EDD? +5374.80 5376.36 "Анатолий Кулаков" Да, там есть такой вариант. +5376.36 5379.36 "Анатолий Кулаков" Ну да-да, потому что PATCH это, по сути, модификация. +5379.36 5383.28 "Анатолий Кулаков" В модификации ты как можешь поле поменять, так и можешь добавить некий элемент, поэтому непредсказуемо. +5383.28 5386.56 "Игорь Лабутин" В PUT ты обязан коллекцию целиком передать, и поэтому он идемпотентен. +5386.56 5390.36 "Игорь Лабутин" А в PATCH можно кусочек, там есть EDD и remove, по-моему, даже там есть. +5390.36 5391.36 "Игорь Лабутин" Что-то мне казалось, что есть. +5391.36 5392.36 "Игорь Лабутин" Ну ладно. +5392.36 5394.88 "Игорь Лабутин" Ну ты же точно так же в PUT можешь коллекцию добавлять? +5394.88 5395.88 "Игорь Лабутин" В PATCH? +5395.88 5398.24 "Игорь Лабутин" Добавлять не могу в PUT, в PUT она целиком перезапишется. +5398.24 5401.76 "Анатолий Кулаков" Опять же, бывают разные имплементации, кто как +5401.76 5402.76 "Игорь Лабутин" интерпретирует PUT. +5402.76 5406.88 "Игорь Лабутин" Ладно, да, хорошо, давай мы это, не будем углубляться в эту область. +5406.88 5414.96 "Игорь Лабутин" Короче, есть, в принципе, три таких способа, что ли, да, обеспечить эту самую демпотентность. +5414.96 5431.56 "Игорь Лабутин" Один вариант – это ключи демпотентности, т.е. вы вместе с POST просто посылаете заголовочки, отдельный еще ID-шник, там GUID, грубо говоря, и даже если… и сервер, соответственно, трекает, он будет знать, что операцию с таким GUID он уже выполнял. +5431.56 5433.88 "Анатолий Кулаков" Смотри, здесь, наверное, стоит сказать, а в чем проблема-то? +5433.88 5436.96 "Анатолий Кулаков" Ну допустим, у нас все урлы не демпотентны, и к чему это приводит? +5436.96 5464.56 "Игорь Лабутин" Ну проблема в том, что, например, если мы берем POST, да, традиционно он используется для создания сущности, вы попробовали вызвать метод, вам вернулся там тайм-аут, вы не знаете, вам вернулся тайм-аут, потому что ответ к вам не пришел, а сервер уже выполнил запрос, или ваш реквест не дошел, а даже если, например, не дошел ответ, сущность-то уже создана на сервере, сервер ее обработал, создал, получил какой-то ID-шник, но вы этот ID-шник не узнали. +5464.56 5469.04 "Игорь Лабутин" Вы, естественно, делаете retry, как положено в современном облаке. +5469.04 5484.60 "Игорь Лабутин" Допустим, второй retry проходит, но в итоге у вас созданы две сущности, но первая никуда ни к чему не привязана, потому что ее ID-шник потерян, или наоборот, она в каком-нибудь списке будет видеться, и вы, когда получите список сущностей, увидите, что, оказывается, вы создали две. +5484.60 5503.56 "Игорь Лабутин" А если бы был способ понять, что вот создание сущности вы повторяете, на самом деле, то тогда сервер мог бы сообразить, ага, он хочет создать сущность снова, но он же уже пробовал, я уже это обработал, можно не обрабатывать второй раз. +5503.56 5527.68 "Игорь Лабутин" Так вот, способов это сделать, два хороших, это либо вы передаете ключ ID-патентности, то есть некоторые просто искусственный идентификатор, грубо говоря, уникальный идентификатор запроса, который сервер помнит какое-то время у себя и знает, что если к нему повторно придутся таким идентификатором, то просто можно ничего не делать, а вернуть, соответственно, созданную уже там сущность. +5527.68 5556.00 "Игорь Лабутин" Либо же надо просто отдать, то есть нельзя делать никакой генерации, условно говоря, ID-шников на клиенте, то есть этим самым уникальным идентификатором будет являться нечто сгенеренное на клиенте, то есть в этом случае ID-шники генерятся на клиенте, в пост передаются они, вы точно так же трекайте, но вы знаете, что поскольку не вы генерите ID-шник, вы просто увидите, что объект с таким ID уже создан, ну как бы и просто скажите, ну окей, да, уже создан. +5556.00 5567.08 "Анатолий Кулаков" Ну немножко учтите, что этот подход противоречит тому, что после этого вы уже не выбираете хранилище, если у вас ID-шники будут генерироваться на клиенте, уже клиент выбирает в каком хранилище и как вам хранить эти ID-шники. +5567.08 5568.08 "Игорь Лабутин" Да. +5568.08 5583.84 "Игорь Лабутин" И здесь на самом деле, а еще, кстати, есть такой интересный момент, а что делать, допустим, мы используем ключи демпотенности, вы делаете пост и говорите, что сервер понимает, что ага, такой пост я уже обрабатывал. +5583.84 5587.88 "Игорь Лабутин" На самом деле существует два способа обработать такую штуку. +5587.88 5601.00 "Игорь Лабутин" Способ один — вернуть специальный что-то по коду 409, это конфликт, и в принципе вы можете вместе с этим error-кодом вернуть прошлый ответ, да, ID-шник прошлого созданного, например, созданной сущности. +5601.00 5610.32 "Игорь Лабутин" Таким образом клиент поймет, что ну да, он уже созданный, вот конфликт вот с этой сущностью, ага, ну то есть как бы ее мы, этот ID мы и возьмем за создание. +5610.32 5620.32 "Игорь Лабутин" Либо вы можете сделать вид, что вы обрабатываете этот реквест как будто в первый раз и вернуть тот же самый респонс, который вы бы вернули, если бы первый реквест не затаймаутился. +5620.32 5633.44 "Анатолий Кулаков" Я бы тут как раз предложил обратиться к правилу, а клиенту это надо, т.е. клиенту ваши различные результаты нужны, т.е. ему важно, конфликт это или не конфликт, и в большинстве случаев ему не важно, ему нужно получить обратную сущность. +5633.44 5645.76 "Игорь Лабутин" Да, но с другой стороны, нагрузка, ну т.е. как бы программировать сложнее второй вариант, когда нужно получить сущность, потому что вам нужно помнить не только тот факт, что вы этот вопрос обрабатывали, а собственно и полный ответ. +5645.76 5652.72 "Анатолий Кулаков" Ну у тебя есть ключи на импотентности, да, ты по этому ключу на импотентность должен знать, какую сущность породила этот ключ на импотентность, ну какой ответ породил. +5652.72 5653.72 "Анатолий Кулаков" Да-да-да, какой ответ. +5653.72 5661.20 "Анатолий Кулаков" Тут еще один интересный вопрос, ни в какой ли спецификации не сказано, сколько нужно хранить ключи на импотентности, потому что… В спеках я этого нигде не видел. +5661.20 5666.02 "Анатолий Кулаков" Ретрай может прийти через секунду, а может через неделю прийти, и что нам делать, не вечно же их хранить? +5666.02 5675.70 "Игорь Лабутин" В спеках я этого не видел, Золанда, кстати, говорит, что возвращайте заголовки, где будет сказано, сколько он живет у вас. +5675.70 5680.34 "Анатолий Кулаков" Это хорошо, если твои заголовки кто-то прочитал, а если мы говорим, что у нас оборвалась связь, и клиент ретрает. +5680.34 5685.22 "Игорь Лабутин" Все правда, ну я так понимаю, что какой-то стандарт я не видел. +5685.22 5691.12 "Анатолий Кулаков" То есть тут плохо, конечно, что наши ретрай-библиотеки никак не договорились с кэширующими импотентными серверами. +5691.12 5696.76 "Анатолий Кулаков" Было бы неплохо, какой-нибудь стандартный таймаут, после которого чувак не ретрай, не надо. +5696.76 5698.12 "Игорь Лабутин" Ну да. +5698.12 5701.36 "Игорь Лабутин" Так, что у нас ещё интересного? +5701.36 5702.92 "Игорь Лабутин" А вот, про глаголы. +5702.92 5711.04 "Игорь Лабутин" У Майкрософта есть интересная рекомендация, я ей, я бы сказал, никогда не пользуюсь, но, в принципе, подход интересный. +5711.04 5713.52 "Игорь Лабутин" Ажура, я так понимаю, ей пользуется всё время. +5713.52 5720.18 "Игорь Лабутин" Для того, чтобы вы, для создания ресурсов используете только патч или пут. +5720.18 5721.18 "Игорь Лабутин" Пост использовать нельзя. +5721.18 5722.80 "Игорь Лабутин" А почему? +5722.80 5734.66 "Игорь Лабутин" Ну, потому что он типа, ну у них написано, что типа may use post, если вы сделали, короче, всю импотентность, вот это всё, короче, пост не надо. +5734.66 5735.66 "Игорь Лабутин" А патч... +5735.66 5737.46 "Игорь Лабутин" Ну то есть потому, что без импотентности он по-дефритному? +5737.46 5742.78 "Игорь Лабутин" Да, патч тоже же без импотентности, но у патча есть несколько вариаций. +5742.78 5754.74 "Игорь Лабутин" Вот там вот body, который вы передаёте, он может быть разных немножко форматов, и там есть специальный тип, называется то ли мерч патч, мерч патч, по-моему, это называется, короче. +5754.74 5761.46 "Игорь Лабутин" Вот он как раз не будет позволять добавлению коллекции вот этого всего, и за счёт чего он становится и демпатентным. +5761.46 5762.46 "Анатолий Кулаков" Вот. +5762.46 5767.42 "Анатолий Кулаков" Ты говоришь про какой-то стандартный имплементатор и накатыватель патчей, да? +5767.42 5768.42 "Игорь Лабутин" РФЦ 5789. +5768.42 5777.10 "Анатолий Кулаков" Нет, хорошо, а есть ли у нас в дотнете какой-нибудь классик, который возьмёт тебе патчи, поэтому РФЦ его накатит без добавлений, без ничего вот этого? +5777.10 5781.30 "Игорь Лабутин" Наверняка есть библиотечка, не искал, честно говоря, я говорю, что я никогда так не пользовался. +5781.30 5788.62 "Анатолий Кулаков" Ну вот сложно, рекомендовать такие вещи, когда у тебя нет простого способа вот это заиспользовать, а у нас в индустрии пока простого способа чуть ли не полно. +5788.62 5795.26 "Игорь Лабутин" Но с другой стороны, разажур, как бы на этом ажур написан, в частности на шарпе местами, должно быть что-то, наверняка. +5795.26 5800.78 "Анатолий Кулаков" Ну наверное должно, но пока оно не станет как бы стандартом везде, рассчитывать на него довольно странно. +5800.78 5805.66 "Игорь Лабутин" В среднем, конечно, все создают через пост, ну иногда через пуд, такое встречал. +5805.66 5810.06 "Игорь Лабутин" Ну в общем-то всё по методам. +5810.06 5815.98 "Анатолий Кулаков" Смотри, я как раз больше встречал, что люди предпочитают не использовать патч, как раз таки потому, что охрень знает, как его реализовать. +5815.98 5819.98 "Игорь Лабутин" Да он сложный, да, и со стороны фронта в том числе, то есть непонятно как. +5819.98 5829.22 "Игорь Лабутин" Особенно этот стандартный патч, который там с эдремувами, он там очень хитро собирается, этот джейсончик, мы один раз делали такое, нам не понравилось. +5829.22 5841.82 "Игорь Лабутин" Мерч патч, он попроще, но тоже непонятно, то есть может быть действительно пока еще не появилось удобных тулов, так скажем, библиотек и всего остального. +5841.82 5854.46 "Игорь Лабутин" Давай дальше, по заголовкам, ШТТП заголовка имеется в виду, каких-то интересных рекомендаций нет, все говорят ну используйте стандартные, что как бы, они стандартные, не используйте. +5854.46 5868.10 "Игорь Лабутин" А, ну единственное, рекомендации, сейчас в РФЦ уже написано, в РФЦ специальной, в котором написано не используйте префикс x для кастомных заголовков, в долгое время считалось, что нужно все ваши кастомные заголовки начинать с символа x, то есть x-дефис и что-нибудь. +5868.10 5870.74 "Игорь Лабутин" Вот, последняя рекомендация говорит не надо. +5870.74 5873.10 "Игорь Лабутин" А что, вместо него надо? +5873.10 5884.94 "Игорь Лабутин" Написано в РФЦ, я РФЦ почитал, там написано, просто придумайте имя, которое наверняка, про которое вы с достаточной уверенностью можете сказать, что оно не используется, +5884.94 5885.94 "Анатолий Кулаков" точка. +5885.94 5889.62 "Анатолий Кулаков" Ну обычно в такие вещи вставляют или имя продукта, или имя компании. +5889.62 5890.62 "Анатолий Кулаков" Ну да, да. +5890.62 5896.06 "Анатолий Кулаков" Для того, чтобы можно было сразу сказать, что вот этот заголовок, он наверняка относится к этому продукту, потому что заголовков много и так далее. +5896.06 5897.06 "Анатолий Кулаков" Всё так. +5897.06 5899.06 "Анатолий Кулаков" Ну это примерно уникальность тебе какую-то гарантирует. +5899.06 5907.14 "Игорь Лабутин" Да, там в РФЦ что-то такое написано, типа company name, там что-то такое, можно, но при этом у Майкрософта все их стандартные заголовки, они xms, что-то там, но видимо +5907.14 5908.14 "Анатолий Кулаков" исторически. +5908.14 5912.58 "Анатолий Кулаков" Да и, насколько я помню, у всех, и у Гуглова, и у Гитхаба, как бы у всех. +5912.58 5913.58 "Игорь Лабутин" Да. +5913.58 5919.94 "Игорь Лабутин" Ну и примерно осталось два раздела, это версионирование и тот самый пейджинг. +5919.94 5920.94 "Игорь Лабутин" Вот. +5920.94 5927.02 "Игорь Лабутин" Давай про пейджинг сначала немножко, рядом с контрактом пока это самое. +5927.02 5948.50 "Игорь Лабутин" Значит, про пейджинг сказано следующее, что Майкрософт говорит, бывает client-сайт и server-сайт, ну то есть client-сайт это offset-base, когда вам с клиента приходит, хочу там, не знаю, пятую страницу 20 сущностей, а server-сайт это когда вы запрашиваете список, вам сервер возвращает начало этого списка и ссылочка про то, что, а продолжение вот по этой ссылке. +5948.50 5949.50 "Игорь Лабутин" Вот. +5949.50 5956.20 "Игорь Лабутин" Соответственно клиент просто запрашивает, не зная, что там дальше, сколько там будет еще страниц, не страниц и так далее. +5956.20 5971.58 "Игорь Лабутин" Майкрософт говорит, что ну постарайтесь никогда не отдавать total в списках, независимо от как бы пейджинга, не надо считать total, если вам очень надо, сделайте отдельный query-опцию, что типа. +5971.58 5977.66 "Анатолий Кулаков" Слушай, ну сложно не отдавать total, когда ты первый вид используешь, когда тебе перед клиентом нужно показать количество страниц. +5977.66 5982.26 "Игорь Лабутин" Это правда, но тем не менее старайтесь не отдавать +5982.26 5983.26 "Анатолий Кулаков" total. +5983.26 5984.26 "Игорь Лабутин" Тем не менее не отдавать, да. +5984.26 5985.26 "Игорь Лабутин" Да. +5985.26 5987.50 "Игорь Лабутин" Ну типа там, напишите, что там 1, 2, 3 и многоточие. +5987.50 5989.66 "Игорь Лабутин" Так а если он 1? +5989.66 5990.66 "Игорь Лабутин" Вот. +5990.66 6009.90 "Игорь Лабутин" Ну правда, я согласен, да, что скорее всего, конечно, в таком случае вы будете, но рекомендация говорит, что старайтесь избежать total, ну отправьте какой-нибудь там has_next_true, знаешь как это в итераторах C#, has_next и move_next, все. +6009.90 6010.90 "Анатолий Кулаков" Это cursor based по сути. +6010.90 6011.90 "Анатолий Кулаков" Да. +6011.90 6023.38 "Анатолий Кулаков" У этих двух способов есть плюсы и минусы, да, и один как раз таки из минусов того, что тебе в принципе всегда в первом случае приходится total отправлять, но зато во втором не нужно, это его плюс. +6023.38 6034.82 "Игорь Лабутин" Ну и во втором вы можете, да, чуть более стабильные может быть даже результаты возвращать, если вы, например, что-то там, ну хотя в первом тоже теоретически, но… +6034.82 6039.18 "Анатолий Кулаков" Слушай, нам по идее, мне кажется, по версионированию вообще надо отдельную статейку сделать. +6039.18 6040.18 "Анатолий Кулаков" Давай как-нибудь, да. +6040.18 6041.18 "Анатолий Кулаков" Отдельную тему. +6041.18 6042.18 "Анатолий Кулаков" Не по версионированию, это pagination. +6042.18 6054.22 "Анатолий Кулаков" По пейджингу, да, да, потому что оба этих подхода, они прям стоят того, чтобы их обсудить, плюсы, минусы и так далее, потому что там второй у него больше плюсов, но его не всегда можно сделать, там для него есть определённые хаки, в общем, хорошая тема. +6054.22 6055.22 "Анатолий Кулаков" Да. +6055.22 6056.22 "Игорь Лабутин" Можно как-нибудь отдельно её сделать. +6056.22 6058.94 "Игорь Лабутин" Давай посмотрим потом отдельно, ну и давай про версионирование. +6058.94 6073.90 "Игорь Лабутин" В общем, все сходятся из тех статей, которые я читал в основном, вот крупных компаний, все сходятся к тому, что типа не надо использовать версию в Урле, ну хотя Nuget использует, например, да, там API Nuget, там v1, v2, v3. +6073.90 6076.22 "Анатолий Кулаков" Да мне кажется, тоже все большие все используют, +6076.22 6077.22 "Игорь Лабутин" именно в Урле. +6077.22 6078.82 "Игорь Лабутин" Ну вот Microsoft не использует. +6078.82 6079.82 "Игорь Лабутин" Уже молодец. +6079.82 6086.26 "Игорь Лабутин" Да, Zalando не использует, а у Zalando вообще прикольное это самое, у них просто рекомендация, should avoid 6086.26 6087.26 UNKNOWN versioning. -6087.26 6091.70 SPEAKER_01 Т.е. как бы вот типа не надо использовать вершинк вообще. -6091.70 6094.98 SPEAKER_01 Модифицируйте ваши API так, чтобы версионирование было не нужно. -6094.98 6121.54 SPEAKER_00 И они недалеки от правды, потому что знаешь, когда самого Роя Филдинга спросили, а где нужно версию указывать, в Урле там или в заголовке или ещё где-то, и он твитанул, что типа если вы указываете версию в своём API, то вы по сути посылаете в задницу весь в REST, потому что весь REST как раз создан именно для того, чтобы быть мегагибким и указывая версию, вы по сути ломаете весь его -6121.54 6122.54 SPEAKER_01 принцип. -6122.54 6123.54 SPEAKER_01 Да. -6123.54 6154.58 SPEAKER_01 Значит, надо сказать, что Microsoft, что Zalando, тут Microsoft неплохо сформулировали, у них написано следующее в принципах своих с точки зрения дизайна API, что заказчик никогда не, ну как бы код заказчика никогда не должен сломаться, если вы меняете сервис, а с другой стороны, а заказчик должен уметь переключиться на новую версию сервиса без необходимости менять код. -6154.58 6166.94 SPEAKER_01 Звучит очень абстрактно, но они, я так подозреваю, под этим понимают тот факт, что если вы как бы используете там v1, v2 в URL, то скорее всего им придется все-таки довольно сильно менять. -6166.94 6186.22 SPEAKER_01 Я не очень понимаю, почему их подход, они призывают использовать query параметр, почему он как-то чем-то отличается от версии в URL с точки зрения изменения кода клиента, и там либо это как-то параметризуется, либо это, не знаю, через конфиг задается, не знаю. -6186.22 6187.90 SPEAKER_01 Ну вот их парадигма такая. -6187.90 6200.42 SPEAKER_01 Думал, давайте это сделаем так, чтобы кастомер мог начать использовать новую версию сервиса без необходимости, соответственно, его менять, ну свой код. -6200.42 6211.90 SPEAKER_01 И Microsoft говорит, мы используем query параметр, причем у них для версии используется формат, не как все привыкли, там 1.0.1.1.1.2, у них для версии используется формат вида дата. -6211.90 6238.34 SPEAKER_01 Не знаю, пользуются какими-нибудь ажурскими API, но там действительно так, вы передаёте специальный query параметр, называется API version, причем если его не передать, то это ошибка, это 400, и вам в ответе пролетит, что API version обязательно, и туда нужно передать дату, ну из well-known, так скажем, списка дат, вида там год, месяц, день, они вот так вот идентифицируют свои версии, просто датой, когда она была зарелижена. -6238.34 6241.14 SPEAKER_01 Ну нормальный формат, почему бы и нет. -6241.14 6259.02 SPEAKER_01 Да, The London, наоборот, говорит, что типа в, ну он тоже говорит, что в url-е нельзя, ни в коем случае, если очень надо, то мы версионируем в media type, то есть не отдельным заголовком, а прямо в media type, то есть у вас там будет какой-нибудь там application.json, точка запятой, API version равно 5. -6259.02 6260.02 SPEAKER_01 Вот. -6260.02 6276.78 SPEAKER_00 Это как раз соответствует одному из принципов, что ресурсы, они должны быть стабильными, то есть от версии они не должны меняться, поскольку были юзеры, значит, они и остались юзерами, а то какой они версии, грубо говоря, или в каком формате, это всё определяется другими атрибутами, это не определяется этим адресом ресурса. -6276.78 6285.30 SPEAKER_01 Да, именно так, но я вот не знаю, мне кажется, что подавляющее большинство народу версионируют именно url-ами. -6285.30 6288.70 SPEAKER_01 Я могу ошибаться, но мне кажется, что это подавляющее большинство опишек, которые я встречаю. -6288.70 6298.62 SPEAKER_00 Я бы, по моему опыту, сказал, что в разноброс, где-то по поровну, и url-ами, и query-ами, и header-ами, и вообще не версионируют. -6298.62 6309.22 SPEAKER_00 Кстати, если бы мы пользовались hypermedia, то там бы все url-ы пользовались бы динамически, и таким образом люди делают так, что сервер сам решает, на какой url тебя послать. -6309.22 6313.42 SPEAKER_00 И клиент, как бы не зная url-а, он ходит по тому, куда его пошлют. -6313.42 6315.74 SPEAKER_00 И вот таким образом они делают прозрачное версионирование. -6315.74 6320.98 SPEAKER_00 Более того, они делают его постепенным, потому что для половины клиентов отдаётся один url, а для половины другой. -6320.98 6321.98 SPEAKER_00 В зависимости от чего-то. -6321.98 6322.98 SPEAKER_01 Да. -6322.98 6328.90 SPEAKER_01 Ну и последний момент касательно версионирования, я не знал, кстати, что такое существует. -6328.90 6332.14 SPEAKER_01 Короче, у нас теперь есть 2 rfc на 2 новых заголовка в респонсах. -6332.14 6335.02 SPEAKER_01 Один называется deprecation, второй называется sunset. -6335.02 6337.02 SPEAKER_01 Прям вот так вот они и называются. -6337.02 6338.02 SPEAKER_01 И они должны вызывать. -6338.02 6370.22 SPEAKER_01 То есть, если вы планируете, как владелец API, какие-то методы убирать, там, obsolетить или ещё что-то, этого, конечно, делать не надо, но иногда приходится, то сначала вы должны навесить header deprecation, где будет написана дата, когда он планируется к deprecation, а как только наступила эта дата, вы должны повесить header sunset, насколько я помню, в котором будет написана дата, согласованная, конечно, с потребителями и достаточно далёкая в будущем, после которой этот метод может быть отключен. -6370.22 6375.46 SPEAKER_00 Ну, то есть, одного не хватило, ты будешь, да, предупреждаю второй раз называть. -6375.46 6377.98 SPEAKER_00 Ну, типа warning error, да, типа такого. -6377.98 6378.98 SPEAKER_01 Вот. -6378.98 6379.98 SPEAKER_01 Ну, как-то так. -6379.98 6385.10 SPEAKER_01 То есть, я не видел, что такие хедеры появились и как бы да, rfc-шка даже есть на них новая. -6385.10 6387.06 SPEAKER_01 Ну прикольно, я тоже не встречал ещё. -6387.06 6388.06 SPEAKER_01 Вот. -6388.06 6389.42 SPEAKER_01 Ну и в реальной жизни я их пока не встречал. -6389.42 6392.94 SPEAKER_01 Но вот в Zalando уже прям, уже добавлены. -6392.94 6394.42 SPEAKER_01 Ну вот примерно такие дела. -6394.42 6396.90 SPEAKER_00 То есть, оно не версионирует, но деприкетит, да? -6396.90 6399.90 SPEAKER_01 Ну да, деприкетить можно, ничего, мы версии не меняем. -6399.90 6400.90 SPEAKER_01 А версионировать не надо? -6400.90 6401.90 SPEAKER_01 А версионировать не надо? -6401.90 6406.94 SPEAKER_01 Не, у них, кстати, написано, что один из самых хороших способов – это типа добавьте просто отдельный метод. -6406.94 6407.94 SPEAKER_01 Ну, отдельный. -6407.94 6410.10 SPEAKER_00 Ну, тогда, но просто деприкет этого не подразумевает. -6410.10 6411.10 SPEAKER_00 Ну да. -6411.10 6413.02 SPEAKER_00 То есть, по сути, деприкет – это и есть версионирование. -6413.02 6414.02 SPEAKER_00 Да. -6414.02 6417.86 SPEAKER_00 Как только ты деприкетишь старый метод, это значит, что у тебя там скоро поменяется мажор, грубо говоря. -6417.86 6418.86 SPEAKER_00 Скоро breaking changes будет. -6418.86 6419.86 SPEAKER_00 Это и есть версионирование. -6419.86 6422.00 SPEAKER_01 Ну, такое, незаметное для пользователя. -6422.00 6427.86 SPEAKER_01 Если кто-то не пользуется этим методом, ему не нужно переключаться на V2 или еще на что-нибудь ради новых фич других методов. -6427.86 6428.86 SPEAKER_01 Ладно. -6428.86 6431.86 SPEAKER_01 Ну как, на сегодня покрыли? -6431.86 6434.70 SPEAKER_01 Да, я думаю, что на сегодня это самое. -6434.70 6441.18 SPEAKER_01 Больше длинных статей мы брать, наверное, не будем, давай еще пробежимся кратенько о разном у нас чуть-чуть тут есть. -6441.18 6442.18 SPEAKER_01 Давай. -6442.18 6443.18 SPEAKER_01 Всяких разных. -6443.18 6444.86 SPEAKER_01 Я попробую не очень задерживаться. -6444.86 6471.10 SPEAKER_01 Несмотря на то, что у нас нету новостей от Microsoft в виде прям больших статей, которые было бы прикольно обсудить, там, превью или еще что-нибудь в таком духе, у нас есть, периодически возникают всякие разные штуки про, из GitHub у Microsoft, один из таких кейсов — это заведенный тикет в ISP.NET Core-овском репозитории под названием Eventing Framework в девятом дотнете. -6471.10 6474.62 SPEAKER_01 Вот если бы ты услышал Eventing Framework, что тебе приходит в голову? -6474.62 6484.62 SPEAKER_00 Тем более в девятом дотнете, но я думаю, сейчас прям такую выпустят мега-фреймворк, который будет все подряд консумить, все позит-хендлить, обрабатывать, и комплекс event-процессинг и все такое. -6484.62 6487.82 SPEAKER_01 Вот, и недалеко от истины примерно так же подумал весь интернет. -6487.82 6500.26 SPEAKER_01 В итоге в GitHub issue сейчас, вот на момент, когда я смотрел, не сейчас, это было несколько дней назад, 120 комментов уже, и это не технический комментарий, это очередное обсуждение open source versus Microsoft. -6500.26 6508.50 SPEAKER_01 Короче, типа вот, там половина народу, как обычно, типа вот, вы сейчас делаете свой убер-фреймворк, как ты сказал, да? -6508.50 6516.26 SPEAKER_01 И тем самым, короче, всякие вот наши, значит, open source-ные подели будут больше не нужны, и все начнут пользоваться вами, и вообще, что вы делаете? -6516.26 6527.38 SPEAKER_01 С другой стороны, народ говорит, что типа, наконец-таки Microsoft что-то, ну как с логгингом, короче, да, вот этот DI, как бы, контракт есть, да, дальше логгеры, пожалуйста, сериалок никто не убивал, бери да пользуйся. -6527.38 6536.10 SPEAKER_00 Да так же точно, как и с Aspire, да, все 10 лет пытались что-то нагромоздить на коленке, у них ничего не случилось, а тут Microsoft выкатил кусок, как бы, недоделанного чего-то, и все счастливы. -6536.10 6595.86 SPEAKER_01 Короче, в среднем интернет считал, что будет убер-мега-пупер-штука, но потом пришел Дэвид Фаулер, по-моему, Фаулер, и сказал, ну вообще-то, вообще-то, мы собирались сфокусироваться на очень маленьком подножестве event-хендлинга, а именно, что происходит, то есть, как удобно консумить ивенты из вот этих всяких, там, сервис-басов и прочего в контексте Azure-фанкшенов и Azure-веб-джобов, и сделать вот эту вот модель того, как консумить ивенты, похожую на minimal API, все, вот, то есть, типа, мы просто хотим сделать такой простой контракт поверх, как бы, поверх, скажем так, идей, которые, можете посмотреть, сайтик такой есть cloudevents.io, вот, там есть некоторое описание, попытка стандартизации, да, они говорят, что, ну, мы сделаем это, по сути, очень похоже на minimal API, там тоже будут middlewires для выработки ивентов, ну, такой, типа, не знаю, на медиатор, может, похоже будет, черт знает, фильтры и все. -6595.86 6600.94 SPEAKER_00 А что было не назвать minimal-events какой-нибудь, они не вводили в людей воплосы, нет, фреймворки там. -6600.94 6607.38 SPEAKER_01 Вот, короче, поглядим, что будет, 120 комментов не предел, ну, посмотрим, во что это выльется. -6607.38 6616.98 SPEAKER_01 Дальше, в C#-овом репозитории нашлась штука под названием C# log statement pattern, причем она уже чуть ли не там реализована, и вот-вот скоро будет. -6616.98 6649.54 SPEAKER_01 Штука следующая, вы сейчас можете внутри использовать любой тип, любой instance, точнее, любого типа внутри конструкции log, да, есть ключевое слово log, вы передаете, значит, в круглый скобочек какой-то instance, дальше в фигурных скобочках что-то пишете, тело, и, соответственно, через monitor-enter, monitor-exit, да, происходит блокировка на этом объекте, и пока какой-то кусочек, один поток выполняется внутри этого лога, другие потоки не будут выполняться. -6649.54 6685.02 SPEAKER_01 Скорее всего, в 9-ом дотнете появится специальный тип system.trading.log, который будет, можно использовать внутри лога, ходят слухи, что в каком-нибудь 10-ом дотнете, грубо говоря, в 11-ом, ну, короче, через несколько лет, когда все это аккуратно задеприкейтит, внутри лог можно будет использовать только этот специальный тип, но пока как бы просто добавят новый тип, и если бы его просто добавили, то никакая как бы хитрая логика внутри этого типа, они, видимо, хотят какую-то хитрую логику сделать в блокировок, я даже потом могу как-нибудь отдельно рассказать, зачем эта идея движется. -6685.02 6725.02 SPEAKER_01 Короче, если сделать его просто добавить, даже какую-то хитрую логику внутри не написал, ключевое слово log, внутренней логики типа не работает никак, поэтому теперь у нас будет новый маркерный интерфейс, называется ilogpattern, и если этот интерфейс реализован, в нём нет методов, но в нём должен быть метод под названием enterLogScope, который возвращает специальный ref struct, у которого есть dispose, и тогда, если тип, который вы передали в ключевое слово log, в конструкцию log, резвит этот ilogpattern, то вместо monitorEnter будет вызван вот этот enterLogScope метод. -6725.02 6730.06 SPEAKER_00 Ну, это богатая идея, можно свои monitorLogs иметь, значит, это более другое. -6730.06 6731.06 SPEAKER_01 Да-да-да. -6731.06 6732.06 SPEAKER_00 Можно будет касаться. -6732.06 6737.50 SPEAKER_00 Название только дурацкое, то есть это как disposable для ютинга, у нас теперь будет для лога тоже такой интерфейс. -6737.50 6738.50 SPEAKER_01 Типа того. -6738.50 6740.34 SPEAKER_01 Да-да-да, вот ровно оно, по сути. -6740.34 6746.38 SPEAKER_01 Только в dispose понятно, что там только один выходной метод есть, а здесь будет два, на вход и на выход. -6746.38 6750.82 SPEAKER_01 Посмотрим, к чему приведёт, на самом деле, да, вся эта история делается ровно для одного. -6750.82 6767.70 SPEAKER_01 Если сделать вот такой специальный log-тип, который будет, собственно, реализовать некоторую логику логов, а в каком-то дунете запретить использование внутри конструкции лог любых типов, кроме этого типа, то знаешь, что можно сделать? -6767.70 6772.18 SPEAKER_00 Узнать, прооптимизировать абсолютно все объекты, которые хранят этот дурацкий флажочек у себя в ядерах. -6772.18 6778.58 SPEAKER_01 Именно, мало того, что флажочек они хранят не только флажочек, там получится выкинуть, короче, из заголовка объекта кучу всего. -6778.58 6787.26 SPEAKER_00 Ну вот у меня прям с первых версий C# сразу был такой ступор, нафига они задумали все объекты лочить, почему нельзя было сделать отдельный класс? -6787.26 6790.58 SPEAKER_00 Потому что никто никогда не хочет лочить просто абсолютно всё. -6790.58 6794.94 SPEAKER_00 Все делают свой какой-нибудь классик по бестпрактисам всем, и только этот классик лочат. -6794.94 6797.98 SPEAKER_01 Скорее всего, наследие Java, потому что синхронайст и вот это всё. -6797.98 6800.98 SPEAKER_00 Там тоже можно, но это… Во всём виноваты эти личаисты. -6800.98 6819.14 SPEAKER_01 Ну, короче, смысл в том, что, да, глобальная такая идея – это пока не цель, это пока идея, а можно ли у объекта выкинуть вот этот заголовок, где хранится лог, где хранится ещё хэшкод, кстати, иногда, а иногда лог, а иногда хэшкод, в зависимости от того, использовали вы объект в лог или не использовали. -6819.14 6827.86 SPEAKER_01 Вот, там ещё хранится пачка некоторых битовых флагов, короче, там есть идеи, как его можно порезать, чтобы мы поменьше кушали в памяти. -6827.86 6828.86 SPEAKER_01 Вот. -6828.86 6831.90 SPEAKER_01 Последим, посмотрим, к чему это всё приведёт. -6831.90 6832.90 SPEAKER_01 Сериолог трейсинг. -6832.90 6852.78 SPEAKER_01 Мы в прошлый раз как раз рассказывали про СЕК новый, который позволяет, по-моему, что он там, OTLP, да, open telemetry провайдерам теперь быть, всё это в себя собирать, и мы там упоминали, что вот есть библиотечка сериолог трейсинг, удобный, client-side, все дела, вышла статья, в которой прямо описано, как ей пользоваться, что она даёт, так что посмотрите. -6852.78 6861.58 SPEAKER_00 Ну, не просто статья, а статья Никаса Блумхарта, как раз автора СЕКа и сериолога, и всех вместе взятых, у него классный блог, если ещё не подписаны, то тоже рекомендуем. -6861.58 6862.58 SPEAKER_01 Да. -6862.58 6875.14 SPEAKER_01 В .NET 9 продолжается работа над генерацией, удобной генерацией ИЛИ кода, я напоминаю, что когда мы получили .NET Core, у нас был, отрезана, на самом деле, возможность кода генерации некоторая, сейчас вот потихонечку это всё возвращается. -6875.14 6880.66 SPEAKER_01 Короче, в .NET 9 должен полностью AssemblyBuilder.save уже нормально работать со всеми нужными приседаниями. -6880.66 6901.70 SPEAKER_01 В .NET 9 уже заимплементили три новых link_you метода, мало ли вам не хватало, это count_by и aggregate_by, то есть вы можете просто, ну, count - это просто считал элементы коллекции, можно сказать count_by и передать делегатик, по какому полю считать, собственно, эти самые, или агрегировать сущности. -6901.70 6917.98 SPEAKER_01 И есть ещё теперь новый метод index, раньше, если вы хотели итерировать коллекцию так, чтобы вам возвращался и сущность, и её индекс в этой коллекции, нужно было писать замечательную конструкцию там, select item_index и вернуть tuple, соответственно, из item_index, теперь для этого у нас есть отдельный метод index. -6917.98 6942.58 SPEAKER_01 И последнее, что у нас есть из краткого, это то, что mstest до сих пор жив, и Microsoft выпустил mstestrunner, это, короче, штука, которая позволяет вам теперь собрать ваш проект с тестами, напоминаю, мстестовый проект, раньше, как и на самом деле во многих других тестовых фреймворках, это .dll, и вам нужен какой-то специальный раннер, который её будет запускать. -6942.58 6948.62 SPEAKER_01 В XUnity, по-моему, сейчас в последнем вроде как они собрались сделать .exe, или даже сделали уже, что XUnity -6948.62 6949.62 SPEAKER_00 генерирует .exe. -6949.62 6953.46 SPEAKER_00 Ну, при альфе, который у них есть, да, тоже сделали. -6953.46 6954.46 SPEAKER_01 Вот. -6954.46 6983.54 SPEAKER_01 У mstest теперь есть следующее, что вы можете взять в вашем тест-продже, добавить, ну, get_packet, специально называется mstest.adapter, тест-адаптер, поставить опцию enable mstestrunner, и в output type вместо .dll написать .exe, после чего у вас берётся executable, который, во-первых, не требует никаких там продуктных тестов, visual studio, mstestconsole, вообще никаких других раннеров он не требует, он полностью самодостаточен, то есть его можно отлаживать, его можно делать чего угодно. -6983.54 6994.02 SPEAKER_01 Вы можете таким образом, как ни странно, собрать какой-нибудь там кроссплатформенный тест, в смысле на винде собрать тест, который юнит-тестом запустится на линуксе, ну, например. -6994.02 6995.02 SPEAKER_01 Вот. -6995.02 6998.34 SPEAKER_01 И вы можете его отлаживать, как обычное приложение, всё такое. -6998.34 7013.86 SPEAKER_01 И при этом это всё ещё работает быстрее, то есть они меряли, там, на некоторых тестах, там, скорость увеличивается раза в три, за счёт того, что нет вот этого межпроцессного взаимодействия между хостом, который контролирует раны вашего теста, и тем процессом, который загружает ваши сборки с тестами. -7013.86 7014.86 SPEAKER_00 Примерно так. -7014.86 7019.26 SPEAKER_00 Ну, отлично, в принципе, смотри, сколько нововведений оказывается. -7019.26 7020.26 SPEAKER_00 А мы зря Microsoft ругали. -7020.26 7021.26 SPEAKER_00 Что они делают? -7021.26 7029.26 SPEAKER_01 Да, что-то делают, потихонечку какие-то вмещения выходят, мы просто всё ждём какого-нибудь превью уже нормального, там наверняка будет что-нибудь интересное и масштабное и мега суперкрутое для девятки. -7029.26 7030.26 SPEAKER_01 Но посмотрим. -7030.26 7038.34 SPEAKER_00 Да, хорошо, подождём, и как только будет, мы вам обязательно об этом расскажем, поэтому никуда не уходите, подписывайтесь и всех остальных тоже зовите подписываться. -7038.34 7039.90 SPEAKER_00 Давай, на сегодня, наверное, хватит нам. -7039.90 7047.22 SPEAKER_01 Да, на сегодня нам хватит, мы посмотрели на Andrew Locke и вспомнили, что такое дефолтные методы интерфейсов или реализации. -7047.22 7062.18 SPEAKER_01 Мы узнали Aspire Roadmap, посмотрели на байнари-форматер и чем его теперь заменять, подробнейшим образом обсудили различные аспекты того, как можно дизайнить REST API, ну и много мелочей от Microsoft в основном, но не только от Microsoft, тоже -7062.18 7063.18 SPEAKER_00 было. -7063.18 7068.86 SPEAKER_00 Всем спасибо за прослушивание, заходите ещё и увидимся. -7068.86 7069.86 SPEAKER_00 До новых встреч, пока. -7069.86 7070.46 SPEAKER_00 Пока. -7070.46 7085.50 SPEAKER_00 [Музыка] +6087.26 6091.70 "Игорь Лабутин" Т.е. как бы вот типа не надо использовать вершинк вообще. +6091.70 6094.98 "Игорь Лабутин" Модифицируйте ваши API так, чтобы версионирование было не нужно. +6094.98 6121.54 "Анатолий Кулаков" И они недалеки от правды, потому что знаешь, когда самого Роя Филдинга спросили, а где нужно версию указывать, в Урле там или в заголовке или ещё где-то, и он твитанул, что типа если вы указываете версию в своём API, то вы по сути посылаете в задницу весь в REST, потому что весь REST как раз создан именно для того, чтобы быть мегагибким и указывая версию, вы по сути ломаете весь его +6121.54 6122.54 "Игорь Лабутин" принцип. +6122.54 6123.54 "Игорь Лабутин" Да. +6123.54 6154.58 "Игорь Лабутин" Значит, надо сказать, что Microsoft, что Zalando, тут Microsoft неплохо сформулировали, у них написано следующее в принципах своих с точки зрения дизайна API, что заказчик никогда не, ну как бы код заказчика никогда не должен сломаться, если вы меняете сервис, а с другой стороны, а заказчик должен уметь переключиться на новую версию сервиса без необходимости менять код. +6154.58 6166.94 "Игорь Лабутин" Звучит очень абстрактно, но они, я так подозреваю, под этим понимают тот факт, что если вы как бы используете там v1, v2 в URL, то скорее всего им придется все-таки довольно сильно менять. +6166.94 6186.22 "Игорь Лабутин" Я не очень понимаю, почему их подход, они призывают использовать query параметр, почему он как-то чем-то отличается от версии в URL с точки зрения изменения кода клиента, и там либо это как-то параметризуется, либо это, не знаю, через конфиг задается, не знаю. +6186.22 6187.90 "Игорь Лабутин" Ну вот их парадигма такая. +6187.90 6200.42 "Игорь Лабутин" Думал, давайте это сделаем так, чтобы кастомер мог начать использовать новую версию сервиса без необходимости, соответственно, его менять, ну свой код. +6200.42 6211.90 "Игорь Лабутин" И Microsoft говорит, мы используем query параметр, причем у них для версии используется формат, не как все привыкли, там 1.0.1.1.1.2, у них для версии используется формат вида дата. +6211.90 6238.34 "Игорь Лабутин" Не знаю, пользуются какими-нибудь ажурскими API, но там действительно так, вы передаёте специальный query параметр, называется API version, причем если его не передать, то это ошибка, это 400, и вам в ответе пролетит, что API version обязательно, и туда нужно передать дату, ну из well-known, так скажем, списка дат, вида там год, месяц, день, они вот так вот идентифицируют свои версии, просто датой, когда она была зарелижена. +6238.34 6241.14 "Игорь Лабутин" Ну нормальный формат, почему бы и нет. +6241.14 6259.02 "Игорь Лабутин" Да, The London, наоборот, говорит, что типа в, ну он тоже говорит, что в url-е нельзя, ни в коем случае, если очень надо, то мы версионируем в media type, то есть не отдельным заголовком, а прямо в media type, то есть у вас там будет какой-нибудь там application.json, точка запятой, API version равно 5. +6259.02 6260.02 "Игорь Лабутин" Вот. +6260.02 6276.78 "Анатолий Кулаков" Это как раз соответствует одному из принципов, что ресурсы, они должны быть стабильными, то есть от версии они не должны меняться, поскольку были юзеры, значит, они и остались юзерами, а то какой они версии, грубо говоря, или в каком формате, это всё определяется другими атрибутами, это не определяется этим адресом ресурса. +6276.78 6285.30 "Игорь Лабутин" Да, именно так, но я вот не знаю, мне кажется, что подавляющее большинство народу версионируют именно url-ами. +6285.30 6288.70 "Игорь Лабутин" Я могу ошибаться, но мне кажется, что это подавляющее большинство опишек, которые я встречаю. +6288.70 6298.62 "Анатолий Кулаков" Я бы, по моему опыту, сказал, что в разноброс, где-то по поровну, и url-ами, и query-ами, и header-ами, и вообще не версионируют. +6298.62 6309.22 "Анатолий Кулаков" Кстати, если бы мы пользовались hypermedia, то там бы все url-ы пользовались бы динамически, и таким образом люди делают так, что сервер сам решает, на какой url тебя послать. +6309.22 6313.42 "Анатолий Кулаков" И клиент, как бы не зная url-а, он ходит по тому, куда его пошлют. +6313.42 6315.74 "Анатолий Кулаков" И вот таким образом они делают прозрачное версионирование. +6315.74 6320.98 "Анатолий Кулаков" Более того, они делают его постепенным, потому что для половины клиентов отдаётся один url, а для половины другой. +6320.98 6321.98 "Анатолий Кулаков" В зависимости от чего-то. +6321.98 6322.98 "Игорь Лабутин" Да. +6322.98 6328.90 "Игорь Лабутин" Ну и последний момент касательно версионирования, я не знал, кстати, что такое существует. +6328.90 6332.14 "Игорь Лабутин" Короче, у нас теперь есть 2 rfc на 2 новых заголовка в респонсах. +6332.14 6335.02 "Игорь Лабутин" Один называется deprecation, второй называется sunset. +6335.02 6337.02 "Игорь Лабутин" Прям вот так вот они и называются. +6337.02 6338.02 "Игорь Лабутин" И они должны вызывать. +6338.02 6370.22 "Игорь Лабутин" То есть, если вы планируете, как владелец API, какие-то методы убирать, там, obsolетить или ещё что-то, этого, конечно, делать не надо, но иногда приходится, то сначала вы должны навесить header deprecation, где будет написана дата, когда он планируется к deprecation, а как только наступила эта дата, вы должны повесить header sunset, насколько я помню, в котором будет написана дата, согласованная, конечно, с потребителями и достаточно далёкая в будущем, после которой этот метод может быть отключен. +6370.22 6375.46 "Анатолий Кулаков" Ну, то есть, одного не хватило, ты будешь, да, предупреждаю второй раз называть. +6375.46 6377.98 "Анатолий Кулаков" Ну, типа warning error, да, типа такого. +6377.98 6378.98 "Игорь Лабутин" Вот. +6378.98 6379.98 "Игорь Лабутин" Ну, как-то так. +6379.98 6385.10 "Игорь Лабутин" То есть, я не видел, что такие хедеры появились и как бы да, rfc-шка даже есть на них новая. +6385.10 6387.06 "Игорь Лабутин" Ну прикольно, я тоже не встречал ещё. +6387.06 6388.06 "Игорь Лабутин" Вот. +6388.06 6389.42 "Игорь Лабутин" Ну и в реальной жизни я их пока не встречал. +6389.42 6392.94 "Игорь Лабутин" Но вот в Zalando уже прям, уже добавлены. +6392.94 6394.42 "Игорь Лабутин" Ну вот примерно такие дела. +6394.42 6396.90 "Анатолий Кулаков" То есть, оно не версионирует, но деприкетит, да? +6396.90 6399.90 "Игорь Лабутин" Ну да, деприкетить можно, ничего, мы версии не меняем. +6399.90 6400.90 "Игорь Лабутин" А версионировать не надо? +6400.90 6401.90 "Игорь Лабутин" А версионировать не надо? +6401.90 6406.94 "Игорь Лабутин" Не, у них, кстати, написано, что один из самых хороших способов – это типа добавьте просто отдельный метод. +6406.94 6407.94 "Игорь Лабутин" Ну, отдельный. +6407.94 6410.10 "Анатолий Кулаков" Ну, тогда, но просто деприкет этого не подразумевает. +6410.10 6411.10 "Анатолий Кулаков" Ну да. +6411.10 6413.02 "Анатолий Кулаков" То есть, по сути, деприкет – это и есть версионирование. +6413.02 6414.02 "Анатолий Кулаков" Да. +6414.02 6417.86 "Анатолий Кулаков" Как только ты деприкетишь старый метод, это значит, что у тебя там скоро поменяется мажор, грубо говоря. +6417.86 6418.86 "Анатолий Кулаков" Скоро breaking changes будет. +6418.86 6419.86 "Анатолий Кулаков" Это и есть версионирование. +6419.86 6422.00 "Игорь Лабутин" Ну, такое, незаметное для пользователя. +6422.00 6427.86 "Игорь Лабутин" Если кто-то не пользуется этим методом, ему не нужно переключаться на V2 или еще на что-нибудь ради новых фич других методов. +6427.86 6428.86 "Игорь Лабутин" Ладно. +6428.86 6431.86 "Игорь Лабутин" Ну как, на сегодня покрыли? +6431.86 6434.70 "Игорь Лабутин" Да, я думаю, что на сегодня это самое. +6434.70 6441.18 "Игорь Лабутин" Больше длинных статей мы брать, наверное, не будем, давай еще пробежимся кратенько о разном у нас чуть-чуть тут есть. +6441.18 6442.18 "Игорь Лабутин" Давай. +6442.18 6443.18 "Игорь Лабутин" Всяких разных. +6443.18 6444.86 "Игорь Лабутин" Я попробую не очень задерживаться. +6444.86 6471.10 "Игорь Лабутин" Несмотря на то, что у нас нету новостей от Microsoft в виде прям больших статей, которые было бы прикольно обсудить, там, превью или еще что-нибудь в таком духе, у нас есть, периодически возникают всякие разные штуки про, из GitHub у Microsoft, один из таких кейсов — это заведенный тикет в ISP.NET Core-овском репозитории под названием Eventing Framework в девятом дотнете. +6471.10 6474.62 "Игорь Лабутин" Вот если бы ты услышал Eventing Framework, что тебе приходит в голову? +6474.62 6484.62 "Анатолий Кулаков" Тем более в девятом дотнете, но я думаю, сейчас прям такую выпустят мега-фреймворк, который будет все подряд консумить, все позит-хендлить, обрабатывать, и комплекс event-процессинг и все такое. +6484.62 6487.82 "Игорь Лабутин" Вот, и недалеко от истины примерно так же подумал весь интернет. +6487.82 6500.26 "Игорь Лабутин" В итоге в GitHub issue сейчас, вот на момент, когда я смотрел, не сейчас, это было несколько дней назад, 120 комментов уже, и это не технический комментарий, это очередное обсуждение open source versus Microsoft. +6500.26 6508.50 "Игорь Лабутин" Короче, типа вот, там половина народу, как обычно, типа вот, вы сейчас делаете свой убер-фреймворк, как ты сказал, да? +6508.50 6516.26 "Игорь Лабутин" И тем самым, короче, всякие вот наши, значит, open source-ные подели будут больше не нужны, и все начнут пользоваться вами, и вообще, что вы делаете? +6516.26 6527.38 "Игорь Лабутин" С другой стороны, народ говорит, что типа, наконец-таки Microsoft что-то, ну как с логгингом, короче, да, вот этот DI, как бы, контракт есть, да, дальше логгеры, пожалуйста, сериалок никто не убивал, бери да пользуйся. +6527.38 6536.10 "Анатолий Кулаков" Да так же точно, как и с Aspire, да, все 10 лет пытались что-то нагромоздить на коленке, у них ничего не случилось, а тут Microsoft выкатил кусок, как бы, недоделанного чего-то, и все счастливы. +6536.10 6595.86 "Игорь Лабутин" Короче, в среднем интернет считал, что будет убер-мега-пупер-штука, но потом пришел Дэвид Фаулер, по-моему, Фаулер, и сказал, ну вообще-то, вообще-то, мы собирались сфокусироваться на очень маленьком подножестве event-хендлинга, а именно, что происходит, то есть, как удобно консумить ивенты из вот этих всяких, там, сервис-басов и прочего в контексте Azure-фанкшенов и Azure-веб-джобов, и сделать вот эту вот модель того, как консумить ивенты, похожую на minimal API, все, вот, то есть, типа, мы просто хотим сделать такой простой контракт поверх, как бы, поверх, скажем так, идей, которые, можете посмотреть, сайтик такой есть cloudevents.io, вот, там есть некоторое описание, попытка стандартизации, да, они говорят, что, ну, мы сделаем это, по сути, очень похоже на minimal API, там тоже будут middlewires для выработки ивентов, ну, такой, типа, не знаю, на медиатор, может, похоже будет, черт знает, фильтры и все. +6595.86 6600.94 "Анатолий Кулаков" А что было не назвать minimal-events какой-нибудь, они не вводили в людей воплосы, нет, фреймворки там. +6600.94 6607.38 "Игорь Лабутин" Вот, короче, поглядим, что будет, 120 комментов не предел, ну, посмотрим, во что это выльется. +6607.38 6616.98 "Игорь Лабутин" Дальше, в C#-овом репозитории нашлась штука под названием C# log statement pattern, причем она уже чуть ли не там реализована, и вот-вот скоро будет. +6616.98 6649.54 "Игорь Лабутин" Штука следующая, вы сейчас можете внутри использовать любой тип, любой instance, точнее, любого типа внутри конструкции log, да, есть ключевое слово log, вы передаете, значит, в круглый скобочек какой-то instance, дальше в фигурных скобочках что-то пишете, тело, и, соответственно, через monitor-enter, monitor-exit, да, происходит блокировка на этом объекте, и пока какой-то кусочек, один поток выполняется внутри этого лога, другие потоки не будут выполняться. +6649.54 6685.02 "Игорь Лабутин" Скорее всего, в 9-ом дотнете появится специальный тип system.trading.log, который будет, можно использовать внутри лога, ходят слухи, что в каком-нибудь 10-ом дотнете, грубо говоря, в 11-ом, ну, короче, через несколько лет, когда все это аккуратно задеприкейтит, внутри лог можно будет использовать только этот специальный тип, но пока как бы просто добавят новый тип, и если бы его просто добавили, то никакая как бы хитрая логика внутри этого типа, они, видимо, хотят какую-то хитрую логику сделать в блокировок, я даже потом могу как-нибудь отдельно рассказать, зачем эта идея движется. +6685.02 6725.02 "Игорь Лабутин" Короче, если сделать его просто добавить, даже какую-то хитрую логику внутри не написал, ключевое слово log, внутренней логики типа не работает никак, поэтому теперь у нас будет новый маркерный интерфейс, называется ilogpattern, и если этот интерфейс реализован, в нём нет методов, но в нём должен быть метод под названием enterLogScope, который возвращает специальный ref struct, у которого есть dispose, и тогда, если тип, который вы передали в ключевое слово log, в конструкцию log, резвит этот ilogpattern, то вместо monitorEnter будет вызван вот этот enterLogScope метод. +6725.02 6730.06 "Анатолий Кулаков" Ну, это богатая идея, можно свои monitorLogs иметь, значит, это более другое. +6730.06 6731.06 "Игорь Лабутин" Да-да-да. +6731.06 6732.06 "Анатолий Кулаков" Можно будет касаться. +6732.06 6737.50 "Анатолий Кулаков" Название только дурацкое, то есть это как disposable для ютинга, у нас теперь будет для лога тоже такой интерфейс. +6737.50 6738.50 "Игорь Лабутин" Типа того. +6738.50 6740.34 "Игорь Лабутин" Да-да-да, вот ровно оно, по сути. +6740.34 6746.38 "Игорь Лабутин" Только в dispose понятно, что там только один выходной метод есть, а здесь будет два, на вход и на выход. +6746.38 6750.82 "Игорь Лабутин" Посмотрим, к чему приведёт, на самом деле, да, вся эта история делается ровно для одного. +6750.82 6767.70 "Игорь Лабутин" Если сделать вот такой специальный log-тип, который будет, собственно, реализовать некоторую логику логов, а в каком-то дунете запретить использование внутри конструкции лог любых типов, кроме этого типа, то знаешь, что можно сделать? +6767.70 6772.18 "Анатолий Кулаков" Узнать, прооптимизировать абсолютно все объекты, которые хранят этот дурацкий флажочек у себя в ядерах. +6772.18 6778.58 "Игорь Лабутин" Именно, мало того, что флажочек они хранят не только флажочек, там получится выкинуть, короче, из заголовка объекта кучу всего. +6778.58 6787.26 "Анатолий Кулаков" Ну вот у меня прям с первых версий C# сразу был такой ступор, нафига они задумали все объекты лочить, почему нельзя было сделать отдельный класс? +6787.26 6790.58 "Анатолий Кулаков" Потому что никто никогда не хочет лочить просто абсолютно всё. +6790.58 6794.94 "Анатолий Кулаков" Все делают свой какой-нибудь классик по бестпрактисам всем, и только этот классик лочат. +6794.94 6797.98 "Игорь Лабутин" Скорее всего, наследие Java, потому что синхронайст и вот это всё. +6797.98 6800.98 "Анатолий Кулаков" Там тоже можно, но это… Во всём виноваты эти личаисты. +6800.98 6819.14 "Игорь Лабутин" Ну, короче, смысл в том, что, да, глобальная такая идея – это пока не цель, это пока идея, а можно ли у объекта выкинуть вот этот заголовок, где хранится лог, где хранится ещё хэшкод, кстати, иногда, а иногда лог, а иногда хэшкод, в зависимости от того, использовали вы объект в лог или не использовали. +6819.14 6827.86 "Игорь Лабутин" Вот, там ещё хранится пачка некоторых битовых флагов, короче, там есть идеи, как его можно порезать, чтобы мы поменьше кушали в памяти. +6827.86 6828.86 "Игорь Лабутин" Вот. +6828.86 6831.90 "Игорь Лабутин" Последим, посмотрим, к чему это всё приведёт. +6831.90 6832.90 "Игорь Лабутин" Сериолог трейсинг. +6832.90 6852.78 "Игорь Лабутин" Мы в прошлый раз как раз рассказывали про СЕК новый, который позволяет, по-моему, что он там, OTLP, да, open telemetry провайдерам теперь быть, всё это в себя собирать, и мы там упоминали, что вот есть библиотечка сериолог трейсинг, удобный, client-side, все дела, вышла статья, в которой прямо описано, как ей пользоваться, что она даёт, так что посмотрите. +6852.78 6861.58 "Анатолий Кулаков" Ну, не просто статья, а статья Никаса Блумхарта, как раз автора СЕКа и сериолога, и всех вместе взятых, у него классный блог, если ещё не подписаны, то тоже рекомендуем. +6861.58 6862.58 "Игорь Лабутин" Да. +6862.58 6875.14 "Игорь Лабутин" В .NET 9 продолжается работа над генерацией, удобной генерацией ИЛИ кода, я напоминаю, что когда мы получили .NET Core, у нас был, отрезана, на самом деле, возможность кода генерации некоторая, сейчас вот потихонечку это всё возвращается. +6875.14 6880.66 "Игорь Лабутин" Короче, в .NET 9 должен полностью AssemblyBuilder.save уже нормально работать со всеми нужными приседаниями. +6880.66 6901.70 "Игорь Лабутин" В .NET 9 уже заимплементили три новых link_you метода, мало ли вам не хватало, это count_by и aggregate_by, то есть вы можете просто, ну, count - это просто считал элементы коллекции, можно сказать count_by и передать делегатик, по какому полю считать, собственно, эти самые, или агрегировать сущности. +6901.70 6917.98 "Игорь Лабутин" И есть ещё теперь новый метод index, раньше, если вы хотели итерировать коллекцию так, чтобы вам возвращался и сущность, и её индекс в этой коллекции, нужно было писать замечательную конструкцию там, select item_index и вернуть tuple, соответственно, из item_index, теперь для этого у нас есть отдельный метод index. +6917.98 6942.58 "Игорь Лабутин" И последнее, что у нас есть из краткого, это то, что mstest до сих пор жив, и Microsoft выпустил mstestrunner, это, короче, штука, которая позволяет вам теперь собрать ваш проект с тестами, напоминаю, мстестовый проект, раньше, как и на самом деле во многих других тестовых фреймворках, это .dll, и вам нужен какой-то специальный раннер, который её будет запускать. +6942.58 6948.62 "Игорь Лабутин" В XUnity, по-моему, сейчас в последнем вроде как они собрались сделать .exe, или даже сделали уже, что XUnity +6948.62 6949.62 "Анатолий Кулаков" генерирует .exe. +6949.62 6953.46 "Анатолий Кулаков" Ну, при альфе, который у них есть, да, тоже сделали. +6953.46 6954.46 "Игорь Лабутин" Вот. +6954.46 6983.54 "Игорь Лабутин" У mstest теперь есть следующее, что вы можете взять в вашем тест-продже, добавить, ну, get_packet, специально называется mstest.adapter, тест-адаптер, поставить опцию enable mstestrunner, и в output type вместо .dll написать .exe, после чего у вас берётся executable, который, во-первых, не требует никаких там продуктных тестов, visual studio, mstestconsole, вообще никаких других раннеров он не требует, он полностью самодостаточен, то есть его можно отлаживать, его можно делать чего угодно. +6983.54 6994.02 "Игорь Лабутин" Вы можете таким образом, как ни странно, собрать какой-нибудь там кроссплатформенный тест, в смысле на винде собрать тест, который юнит-тестом запустится на линуксе, ну, например. +6994.02 6995.02 "Игорь Лабутин" Вот. +6995.02 6998.34 "Игорь Лабутин" И вы можете его отлаживать, как обычное приложение, всё такое. +6998.34 7013.86 "Игорь Лабутин" И при этом это всё ещё работает быстрее, то есть они меряли, там, на некоторых тестах, там, скорость увеличивается раза в три, за счёт того, что нет вот этого межпроцессного взаимодействия между хостом, который контролирует раны вашего теста, и тем процессом, который загружает ваши сборки с тестами. +7013.86 7014.86 "Анатолий Кулаков" Примерно так. +7014.86 7019.26 "Анатолий Кулаков" Ну, отлично, в принципе, смотри, сколько нововведений оказывается. +7019.26 7020.26 "Анатолий Кулаков" А мы зря Microsoft ругали. +7020.26 7021.26 "Анатолий Кулаков" Что они делают? +7021.26 7029.26 "Игорь Лабутин" Да, что-то делают, потихонечку какие-то вмещения выходят, мы просто всё ждём какого-нибудь превью уже нормального, там наверняка будет что-нибудь интересное и масштабное и мега суперкрутое для девятки. +7029.26 7030.26 "Игорь Лабутин" Но посмотрим. +7030.26 7038.34 "Анатолий Кулаков" Да, хорошо, подождём, и как только будет, мы вам обязательно об этом расскажем, поэтому никуда не уходите, подписывайтесь и всех остальных тоже зовите подписываться. +7038.34 7039.90 "Анатолий Кулаков" Давай, на сегодня, наверное, хватит нам. +7039.90 7047.22 "Игорь Лабутин" Да, на сегодня нам хватит, мы посмотрели на Andrew Locke и вспомнили, что такое дефолтные методы интерфейсов или реализации. +7047.22 7062.18 "Игорь Лабутин" Мы узнали Aspire Roadmap, посмотрели на байнари-форматер и чем его теперь заменять, подробнейшим образом обсудили различные аспекты того, как можно дизайнить REST API, ну и много мелочей от Microsoft в основном, но не только от Microsoft, тоже +7062.18 7063.18 "Анатолий Кулаков" было. +7063.18 7068.86 "Анатолий Кулаков" Всем спасибо за прослушивание, заходите ещё и увидимся. +7068.86 7069.86 "Анатолий Кулаков" До новых встреч, пока. +7069.86 7070.46 "Анатолий Кулаков" Пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-88.txt b/input/Radio/Transcriptions/RadioDotNet-88.txt index f67fd53..edfcee8 100644 --- a/input/Radio/Transcriptions/RadioDotNet-88.txt +++ b/input/Radio/Transcriptions/RadioDotNet-88.txt @@ -1,817 +1,817 @@ -0.00 11.40 SPEAKER_01 Здравствуйте, дорогие друзья, в эфире Radio.net, выпуск номер 88. -11.40 15.72 SPEAKER_01 И сегодня с вами его постоянный ведущий Анатолий Кулаков -15.72 16.92 SPEAKER_00 и Игорь Лабутин. -16.92 17.92 SPEAKER_00 Всем привет. -17.92 34.44 SPEAKER_01 А также большая-большая армия наших помогаторов, в частности Александр, Сергей, Владислав, Шевченко Антон, Лазарев Илья, Гурий Самарин, Виктор, Руслан Артамонов, Александр Ерыгин, Сергей Бензенко, Александр Лапердин и Ольга Бондаренко. -34.44 36.40 SPEAKER_01 Всем спасибо, друзья, кто нас поддерживает. -36.40 46.20 SPEAKER_01 Если вы не знаете, про что я говорю, заходите на Boosty и поддержите мелкой копеечкой ваш любимый подкаст и посмотрите также, что у нас там еще есть интересного для вас. -46.20 66.32 SPEAKER_01 Так, из неофициальных новостей у нас все еще продолжается CFP на .NEXT, поэтому если вы хотите стать звездой и блистать на самой большой конференции по .NET, то обязательно поддавайтесь на спикерство, поддавайтесь на доклады, мы поможем с тренировками, с подготовками, со всем и сделаем отличную конференцию вместе. -66.32 68.52 SPEAKER_01 Поэтому всех ждем, всех милости просим. -68.52 73.00 SPEAKER_01 И, кажется, из неофициального это все, можно приступать к выпуску. -73.00 74.00 SPEAKER_01 Как у нас там с материалами? -74.00 75.00 SPEAKER_01 Микрософт подтянулся? -75.00 94.20 SPEAKER_00 Да, Майкрософт нашел, чем нас порадовать, ну или погрустить тут же, я не знаю, кому как, и выпустил не только статью про то, что там у нас новый превью, у нас там еще что-нибудь, а у нас прям теперь есть статья под названием «Новый вижен .NET 9», точнее не то, что новый, просто вижен .NET 9. -94.20 99.96 SPEAKER_00 То есть что же Майкрософт в целом хочет сделать за этот наступающий год, так скажем. -99.96 109.24 SPEAKER_01 Знаешь, интересно, после статей, как бы мы переписываем .NET сервисы на раст от Майкрософта, уже прям страшно такие вижены смотреть, открывать, так знаешь, страничку. -109.24 134.24 SPEAKER_00 Ну открываешь вижен, на самом деле там начинается все с типичных, ну я бы сказал баз вардов, то есть там написано, что самый главный фокус для нас это Cloud Native и Intelligent App Application Development, ну имеется в виду, конечно же, все, что связано с искусственным интеллектом, ну и куда же без тщательное и значительное вложение в Performance, Productivity и Security. -134.24 142.16 SPEAKER_00 Короче, все максимально общие слова, такое можно, наверное, сказать практически про любую платформу, про любой релиз, но вот тем не менее, вижен и вижен. -142.16 149.64 SPEAKER_00 Но этими словами не только ограничивается, точнее не только ими все ограничивается, есть расшифровка, что же это все значит. -149.64 188.96 SPEAKER_00 Начнем мы с раздела номер один, называется он Platform for Cloud Native Developers, и здесь Майкрософт говорит примерно следующее, что они хотят сделать более легким, то есть не то, чтобы развивать именно сам .NET, а сделать так, чтобы у тех, кто пишет на .NET были простые и легкие способы использовать популярную инфраструктуру, которую все и так используют в Prod, ну например, не знаю Kuber или еще что-нибудь, там Redis, более так сказать прямолинейным путем из .NET, то есть сделать так, чтобы все было попроще. -188.96 195.00 SPEAKER_00 И конечно же, главный кусочек здесь это .NET Aspire, тут куда же без него, мы про него уже каждый выпуск говорим. -195.00 239.28 SPEAKER_00 Кроме того, это конечно же найти фауты Trimming, потому что это позволяет уменьшать размеры кода в контейнере и размеры в контейнерах, дальше туда же уходит новый режим Garbage Collector, который был в The Religion в прошлом .NET, это Dynamically Adaptable to Application Size, то есть штука, которая позволяет подгонять размеры потребляемой памяти, а точнее количество куч, которые использует Garbage Collector внутри себя для разных режимов работы вашего приложения и в динамике их менять, ну и всякие более прикладные вещи, типа там Rate Limiting вот этого всего, то что без чего сейчас не живет ни одно Cloud Native приложение, вот это все будет, так сказать, в фокусе команды на ближайший релиз. -239.28 241.60 SPEAKER_00 Это то, что касается платформы. -241.60 306.48 SPEAKER_00 Есть еще раздел Tools for Cloud Native Developers, и с тулингом тут опять буду повторять те же самые слова, это опять же найти фаут, сейчас для того, чтобы что-то скомпилить в найти фаут, вам нужно поюзать, ну скажем так, как написано в Microsoft, это требует установки тулов, которые большинство дотнет-девелоперов, вообще говоря, обычно не используют, ну типа, например, докера или VSL, Windows Subsystem for Linux, а цель Microsoft сделать так, чтобы любой пользователь Visual Studio мог это все спокойно делать, поэтому они будут расширять поддержку Ahead of Time компиляции в Visual Studio каким-то образом, не знаю, пока каким, ну а также, конечно же, дотнет Aspire, куда войдет более тщательная интеграция с Visual Studio и Visual Studio Code, конфигурация компонентов, отладка, включая Hot Reload, ну и какая-то интеграция с тем самым дэшбордом, то есть, видимо, так, чтобы этот дэшборд можно было смотреть не только в браузере, но, возможно, прямо из студии в каком-нибудь там тулинг окошке, не знаю пока. -306.48 324.16 SPEAKER_00 Никуда мы не деваемся от искусственного интеллекта, Microsoft, наверное, не был бы Microsoft, если бы не сказал, что они не будут делать никакой искусственный интеллект на дотнете, конечно же, будут, и, конечно же, там ведется некоторое количество разработок уже. -324.16 340.56 SPEAKER_00 Основная цель — это не то, чтобы прямо на дотнете все это писать, а именно сам искусственный интеллект, а больше цель на то, чтобы интегрировать в себя все те тулы, которые сейчас есть, то есть более легкое использование там всяких OpenAI и других открытых моделей. -340.56 364.08 SPEAKER_00 Ну и дальше, так скажем, сотрудничество со всякими тем же самым OpenAI, сотрудничество с HRSDK, чтобы более удобно использовать всякие Artificial Intelligence сервисы из Azure, и все такое прочее, просто чтобы было попроще на дотнете использовать искусственный интеллект, ну потому что все этим, конечно, сейчас занимаются. -364.08 377.32 SPEAKER_00 Кроме того, несмотря на то, что у нас есть как бы отдельная статья под названием DotNet 9, overview, да, как там называется, Roadmap Vision, есть еще Roadmap отдельных команд. -377.32 389.20 SPEAKER_00 И я ради интереса заглянул в эти Roadmap, может быть, оно немножко пересечется с превью, который мы будем обсуждать чуть позднее в этом выпуске, но первым мне на глаза попался Maui Roadmap. -389.20 392.72 SPEAKER_00 Как ты думаешь, что же у нас в Maui Roadmap? -392.72 396.52 SPEAKER_01 Перформанс, интеграции, стабилити и все такое? -396.52 397.52 SPEAKER_00 Типа того. -397.52 409.08 SPEAKER_00 У них это называется Product Quality Across Layout, то есть они будут улучшать layouting, они будут улучшать контролы, они будут улучшать надежность тулинга, вот. -409.08 423.52 SPEAKER_00 И может быть, как у них написано, these items are under consideration, будет interrupt со свифтом, чтобы ты мог свифтовые кусочки на iPhone отдергать, может быть, они подумают про кастомные курсоры. -423.52 426.56 SPEAKER_01 Во-во, вот это замахнулись прямо. -426.56 438.36 SPEAKER_00 Да, и на том же уровне у них стоит, что они часть контролов подвинули в Maui Core слой для того, чтобы они были, ну там, видимо, можно их быстрее писать, там я не знаю еще как, что. -438.36 448.00 SPEAKER_00 Вот они move, короче, remainder of controls, оставшиеся контролы тоже подвинуть в Maui Core Layer для того, чтобы стало лучше с перформансом и стабилити. -448.00 452.08 SPEAKER_00 Короче, мы что-то будем делать, но мы пока не знаем, что мы будем делать. -452.08 454.32 SPEAKER_00 Quality и стабилити как бы. -454.32 456.36 SPEAKER_00 Quality и стабилити, да. -456.36 464.72 SPEAKER_00 Значит, дальше я посмотрел на SPNet Core Roadmap, там много всего, прям очень много, но все это под одним большим жирным заголовком – Blazor. -464.72 475.16 SPEAKER_00 То есть из прям таких больших, ну как сказать, не мега-фич, а таких направлений, да, это Blazor, Blazor, Blazor, еще Blazor, все для Blazor. -475.16 478.60 SPEAKER_00 Конечно, там будут другие улучшения, но вот это основное. -478.60 487.00 SPEAKER_01 Смотри, как интересно, это же Blazor, он же никуда не вписывается, это и не Artificial Intelligence, и не CloudNet, и вообще никуда. -487.00 490.00 SPEAKER_01 Зачем они у него столько сил вкладывают, непонятно. -490.00 491.00 SPEAKER_00 Не знаю пока. -491.00 532.20 SPEAKER_00 Ну вот посмотрим, то есть я действительно пытался найти в SPNet какие-то, ну прям такие, в вышках, которые там приведены в качестве Roadmap, какие-то более приземленные, что ли, или относящиеся к SPNet штуки, но там есть, конечно, там тема раутинг здесь, там какие-то форм-байнинги там, но они очень мелкие на самом деле, какие-то мелкие полировка всего того, что уже есть в Minimal API и в остальных местах, почему, не знаю, ну может быть они пытаются таким образом как-то, не знаю, тех, кто пишет на дотнете, десктопы, например, писал, и сейчас пересаживается на современный дотнет, типа можно JS не учить? -532.20 538.92 SPEAKER_01 Ну десктопы, мне кажется, уже давно волна прошла, которых пересаживали, ну там, естественно, они еще сохранились, но все же первая активная волна была потом. -538.92 547.00 SPEAKER_01 Мне кажется, наоборот, они видят, что не хватает фронтовиков и пытаются все-таки пересадить, ну побороться с JavaScript в этом плане, с WB Assembly и все такое. -547.00 552.28 SPEAKER_00 Ну побороться, откусить маленький кусочек, может быть. -552.28 553.28 SPEAKER_00 Ну да, наверное. -553.28 557.84 SPEAKER_01 Ну ты же понимаешь, что там даже если от слонака бы маленький откусить, тут уже как бы много. -557.84 558.84 SPEAKER_01 Это да. -558.84 559.84 SPEAKER_00 Уже хватит всем. -559.84 560.84 SPEAKER_00 Это правда. -560.84 563.60 SPEAKER_00 Поэтому может быть и действительно имеет смысл кусать. -563.60 580.16 SPEAKER_00 Дальше у нас есть C# Roslyn, там все очень непонятно, потому что там есть некоторый список VNEXT, который можно было бы принять за то, что вот это может быть и войдет в следующую версию C#, но проблема в том, что некоторые сущности в этом VNEXT живут уже годами. -580.16 588.36 SPEAKER_00 Какие-нибудь как Rawls Extensions там или, не знаю, Paramspans, они, по-моему, уже два релиза живут, не срелизятся. -588.36 589.36 SPEAKER_00 Вот. -589.36 590.36 SPEAKER_00 Но посмотрим. -590.36 602.00 SPEAKER_00 Из очередных таких полукрышесносящих штук, которые мы скорее всего будем, если их сделают, мы будем разбирать и пытаться понять, нафига это сделано, это будут refstruct интерфейсы. -602.00 608.32 SPEAKER_00 То есть спаны можно будет делать, спаны смогут реализовывать интерфейсы. -608.32 620.96 SPEAKER_01 Жестоко, refstruct интерфейсы, ну то есть с интерфейсами, которые реализуют методы, мы уже сталкивались, теперь интерфейсы, которые только для структур, по идее, будут и не просто для структуры, а только для reference structure. -620.96 629.92 SPEAKER_00 Короче, да, если еще вспомнить, что есть еще readonly, refreadonly, вот это все, то, короче, сделают фичу, посмотрим. -629.92 633.80 SPEAKER_01 Ужас, ужас, что-то куда-то не туда она идет. -633.80 634.80 SPEAKER_00 Да. -634.80 665.88 SPEAKER_00 Ну и есть у F# отдельный roadmap, там на самом деле довольно все прикольно сгруппировано, они будут пилить, ну или обновлять скорее, ленгвич сервер, короче, LSP для Visual Studio, Visual Studio Code, они будут улучшать перформанс компилятора и вот этого самого LSP, ну и докидывать там кучку аналайзеров, вот это все, как всегда, догонять по фичам в C#, когда C# что-нибудь зарелизит, такое, что не очень совместимо с F#, им придется срочно пилить совместимость, чтобы ничего не развалилось. -665.88 666.88 SPEAKER_00 Ну, в общем, как-то так. -666.88 672.12 SPEAKER_00 Вот, примерно, такой у нас vision.net. -672.12 682.56 SPEAKER_01 Ну и тут, в принципе, наверное, важно понимать, что это как бы не roadmap уже конечных фич, потому что почему-то Microsoft никогда не рассказывает те большие фичи, над которыми они работают. -682.56 690.12 SPEAKER_01 Они все еще, у меня от себя не знаю, какая-то коммерческая компания, которая во время релиза сообщает какие-то громкие навидки интересные, которые нас встречают. -690.12 692.36 SPEAKER_01 Ну, можем вспомнить много примеров. -692.36 704.80 SPEAKER_01 Поэтому это, наверное, какой-то такой действительно общий roadmap, те мелкие вещи, которые уже известны, но, скорее всего, в рукавах там есть несколько больших фич, которые будут релизиться, будут выпускаться, о которых мы еще понятия не имеем. -704.80 706.64 SPEAKER_00 Может быть, даже и они понятия не имеют. -706.64 723.08 SPEAKER_00 Кажется, что Aspire, например, поскольку он вышел только на dotnet.conf в виде первого превью, да, то есть не факт, что он там с фероля начал делаться, может быть, какие-то идеи позднее появились, потому что я думаю, что тогда бы они dotnet.conf чего-нибудь более табильное бы выпустили. -723.08 726.80 SPEAKER_01 Может быть, они даже не думали, что оно вообще выстрелит и кому-то это будет интересно. -726.80 731.56 SPEAKER_00 Ну или что успеют, в принципе, доделать dotnet.conf хоть как-то, хотя бы до первого превью. -731.56 737.56 SPEAKER_00 Так что будем смотреть, да, давайте поглядим дальше, ближе к делу. -737.56 738.56 SPEAKER_01 Давай дальше. -738.56 745.92 SPEAKER_01 Ну и тут как раз, да, как раз недалеко от вижена вышел превью 1, девятки, как бы всех фреймворков, которые связаны и так далее. -745.92 760.80 SPEAKER_01 И самое, наверное, запоминающееся в этом превью 1 в том, что эти господа изменили структуру анонсов, которые раньше были оформлены в виде хороших блокпостов, которые было прекрасно читать, прекрасно вам рассказывать и прекрасно искать и ссылаться. -760.80 781.44 SPEAKER_01 Теперь они там превратили это все в какой-то ад, они сделали все анонсы в гитлабе, о, в гитхабе, они сделали все анонсы в гитхабе, при том половина из них в виде ишисов, половину тегами к релизам, половину маркдаун-файлы, которые не забросили репозиторий, и еще есть штучки три разновидностей на сайтах микрософта, leon, whatsnew, там и еще где-то в блогах. -781.44 796.88 SPEAKER_01 В общем, получилась адская смесь, ну не знаю, с одной стороны, конечно, плохо, с другой стороны у вас теперь точно не будет никакого шанса самим это читать, вам придется нас слушать, потому что мы все это сагрегировали, задистинктили и доносим вам понятным, упорядоченным языком. -796.88 808.56 SPEAKER_01 Поэтому, не знаю, я сначала, когда собирал анонс, я думал, что я половину не нашел, как бы того, что заанонсили, я все-таки не нашел 10-20 лишних ресурсов, где это тайком нам рассказали. -808.56 813.08 SPEAKER_01 Ну на самом деле нет, я в принципе нашел все, и анонс сам по себе довольно бедненький. -813.08 818.30 SPEAKER_01 Кажется, что это, знаешь, как Hello World, его выкатывают не ради функциональности, а ради того, чтобы обкатать новую инфраструктуру. -818.30 828.00 SPEAKER_01 Так и здесь они вот надумали себе каких-то глупостей, не хотят обкатать инфраструктуру, поэтому надо было выпустить хоть что-то, хотя бы даже без изменений, просто версию поднять. -828.00 837.64 SPEAKER_00 Зато смотри, зато теперь тебе не нужен какой-нибудь клевый автор на девблог, просто сами разработчики закидали маркдаун файлик в репозитории, вот тебе и релиз ноутс. -837.64 848.88 SPEAKER_01 Так и есть, и это в лучшем варианте, если взять какой-нибудь там капам в EF Core, там просто дали тебе эту сотню ссылок на исчез и все, вот наш what's new. -848.88 852.48 SPEAKER_01 Как бы легче всего, что за спринт закрыли, вот это и разбирайте. -852.48 857.92 SPEAKER_00 Это они и в прошлом году так делали, от них статьи не было, в общем-то, одна или две за весь год. -857.92 865.20 SPEAKER_01 Ну, как бы то, что вы спихнули на разработчиков написание документации еще не решит проблему, а скорее всего даже усугубит ее. -865.20 869.00 SPEAKER_00 Ну ладно, давай посмотрим, что в итоге рано-насобиралось. -869.00 893.28 SPEAKER_01 Ну начнем с фреймворка, .NET 9, тут одни из самых главных нововведений, это то, что в JSON Serializer Options теперь засунули два необходимых всем свойства, это Ident Size и Ident Character, то есть то, как мы будем отбивать наши отступы в сериализованном JSON-файлике, и то, каким символом мы будем это делать, ну как бы, как мы без этого жили непонятно. -893.28 898.20 SPEAKER_01 Дальше, вот это еще более-менее нормальная тема, добавили в линку парочку полезных методов. -898.20 903.92 SPEAKER_01 Во-первых, это Count By, который позволяет вам вычислить то же самое количество, но уже по определенному ключу. -903.92 911.32 SPEAKER_01 Есть часто случаи оптимизации, когда это намного удобнее, чем сделать Select, а по нему уже Count, или что-то типа того городить. -911.32 918.32 SPEAKER_01 Aggregated By, который похож на основной Aggregate, но тоже умеет воспринимать в особых местах ключик, где тоже это полезно. -918.32 929.68 SPEAKER_01 И довольно концептуально новая вещь, это новый метод Index, который возвращает нам tuple, где мы получаем элемент вместе с его индексом. -929.68 934.80 SPEAKER_01 Это очень похоже на Select с индексом, вы наверняка таким могли пользоваться. -934.80 942.24 SPEAKER_01 Что есть метод Select, который принимает в качестве аргументов порядковый номер этого элемента в единомерабле и сам элемент. -942.24 945.60 SPEAKER_01 И на основании это что-то делает, что-то происходит. -945.60 951.80 SPEAKER_01 Вот здесь же этот номер и элемент, они просто возвращаются, они не передаются в какое-то замыкание. -951.80 954.04 SPEAKER_01 Вот поэтому их, например, удобно в фурриче прокручивать. -954.04 970.68 SPEAKER_01 Дальше, про фреймворк в Priority и Q немножко изменилось, тогда добавили метод Remove, это сделало возможным эмулировать изменение приоритетов в этой Priority и Q, потому что раньше это было невозможно, и поэтому некоторые хорошие оптимизированные алгоритмы невозможно было сделать. -970.68 972.32 SPEAKER_01 В общем, теперь это возможно. -972.32 985.40 SPEAKER_01 У Security области добавилась поддержка алгоритма KeemAC, это к МАК, поэтому в дотинной девятом к МАК со всех сторон пропихивают, рассовывают во всякие места, чтобы он везде поддерживался. -985.40 1001.24 SPEAKER_01 Небольшое изменение в Assembly Builder, в билдере его сделали persistent имплементацию, то есть теперь мы в рантайме можем собирать код через Reflection Emit, и не только собирать, но и теперь мы можем его сохранять в виде сборки. -1001.24 1005.72 SPEAKER_01 В общем, это тоже возможно после превью первого. -1005.72 1009.84 SPEAKER_01 Саму фреймворк, в принципе, это все, давай по другим компонентам посмотрим. -1009.84 1012.16 SPEAKER_01 Прежде всего, рантайм. -1012.16 1021.60 SPEAKER_01 В рантайме есть оптимизация в NetEvo Auto, сюда притащили Object Writer, новый Object Writer, который был написан на чистом C#. -1021.60 1032.00 SPEAKER_01 До этого в 7, 8 версии использовался тот же самый Object Writer, который базировался на LLVM версии в библиотеке и использовался везде он. -1032.00 1040.72 SPEAKER_01 Это специальный объект, специальный классик, с помощью которого записывалась дебаг информации и всякие дебажные символы для NetEvo Auto. -1040.72 1045.40 SPEAKER_01 То есть полезная в хозяйстве вещь, но была использована через интеропы всякие. -1045.40 1050.92 SPEAKER_01 А теперь на чистом C#, теперь она стала быстрее, у нее удобный интерфейсик и куча простора для оптимизации. -1050.92 1051.92 SPEAKER_01 Ну как и все. -1051.92 1057.28 SPEAKER_01 Идти и кроссплатформенно, и отвязались от лишних нативных лип, что тоже не может не радовать. -1057.28 1068.20 SPEAKER_01 Дальше есть много луп-оптимизаций, то есть оптимизаций циклов, как их красиво выравнивать, разворачивать, выносить неизменяющиеся конструкции за пределы цикла и вот это вот все. -1068.20 1081.80 SPEAKER_01 Также добавилась поддержка AMD64, SVE и SVE2 инструкций, это Scalable Vector Extensions, которые очень широко используются, например, в машин-ленингах и во всяких high-performance компьютингах. -1081.80 1085.60 SPEAKER_01 Наверное, тоже богатым и жирным принесет много удовольствия. -1085.60 1089.76 SPEAKER_00 Я тебя только тут поправлю, это не AMD64, это все-таки ARM64. -1089.76 1097.40 SPEAKER_00 На AMD64 у нас давно всякая параллелизация и прочее есть, векторизация, а вот на ARMах с ней было, ну вроде тоже неплохо, но сейчас стало получше. -1097.40 1101.72 SPEAKER_01 Да, точно, спасибо, на ARM. -1101.72 1116.62 SPEAKER_01 Оптимизации у JITA приехали также в Registered Allocation Improvements, ну это как раз та часть, которая сильно страдала при стартапе, в общем, там тоже что-то подшаманили, что теперь стартап или сделают, или будут делать быстрее и красивше. -1116.62 1138.08 SPEAKER_01 В SDK, в самом Build Tool, которым мы пользуемся, добавили Terminal Logger по дефолту включенный, мы обсуждали же Terminal Logger, это специальная версия аутпута, когда вы запускаете те же самые .NET Build, Restore, Pack и прочие вещи, а вот аутпут, который выдается, теперь будет намного красивее. -1138.08 1148.56 SPEAKER_01 В частности, там появятся кликабельные ссылки, продолжительность различных операций, т.е. таймеры внедрятся, различные подсветки, разноцветные подсветки, уборнингов и роров. -1148.56 1152.64 SPEAKER_01 В общем, станет все очень красивенько и нативненько, и модненько, и стильненько. -1152.64 1171.88 SPEAKER_01 Естественно, этот логгер, он не включается, если вдруг ваш терминал такого не поддерживает, т.е. он там все динамически анализирует и смотрит, что если у вас новый модный терминал с линками и эмоджиками, то он загружается и показывает что-то красивенькое вам. -1171.88 1177.12 SPEAKER_01 Также немножко изменилось поведение команды .NET Tool Install. -1177.12 1190.52 SPEAKER_01 Теперь, если вы вызываете .NET Tool Install и такой пакет на вашем компьютере уже установлен, но у вас находится более старая версия, то Install обновляет эту версию до самой последней, которую он найдет. -1190.52 1199.88 SPEAKER_01 Раньше такого было делать не можно, раньше вам необходимо было вызывать отдельно .NET Tool Update, и с тем же самым эффектом практически. -1199.88 1212.46 SPEAKER_01 А SP-Core практически спит, он добавил JSON-полиморфик Type-support для SignalEra, т.е. в SignalEra-хабах вы теперь можете децерализовать полиморфические ДТОшки, ну, допустим. -1212.46 1227.70 SPEAKER_01 У Entity Framework из заметного, это поддержка комплекс-тайпов в Execute-Update, напомню, Execute-Update это мега шикарная штука, когда вы можете целую пачку по какому-то условию запихнуть в нее Update. -1227.70 1233.04 SPEAKER_01 В общем, очень полезная вещь для многих сценариев, для многих алгоритмов, прям вообще класс. -1233.04 1250.48 SPEAKER_01 А комплекс-тайпы тоже мы обсуждали как раз недавно, это специальные такие Entity в Entity Framework, которые инкапсулируют в себя какие-то более сложные типы, более сложные value-обжекты, которые могут раскладываться, допустим, на несколько полей. -1250.48 1256.20 SPEAKER_01 И теперь вы такие сложные объекты тоже можете обновлять по условию. -1256.20 1261.72 SPEAKER_01 Там синтаксис, конечно, немножко непривычен для нормального человека, но, к сожалению, там по-другому не сделаешь. -1261.72 1264.60 SPEAKER_01 Поэтому если вам это нужно, вы даже этим будете радоваться. -1264.60 1275.60 SPEAKER_01 Ну и MAUI тоже выпустил превью первый, но там практически ничего нет, про что можно сказать в приличном обществе, поэтому про него просто промолчим. -1275.60 1276.60 SPEAKER_01 Ну, Performance, Stability. -1276.60 1279.32 SPEAKER_01 Да, да, да, вот этот все. -1279.32 1291.40 SPEAKER_00 Я прямо вижу наши вот заметки к этому выпуску, и там видно там заголовок такой-то, там SDK Update, какие-то заметки, там SPNET, заметки Entity Framework, заметки про MAUI, только заголовок. -1291.40 1293.36 SPEAKER_00 Прям прекрасно, да. -1293.36 1299.16 SPEAKER_01 Ну, просто про все остальные команды можно было хотя бы один параметр вытащить, а здесь вот просто ничего. -1299.16 1310.04 SPEAKER_01 В общем, превью довольно бедный, практически никчемный, но, наверное, просто чтобы обкатать какую-то инфраструктуру для релизов или просто новую версию выпустить, чтобы что-то было. -1310.04 1328.40 SPEAKER_00 Ну, да, посмотрим, когда это будет уже нормальные следующие превью, превью 2, я надеюсь, там будет что-то ценное и хорошее, и, может быть, даже заметки как-то обретут, может быть, они какую-нибудь ретру проведут на тему того, что как неудобно это все читать и будут экспериментировать дальше. -1328.40 1344.52 SPEAKER_01 Ну, я, кстати, лазил по гитхабу с целью как бы увидеть гневные комментарии, и, если честно, гневных не нашел, а таких нейтральных есть парочку, но не кажется, знаешь, что у них будет какой-то материал для того, чтобы проводить ретроспективы насчет их заметок. -1344.52 1348.72 SPEAKER_00 Ну, может, они сами на самом деле фиг знают, поймут еще что-нибудь. -1348.72 1350.84 SPEAKER_00 Ладно, глянем, давай дальше. -1350.84 1355.28 SPEAKER_00 Дальше у нас про C# и про breaking changes. -1355.28 1371.64 SPEAKER_00 В гитхабе появилось ищу, в котором, ну, точнее, как в гитхабе, в главном репозитории C# ленга появилось ищу, в котором Мэтт Скридсонсон в том числе рассуждает на тему того, как они собираются вносить breaking changes в C#. -1371.64 1384.56 SPEAKER_00 То есть надо понимать, что C# — язык, в который очень строго блюдет принцип обратной совместимости и фича, единожды добавленная в язык, в общем-то живет в этом языке, ну, можно сказать, вечно. -1384.56 1393.32 SPEAKER_00 Можно по пальцам, может быть, даже одной руки пересчитать случаи, когда в языке что-то прямо существенно серьезно ломалось. -1393.32 1407.88 SPEAKER_00 Но проблема заключается в том, что если таким образом жить дальше, то, ну, получается, что довольно много изменений в язык не сделать, потому что они, ну, ломающие по сути своей. -1407.88 1410.28 SPEAKER_00 И вот Мэтт приводит несколько примеров. -1410.28 1418.00 SPEAKER_00 Например, то, что сейчас давно хотят и, может быть, это появится в ближайшем C#, это так называемый field access. -1418.00 1419.00 SPEAKER_00 То есть что это такое? -1419.00 1425.20 SPEAKER_00 Напомню, у нас есть в классе, мы можем объявить property, мы можем объявить поле, field. -1425.20 1441.40 SPEAKER_00 При этом в свойстве вы можете написать setter, getter, и внутри setter вы можете, например, использовать неявную переменную типа value для того, чтобы ее, ну, присвоить тому полю, в который вы хотите его присвоить. -1441.40 1447.92 SPEAKER_00 То есть это то, что передали вам, когда присваивали в это поле, в это свойство что-то. -1447.92 1458.36 SPEAKER_00 Но для того, чтобы это работало, то есть если вам нужна какая-то кастомная логика в setter или getter, приходилось заводить собственно реальное физическое поле, куда это значение, например, складывать. -1458.36 1475.20 SPEAKER_00 Довольно давно висит пропозал про то, что ну раз у нас есть такое специальное переменное, типа псевдопеременное под названием value, давайте заведем псевдопеременное под названием field, и компилятор нам будет автоматически генерить вот это самое то, что на английском называется backing field. -1475.20 1480.92 SPEAKER_00 То есть поле, которое лежит под этим свойством и, собственно, занимается тем, что хранит это значение. -1480.92 1491.00 SPEAKER_00 А в setter или getter мы будем там писать field присвоить value, да, и там в getter и return field, грубо говоря, если прямо вот такое самое простейшее свойство написать, с явным getter и setter. -1491.00 1506.60 SPEAKER_00 Все бы хорошо, но эта штука является breaking change, потому что если у вас уже есть в классе, в области видимости getter или setter, поле под названием field, то внедрив такую новую штуку в язык, вы потенциально поменяете поведение. -1506.60 1529.80 SPEAKER_00 То есть либо вы начнете использовать вот этот новый field, новое псевдопеременное внутри setter и таким образом поменяете поведение, потому что раньше ваш setter, например, обращался к полю field, или, наоборот, вы добавите фичу в язык, но ради сохранения обратной совместимости внутри setter field не будет означать то, ради чего его добавляли в язык, ну тоже как бы странное поведение. -1529.80 1535.56 SPEAKER_00 Короче, breaking change — это то, что новенького, то, что еще не сделано. -1535.56 1548.72 SPEAKER_00 Но на самом деле, те фичи, которые вы хорошо знаете, они тоже в каком-то смысле были добавлены, ну скажем так, с определенными приседаниями, чтобы избежать breaking change. -1548.72 1554.04 SPEAKER_00 Например, всем известное слово var — это ключевое слово языка. -1554.04 1561.92 SPEAKER_00 И его добавление — это тоже было breaking change, потому что технически у вас мог быть класс по имени var маленькими буквами. -1561.92 1566.80 SPEAKER_00 Это, наверное, очень странный класс, но по идее он мог быть. -1566.80 1573.08 SPEAKER_00 Например, я допускаю такой пример, что он мог бы быть автосгенерен из какой-нибудь, не знаю, грамматики. -1573.08 1580.16 SPEAKER_00 У вас там в вашем домене var — это нормальный термин для какого-нибудь бизнес-объекта, и у вас мог бы быть такой класс, ну для удобства. -1580.16 1582.84 SPEAKER_00 Да, это не по C# стилю, но почему нет? -1582.84 1589.76 SPEAKER_01 Ну проблема точно такая же, как и с field, то есть field тоже должен быть маленькими буквами назван так, класс, чтобы это было каким-то breaking changes. -1589.76 1595.92 SPEAKER_00 Нет, в field как раз необязательно, у тебя в field может быть private поле, названное уже field, и всё. -1595.92 1598.84 SPEAKER_01 А, private поле, ну да, private поле может быть. -1598.84 1616.72 SPEAKER_01 Ну вот, да, мне просто хочется сделать небольшую заметку, что если вам вдруг почему-то режется лук, когда мы говорим, что breaking changes возможны, то вот подумайте, что если бы Microsoft не пошёл на breaking changes, то у вас никогда бы не было слова var, потому что var — это реально мог такой класс существовать. -1617.04 1637.24 SPEAKER_01 Но если подумать разумно, то вероятность этого очень-очень мала, и вот ради парочки извращенцев в мире, у кого такое могло бы быть, как бы не развивать полностью язык, это ещё хуже решение, чем вот такими людьми там или проектами такими пренебречь немножко или как-нибудь там компиляторам помочь им проапдейтиться или ещё что-то. -1637.24 1641.60 SPEAKER_01 То есть breaking changes нужны, без них никуда не денешься, ну естественно в каких-то разумных пределах. -1641.60 1642.60 SPEAKER_00 Ну вот. -1642.60 1661.20 SPEAKER_00 Так вот, когда вводили var, то было принято следующее решение, что var означает «выведи, пожалуйста, тип этой переменной автоматически только в том случае, если нет в скоупе, в том месте, где вы написали var, класса под названием var, видимо». -1661.20 1696.08 SPEAKER_00 И как пишет Мэттс у себя в статье выше, если вы помните, там когда только вводили var, были всякие споры, да, там типа var или не var, использовать var или использовать var только там, где тип явно виден из правой части, ну короче там даже в райдере есть, или в шерпе такие настройки типа, да, когда автоконвертить в var, то многие, кто были абсолютно против вара, делали простую штуку, они заводили какой-нибудь утилитный, в утилитном пакете, который включается во все там ваши проекты, компании, класс под названием var маленькими буквами и всё, у вас везде var не работает. -1696.08 1697.08 SPEAKER_00 Вот. -1697.08 1699.72 SPEAKER_00 Такая простая как бы штука. -1699.72 1715.08 SPEAKER_00 И Мэттс говорит, что это как раз очень плохо, не в смысле тот факт, что заводили такую штуку, а тот факт, что заведение класса где-то далеко в каком-нибудь чёрт знает каком нугете влияет на поведение программы в совершенно несвязанном логическом месте. -1715.08 1718.84 SPEAKER_00 Тот факт, что просто эта штука видна в скоупе не означает, что она должна влиять. -1718.84 1719.84 SPEAKER_00 Вот. -1719.84 1722.56 SPEAKER_00 Ну, тем не менее, в общем, штука есть. -1722.56 1723.56 SPEAKER_00 Дальше. -1723.56 1753.24 SPEAKER_00 Есть такая фича в C#, называется она, я, кстати, не знаю, как это на русском называется, я её называю дискард, ну по-английскому называется дискарды, это когда вы можете написать одиночное подчёркивание вместо символа, вместо имени переменной, и в этом случае компьюратор будет понимать, что вам вообще не важно, что там, такое часто используют, например, для out-параметров, то есть если у вас есть функция, которую вам нужно вызвать, у неё есть out-параметр, но вам он не нужен, то вы просто туда пишете там out, не знаю, там int подчёркивание, и компьюратор знает, что подчёркивание в принципе как бы можно игнорировать. -1753.24 1754.24 SPEAKER_00 Вот. -1754.24 1765.88 SPEAKER_00 Но технически, опять же, подчёркивание - это валидное имя переменной, никто никогда не запрещал в C# заводить такое имя переменной, наверное, это опять же странное имя, но почему нет? -1765.88 1767.04 SPEAKER_00 Вот. -1767.04 1788.00 SPEAKER_00 Поэтому, когда вводили эту фичу, то ввели её, задумайся, с приседаниями следующими, что она будет, вот одиночное подчёркивание будет работать дискардом только в тех случаях, которые синтаксически были невозможны в прошлых версиях C#. -1788.00 1791.08 SPEAKER_00 Ну, типа, это в таком случае точно не breaking change. -1791.08 1798.60 SPEAKER_01 То есть, когда ты не мог написать var подчёркивание, потому что тебе нужно было бы раньше указать тип какой-нибудь, да? -1798.60 1812.08 SPEAKER_00 Ну, не var, это не var подчёркивание, это int подчёркивание можно тоже, или там string подчёркивание, ну, в смысле, в каком-нибудь таком месте, в каком-нибудь, например, там tuple deconstruction, вот не было их раньше, вот тут появились, и вот тут можно дискарды, а в других местах нельзя. -1812.08 1825.52 SPEAKER_00 И более того, если есть хотя бы одно использование в качестве, ну, как бы, обычной переменной, то, опять же, дискардность отменяется, и подчёркивание становится валидной переменной. -1825.52 1847.20 SPEAKER_00 Короче, то есть такое ощущение, что ради того, чтобы сделать как можно лучше избежать потенциального breaking change, приходится в компиляторе, скорее всего, генерить огромное количество вот этой лишней логики по проверкам на тему, значит, а вот в каком ли мы месте, в каком мы контексте, в каком ли мы версии языка, вот это всё. -1847.20 1848.20 SPEAKER_00 Короче, сложно. -1848.20 1856.16 SPEAKER_01 Ну, и сам язык это делает некрасивым, неконсистентным, неудобным, сложным для объяснения, сложным для понимания, тебе надо учитывать какие-то неявные контексты. -1856.16 1860.08 SPEAKER_01 Ну, по-разному, по-разному, мне кажется, вот здесь надо жёстче. -1860.08 1957.00 SPEAKER_00 Да, и поэтому следующий как раз раздел – это про то, что, окей, breaking change кажется, что нужны, но breaking нужно делать так, чтобы вся команда, ну, короче, это не должно быть просто так, что типа, ой, я придумал новую фичу, кажется, на breaking, окей, у нас есть алгоритм, как мы будем работать с этим breaking change, ну, технически, да, там, кейнтворнинг, там ещё что-то, поэтому делаем спокойно и не паримся, нет, всё-таки надо минимизировать количество breaking change и делать их максимально безопасными, да, так скажем, и поэтому вот Мэдс предлагает в это ищу, и там дальше есть какое-то обсуждение, я не знаю, не дочитал там какое-то огромное обсуждение, но кажется, что они плюс-минус пришли к следующим критериям того, даже не критериям, а каким-то, ну, набору соображений, не знаю, лозунги, наверное, неправильное слово, как подходить к вопросу, нужно ли и как, если нужно делать этот самый breaking change, то есть, во-первых, это должно быть достаточно редко и с прям вот очевидными преимуществами для потенциальных пользователей, то есть, если действительно у нас есть какая-то старая фича C#, которая, ну, логически неудобна, а мы можем придумать новую, удобную и она точно будет полезна большинству пользователей C#, тогда есть смысл делать, если кому-то там, не знаю, трём человеком хочется какую-нибудь странную фичу в C# и остальные её никогда не будут использовать, но это breaking change, нет, тогда не будем делать. -1957.00 1986.96 SPEAKER_00 Дальше, даже если это breaking change, то технически, как ты раньше говорил, в адекватном, в среднестатистическом C# коде, скорее всего, breaking change не будет, ну, мало кто объявляет классы с именем var маленькой буквы, или мало кто поля объявляет с полем field, ну, обычно всё-таки чуть, в смысле, с названием field, обычно чуть более говорящие названия, да, у полей, то есть в реальном коде, скорее всего, breaking change не будет. -1986.96 2012.48 SPEAKER_00 Дальше, каждый конкретный breaking change должен быть объяснён соответствующими диагностическими месседжами, то есть не просто про то, что типа, а, чувак, ты использовал новую версию компилятора, может у тебя что-то сломается, ну, может быть это будет про слово field, а прям конкретно в нужном месте, вот здесь вот подчеркивается какое-нибудь использование слова field, да, и говорится, вот тут у тебя сломается так-то, вот. -2012.48 2065.44 SPEAKER_00 И последнее четвёртое, для каждого такого случая должен быть хороший дефолтный фикс, который можно применить в EDE-шке, грубо говоря, да, там типа, ну, родственники, да, условно говоря, аналайзеры и фикс к нему, который будет а) простой, то есть не потребует переписывания половины проекта, б) железно работающий, то есть не то, что он там типа в большинстве случаев починит, но 50 на 50, кто-то может ещё сломать, вот, и полностью автоматизируемый, то есть типа, а, и самое главное, я забыл, он должен как это, сохранять смысл кода, то есть, грубо говоря, значит, вы должны иметь возможность каким-то образом поймать эти варнинги, я сейчас объясню каким, после чего, посмотрев на них, сказать, ага, понятно, сказать, применить фикс ко всему solution и быть уверенным, что после этого ваш solution нормально будет работать. -2065.44 2070.96 SPEAKER_01 Ну, типа какой-нибудь migrate процесс запустить и замигрировать на новую версию C#. -2070.96 2079.72 SPEAKER_00 Ну, типа такого, там скорее должно быть case by case, в смысле по каждому из breaking changes, вы должны посмотреть, понять, ага, может быть, что-то руками самому поправить. -2079.72 2086.36 SPEAKER_00 О, блин, кто у нас называл класс, слово var, давайте перепишем, вот, либо просто автоматически что-то сделать. -2086.36 2103.04 SPEAKER_00 Вот, и вот как раз-таки на примере Филда, он говорит, что типа, ага, давайте примерим эту штуку к Филду, вот эти принципы, да, как бы, есть ли у нас явная, так сказать, польза для пользователей. -2103.04 2116.72 SPEAKER_00 Ну, как бы, да, есть, в том смысле, что это одна из, она это, наверное, не самая высоко залайканная фича в гитаре PC#, но довольно высоко, то есть, есть такая просьба. -2116.72 2128.92 SPEAKER_00 Ну, и она звучит логично, имея value, имеет еще и field, но все хорошо с точки зрения, так сказать, adoption от community, все будут, скорее всего, рады. -2128.92 2159.16 SPEAKER_00 Второе, будет ли тот факт, как бы, будет ли соблюдаться тот факт, что реальный breaking change будет действительно встречаться редко в реальном коде, и да, таки будет, потому что для того, чтобы это было breaking change, добавление филда ключевого там слова или какого-то специального слова внутри сеттера или геттера для property будет breaking change, только если внутри такого геттера или сеттера есть доступ к чему-либо под названием field маленькими буквами. -2159.16 2162.70 SPEAKER_00 Ну, что это, скорее всего, означает private поле. -2162.70 2165.72 SPEAKER_00 Как я сказал, вряд ли вы называете private поля просто словом field. -2165.72 2169.48 SPEAKER_00 Я не могу придумать, зачем, но технически такое возможно. -2169.48 2170.48 SPEAKER_00 Дальше. -2170.48 2173.96 SPEAKER_01 В этой ситуации, надо признать, может встретиться гораздо чаще, чем в R-классе. -2173.96 2185.24 SPEAKER_00 Ну, я согласен, какой-нибудь там, не знаю, опертка над чем-нибудь, где у тебя единственное поле, но я все равно как-то не думаю, что это действительно часто. -2185.24 2186.24 SPEAKER_00 Не думаю. -2186.24 2190.88 SPEAKER_00 Это чаще, чем в R, конечно, может быть, но все равно абсолютный процент очень мало. -2190.88 2200.04 SPEAKER_01 Ну вот смотри, можно, например, привести пример, это недалеко ушло от поля под названием value, а поле под названием value применяется много где, в том числе и самим Microsoft. -2200.04 2211.60 SPEAKER_01 Вспомним, например, класс Nullable, то есть структуру Nullable, у которой есть field value, допустим, или там, по моему, гуйда там какой-то value есть, или урла, ну то есть, или options. -2211.60 2215.40 SPEAKER_01 Ну то есть, есть много классов, у которых есть поле value от самого Microsoft. -2215.40 2220.00 SPEAKER_01 Но кажется, что поле field недалеко ушло от такого названия. -2220.00 2226.76 SPEAKER_00 Все верно, я согласен, возможно, действительно так, вопрос, но тебе нужно не только поле field, но тебе еще нужна пропертя. -2226.76 2245.12 SPEAKER_00 То есть тебе нужен класс, у которого есть внутреннее поле, плюс поверх него есть пропертя, которая внутри доступается к этому полю, ну, наверное, есть такие, но, короче, Microsoft, возможно, опять же, они же не просто так считают это из воздуха, они как-то явно это, не знаю, ищут по кодовой базе GitHub, например. -2245.12 2250.40 SPEAKER_00 Непонятно, насколько она репрезентативна, но думаю, что для некоторых… У них просто выбора нет -2250.40 2251.40 SPEAKER_01 особо. -2251.40 2252.40 SPEAKER_00 Ну да. -2252.40 2259.92 SPEAKER_00 Дальше, с точки зрения диагностики, тут тоже все четко, вот там, где ты использовал field, в этом месте его можно подчеркнуть и сказать, вот тут будет breaking change. -2259.92 2267.76 SPEAKER_00 И дефолтный фикс тоже довольно простой, вы просто меняем это на this.field и все, и у тебя все продолжает работать. -2267.76 2273.44 SPEAKER_00 То есть тут без вариантов, все хорошо, все нормально. -2273.44 2276.44 SPEAKER_00 Как, собственно, с этим будут жить? -2276.44 2284.20 SPEAKER_00 Мы вот про это уже когда-то говорили, теперь это оформлено в виде уже вот полноценного такого issue, так сказать, в письменном виде, нормально зафиксировано. -2284.20 2293.56 SPEAKER_00 Смотрите, значит, допустим, мы в новой версии C# что-то делаем breaking, да, вот сейчас выйдет у нас новый C#. -2293.56 2299.52 SPEAKER_00 Ну сейчас, больше, чем через полгода, мы в нем сделаем breaking change. -2299.52 2309.56 SPEAKER_00 Компилятор версии новый, когда он компилирует для любой версии старее, чем новая, ну то есть выйдет у нас какой сейчас, тринадцатый будет, да? -2309.56 2312.40 SPEAKER_00 Я же ничего не путаю, или я уже запутался в числах? -2312.40 2313.40 SPEAKER_00 Или тринадцатый вышел? -2313.40 2314.40 SPEAKER_01 Давай. -2314.40 2315.40 SPEAKER_01 Ну следующее, короче. -2315.40 2316.40 SPEAKER_00 Не это самое, а это самое. -2316.40 2319.64 SPEAKER_00 VNEXT, давай, не будем с числами, что-то я уже путаюсь в числах. -2319.64 2328.60 SPEAKER_00 Короче, выйдет VNEXT, а мы берем, в общем, если мы компилируем под любую версию старше, чем VNEXT, то будет ворнинг в коде. -2328.60 2330.60 SPEAKER_00 То вот тут будет все плохо. -2330.60 2331.60 SPEAKER_00 Вот. -2331.60 2342.92 SPEAKER_00 В ворнинге будет, соответственно, тот самый message, который там из критерия номер три выше, да, будет suggested fix, который, соответственно, из критерия номер четыре. -2342.92 2345.48 SPEAKER_00 Все, в общем, по-моему, все идеально. -2345.48 2350.46 SPEAKER_00 И всякие DE-шки, всякие миграторы должны все эти фиксы, конечно же, предлагать. -2350.46 2372.14 SPEAKER_00 А теперь вопрос, кто, ну как бы, такая стратегия не гарантирует того, что про этот breaking change узнают все, потому что многие просто апгрейдят, ну, ты типа апгрейдишься до последнего, ты апгрейдишь SDK, тут же апгрейдишь target, и типа все хорошо. -2372.14 2381.26 SPEAKER_00 Но поскольку версия языка, под которой компилируется, определяется таргетом, то не будет ситуации, когда весь шаро-компилятор компилирует под старую версию языка. -2381.26 2382.90 SPEAKER_00 Это пока открытый вопрос. -2382.90 2385.62 SPEAKER_00 Что с этим делать? -2385.62 2389.78 SPEAKER_00 Ну, про него чуть-чуть дальше, может быть, еще скажу. -2389.78 2393.50 SPEAKER_00 Теперь смотрите, дальше Мэттс говорит интересную штуку. -2393.50 2419.06 SPEAKER_00 На самом деле, если у вас есть код, он компилировался в старой версии компилятора, работал, у вас там стоит warnings as errors, вот это все, и вы добавляете новые ворнинги на существующий код, то само по себе это вообще, так говорят, тоже breaking change, то есть борясь с breaking change на уровне языка, мы вносим breaking change на уровне билда. -2419.06 2421.30 SPEAKER_00 То есть у вас проект собирался, теперь перестал. -2421.30 2429.46 SPEAKER_00 Да, вы, конечно, переехали на новый, не знаю, на новый таргет, но тем не менее, как бы тоже breaking change. -2429.46 2449.46 SPEAKER_00 Но здесь Мэттс говорит следующее, что, во-первых, мы уменьшаем количество этих ворнингов, уменьшаем точнее количество мест и раз, когда это может встретиться, ну типа раз в год, вот это может случиться, вот когда мы SDK проапгрейдили, тогда случилось, поэтому это будет редко. -2449.46 2460.42 SPEAKER_00 Второе, у компилятора будет специальный флаг, называется выключить нахрен все breaking change ворнинги, вот эти все специальные ворнинги, конкретно про breaking change будет специальный флаг, который вы говорите, вот их конкретно выключи, остальные не оставь, а эти выключим. -2460.42 2461.42 SPEAKER_00 Почему? -2461.42 2485.10 SPEAKER_00 Потому что, во-первых, у вас могут быть какие-то там легаси проекты, в которых вы знаете, что вы никогда ничего не будете фиксить, и вам неинтересно видеть эти ворнинги, ну то есть вы апгрейдите SDK, но вы не собираетесь обновлять target framework на них, это как раз тот кейс, когда ворнинги вам нужно показать, но вы знаете, что вы не будете обновлять target framework у этих проектов, поэтому ворнинги можно выключить. -2485.10 2505.82 SPEAKER_00 И второе, на самом деле, как говорит Мэттс, в принципе на билд-серверах эти ворнинги тоже по идее не нужны, потому что эти ворнинги то, с чем может программист что-то сделать, поэтому они нужны при билде вашем локальном, чтобы вы их видели, а на билд-сервере, ну как бы, пока оно собирается под старый target, там все работает по старому, они не нужны. -2505.82 2515.90 SPEAKER_01 Ну если бы только локально, они могли бы сделать это просто отдельной командой, типа check for migrate, vnext или что-нибудь в этом духе, ну тогда никакого смысла их бы не было в компи засовывать. -2515.90 2519.98 SPEAKER_01 Никто не будет запускать отдельную команду, ну ты что. -2519.98 2525.66 SPEAKER_01 Ну опять же, Visual Studio будет, если мы говорим только про локально, вот пожалуйста, Visual Studio будет запускать эту команду. -2525.66 2528.86 SPEAKER_01 А те, кто умные, те руками могут и сами определенно раз в месяц запускать. -2528.86 2530.94 SPEAKER_00 Ну в общем, пока принято. -2530.94 2539.22 SPEAKER_01 Мне кажется, что как раз-таки наоборот, на CI, если у тебя будет CI падать с этими ворнингами, с этими break-in-changes, то это будет хороший показатель. -2539.22 2542.22 SPEAKER_01 Ты увидишь, ты точно увидишь, ты это не пропустишь никогда. -2542.22 2549.86 SPEAKER_01 Ну и если ты хочешь подавить, пожалуйста, присылаешь флажочек, который говорит, что не надо мне падать на break-in-changes, и он проходит дальше. -2549.86 2553.06 SPEAKER_01 То есть это не то, чтобы сильно ухудшает работоспособность. -2553.06 2555.82 SPEAKER_00 Я так понимаю, что они так и будут делать. -2555.82 2559.62 SPEAKER_00 То есть не так, что компилятор будет понимать, что он в CI, и тут же глушить. -2559.62 2560.62 SPEAKER_00 Нет. -2560.62 2567.10 SPEAKER_00 Это скорее, что ты типа должен в своем CI этот флажок написать явно. -2567.10 2568.10 SPEAKER_00 Хочешь, пиши, хочешь, не пиши. -2568.10 2570.94 SPEAKER_00 Ну вот это хорошо, вот это нормальный в принципе выбор. -2570.94 2575.42 SPEAKER_00 И последний момент тоже довольно важный. -2575.42 2588.74 SPEAKER_00 Как вы знаете, у нас, как вот мы сейчас только что говорили, точнее, компилятор, когда он компилирует ваш C# код, он знает target language level, так называемый, или target версию языка. -2588.74 2591.42 SPEAKER_00 Обычно она определяется таргетом вашего проекта. -2591.42 2603.98 SPEAKER_00 То есть если вы указываете там какой-нибудь .NET, не знаю, 6, возьмется тот C#, который был релизный на момент .NET 6 в качестве таргетного, то есть компилятор будет считать, что вы пишете на том C#. -2603.98 2608.46 SPEAKER_00 Если вы таргетите .NET какой-нибудь 8, вот возьмется последний. -2608.46 2612.66 SPEAKER_00 Но есть две специальных версии. -2612.66 2616.98 SPEAKER_00 Версия на специальный номер 1 – это latest. -2616.98 2635.34 SPEAKER_00 Вы можете в C++ указать lang version, по-моему, называется пропертя, указать туда latest, ну и да, естественно, вы можете указать любую другую фиксированную, то есть вы даже в таргете .NET 6 можете сказать lang version, вот какая сейчас у нас текущая, и он будет компилить ее под текущую нормальную, но можно указать latest. -2635.34 2639.86 SPEAKER_00 И тогда он берет, типа, максимально новую, которую я могу. -2639.86 2648.50 SPEAKER_00 И понятно, что никаких breaking, change warning тогда не будет, потому что у вас нету кейса, когда новый компилятор компилирует под старую версию языка. -2648.50 2662.10 SPEAKER_00 И здесь медс говорит, что, скорее всего, версию под названием latest уберут, ее будет указывать нельзя, ну, точнее, указывать будет можно, но это будет warning. -2662.10 2667.62 SPEAKER_01 Блин, ну это вообще беспредел, это моя самая любимая опция была. -2667.62 2671.98 SPEAKER_01 Так не хотелось вот с этими старперами жить, которые раз в 4 года обновляют эту версию. -2671.98 2674.50 SPEAKER_01 Я всегда под latest сижу, мне все нравится. -2674.50 2676.70 SPEAKER_00 Ну вот, пока не сломали. -2676.70 2687.82 SPEAKER_00 Вот, и для тебя будет специальная опция, которая сможет, так сказать, засопросить этот warning про то, что не надо ворнинги про latest. -2687.82 2692.94 SPEAKER_00 Ну то есть у них убрать в английском это у них называется retire и в кавычках. -2692.94 2699.74 SPEAKER_00 То есть я так понимаю, что типа они не будут промоутить ее использование, но прям убирать-убирать совсем ее не планируют. -2699.74 2703.14 SPEAKER_00 То есть она останется, но будет всегда под warning, который можно всегда убрать. -2703.14 2705.94 SPEAKER_01 Опять какие-то костыли непонятные, блин. -2705.94 2708.74 SPEAKER_00 Вот да, смотри, а мы обсуждаем breaking change, да? -2708.74 2709.74 SPEAKER_00 Вот тебе breaking change. -2709.74 2728.18 SPEAKER_01 Ну подожди, а давай вот вернемся к той идее, что если б у нас все-таки была бы отдельная команда, которая говорит товарищ компилятор, проверь мне вот этот мой код, я собираюсь там перейти с дотнета 6 на 7, проверь мой код и выдай мне ворнинги, на которые я должен обратить внимание. -2728.18 2730.10 SPEAKER_01 Ну это же решило бы абсолютно вообще все проблемы. -2730.10 2736.58 SPEAKER_01 Не надо было бы запрещать там latest, не надо было бы там какие-то флажки, не надо какие-то дизейблы придумать, просто, блин, сделайте отдельную команду и все. -2736.58 2741.62 SPEAKER_01 И как часто ее запускать, то я сам решу, в конце до конца у меня есть MCI-настрой, который каждую ночь ее будет запускать и проверять что-то. -2741.62 2742.62 SPEAKER_00 Ты такой умный. -2742.62 2748.70 SPEAKER_00 Настроишь, и ты точно знаешь, с какой версии языка ты переходишь на какую версию языка. -2748.70 2759.90 SPEAKER_00 Большинство, кажется, народу, Microsoft видео все-таки ориентируется на большинство, они тупо сидят в Visual Studio, жмут кнопку publish, и у них все работает. -2759.90 2766.74 SPEAKER_00 И вот как бы для их кейса никто не будет запускать все эти тулы, там CI-настроить, вот это все. -2766.74 2769.58 SPEAKER_00 Но при этом их код тоже нельзя ломать. -2769.58 2780.74 SPEAKER_01 Просто мы придем постепенно с таким путем, мы придем к тому, что у нас в дотнет-билде будет интегрирован какой-нибудь дотнет-мигрейт, который будет знать, и делать, и проверять, и все на свете. -2780.74 2786.82 SPEAKER_01 У тебя билд будет или медленный, или сложный, или то другое вместе. -2786.82 2790.50 SPEAKER_00 Не знаю, это, может быть, надо смотреть. -2790.50 2797.74 SPEAKER_00 То есть, опять же, надо понимать, что это все не окончательно финальное решение, которое с нами теперь на десятки лет. -2797.74 2845.66 SPEAKER_00 Это некоторый пропозал, который сейчас у МЭДСа родился и сформировался в некоторую уже документированную, структурированную штуку, которую они, скорее всего, собственно говоря, которую они попробуют на том самом филде, вот этот филд аксессор, который внутри пропертий, они его собираются сделать в следующем C# 13, и на нем отработать эту штуку, и посмотреть, какой будет фидбэк от комьюнити, что все остальные скажут, какой фидбэк будет не только от комьюнити, надо понимать, что фидбэк от комьюнити будет это, как сказать, народ типа тебя, который понимает, что они делают, в большинстве своих, могут настроить себя и все остальное, и так далее. -2845.66 2867.50 SPEAKER_00 Возможно, будет фидбэк от каких-нибудь там first, second, third party, кастомеров, где какие-то, возможно, более бизнес там, ну такие, как интерпрайс-программисты сидят, которые только вижу в студии что-то делают, условно говоря, в таком духе, то есть и вероятно к C# 14 следующей версии может что-то еще изменится, посмотрим, пока не знаю. -2867.74 2891.50 SPEAKER_00 Вот, еще последний момент, то, что я недорассказал, помимо лейтеста есть еще специальная версия под названием превью, вот, с ней делать ничего не хотят, если ты такой крутой, что ты указал превью в своем C#, ты, значит, сам лучше Майкрософта знаешь, какие breaking changes могут быть в своем коде, тебя вообще ни о чем предупреждать не будут, вот такие вот дела нас ждут в C#. -2891.50 2906.46 SPEAKER_01 Ну, хорошо, хорошо, вроде звучит вполне разумно, но мне нравится сама ситуация, что наконец-то начали съезжать с этой пьяной точки, когда блюли всякие различные совместимости просто без оглядки, как бы обязательно-обязательно совместимость. -2906.46 2916.86 SPEAKER_01 Наверное, в каких-то вещах это хорошо, но не здесь, ну, вот, например, совместимость в Windows мне нравится, да, когда мы можем на последней винде запустить там какой-нибудь DOS и проиграть в старинные игры, которые делались еще под MS-DOS. -2916.86 2927.70 SPEAKER_01 Вот это нормально, ну, потому что действительно очень много кейсов в мире существует, когда непонятно, под чем и кто сейчас сидит, и что и кто сейчас запускает. -2927.70 2938.82 SPEAKER_01 Но когда мы разговариваем с программистами, у которых кажется, что должно охватить ума, как бы запустить пару команд и посмотреть пару отчетов, то здесь, мне кажется, уже какая-то избыточная паранойя пошла. -2938.82 2942.66 SPEAKER_00 Ну, может быть, они что-то понимают о своих заказчиках? -2942.66 2946.74 SPEAKER_01 Ну, может быть, может быть, я в это искренне верю. -2946.74 2954.98 SPEAKER_01 В общем, хорошая тенденция на то, что мы начали об этом думать, начали каким-то образом ломать breaking changes, в общем, и будем надеяться, что мы дальше пойдем по этой дорожке. -2954.98 2970.78 SPEAKER_01 Я уверен, что мы сильно не углубимся, как бы не будет у нас разницы, как между питонами, но вот такие мелкие вещи, как классы вар с маленькой буквы, их надо истреблять, и под них не надо подстраиваться. -2970.78 2977.78 SPEAKER_00 Ну, будем надеяться, посмотрим, что будет, а у нас тем временем вышел релиз Visual Studio. -2977.78 2992.50 SPEAKER_01 Visual Studio версия 20.22.17.9, когда они уже нормальные версии начнут давать, а также вышел превью, соответственно, 17.10, и вот эти два экземпляра, два анонса мы сегодня с вами и рассмотрим. -2992.50 2999.50 SPEAKER_01 Прежде всего, конечно же, в каждом релизе выходит что-то про копайлот, GitHub-копайлот. -2999.50 3007.02 SPEAKER_01 Нужно напомнить, что для этого вам нужна отдельная платная подписка на GitHub-копайлот, иначе вы ничего этого не увидите. -3007.02 3033.18 SPEAKER_01 И прежде всего, Visual Studio уже в релизе научилась генерировать commit-месседжи, т.е. у вас есть какой-то нобор файлов, которые вы поменяли, и самое сложное – это, конечно же, не реализовать фичу, не протестировать ее, не написать на нее какой-то технический анализ, а самое сложное – это придумать commit-месседж к этой фиче, когда вы пытаетесь запустить ее вашим коллегам на pull-request или в Git-репозиторий, или куда-то туда. -3033.18 3041.98 SPEAKER_01 И вот теперь вам поможет кнопочка, которая запустит GitHub-копайлот и сгенерит вам, проанализирует все ваши изменения и сгенерит вам описание. -3041.98 3051.58 SPEAKER_01 Нужно сказать, что описание – это не просто какой-то однострочник, который у вас там будет появляться, это такой полноценный, блин, прямо вот статья, прямо анонс. -3051.58 3055.34 SPEAKER_01 Т.е. он реально под каждую фичу расписывает там чуть ли не по абзацу. -3055.34 3059.46 SPEAKER_01 Я не знаю, настраивается это где-то или не настраивается, но прямо это хороший документ получается. -3059.46 3060.46 SPEAKER_00 Так вот так вот нужно. -3060.46 3070.82 SPEAKER_00 Они может такое на этих самых перейдут, на своих анонсах превью, что закинул им набор коммитов, как вот в EF Core там сейчас, и все, и вот тебе готовая статья. -3070.82 3082.38 SPEAKER_01 Ну может быть, может быть, но там, мне кажется, нужно 10 уровней и потом еще самурайзеров вставить, строить, потому что если он там для трех файлов выдает абзацы текста, то у Микрософта этих файлов там тысячи летают. -3082.38 3086.26 SPEAKER_01 Поэтому нужен какой-то самурайзер очень умный, который все это способен объединить. -3086.26 3090.46 SPEAKER_00 И обратно сложить, а потом еще выделить основные тезисы для нас. -3090.46 3096.22 SPEAKER_01 Да, отдельно там для разработчиков, для маркетологов, для анонсеров, для конференций и так далее. -3096.22 3100.02 SPEAKER_00 Ладно, да, надо еще допиливать Микрософт, Капайлот, окей. -3100.02 3108.38 SPEAKER_01 Вот, еще поддержаны так называемые слэш-команды, это когда вы у Капайлота просите какие-то стандартные для программиста вещи. -3108.38 3115.78 SPEAKER_01 Ну, например, пофикси мне этот код, или напиши документацию к этому методу на основании его содержимого, или объясни вообще, что этот метод делает. -3115.78 3120.22 SPEAKER_01 В общем, есть маленькие команды, которые с помощью слэша вызываются очень быстро и удобно. -3120.22 3138.46 SPEAKER_01 Еще одна прикольная штучка – это инлайн-чат, это когда вам не нужно отвлекаться на какое-то левое окошко, вы прямо в коде пишите, у вас прямо в коде всплывает какое-то окошко, куда можно повзаимодействовать с Капайлотом, дать ему какие-то команды, попросить отрефакторить текущий код, где сейчас сидит курсор. -3138.46 3142.14 SPEAKER_01 В общем, это все сделать удобно и меньше отвлекаться. -3142.14 3148.42 SPEAKER_01 В общем, это кажется, что довольно полезная штука будет и продуктивность она должна хорошо улучшать. -3148.42 3149.42 SPEAKER_01 Про Visual Studio. -3149.42 3154.06 SPEAKER_01 Также у нас есть оптимизации и улучшения в Memory2Log. -3154.06 3166.10 SPEAKER_01 Прежде всего, это Event Handler Leak поисковик, т.е. у вас теперь в Memory Management вкладочке есть такая специальная опция – это найти все Event Handler Leaks. -3166.10 3174.02 SPEAKER_01 Это один из самых популярных ликов, которые существуют, т.е. утечек памяти, когда вы подписываетесь на какие-то события и забываете про них отписаться. -3174.02 3179.70 SPEAKER_01 Особенно, если мы говорим про UI-разработку на десктопах, винформах, DPF-ах и прочем. -3179.70 3181.46 SPEAKER_01 Там эта проблема очень актуальна. -3181.46 3189.10 SPEAKER_01 И также прорабатывается HotPath ToRoot, это показывается вам самые горячие точки для оптимизации. -3189.10 3204.98 SPEAKER_01 Т.е. если вы захотели прооптимизировать перформанс в вашей программе, то самое лучшее, что вы можете сделать, это посмотреть на вот этот HotPath, который вам посоветует, опять же Memory2Log, и попытаться его каким-то образом простимулировать, прооптимизировать. -3204.98 3209.50 SPEAKER_01 И это даст вам самый лучший прирост в вашей программе, который вы могли бы только придумать. -3209.50 3212.22 SPEAKER_01 Еще из нововведений. -3212.22 3217.78 SPEAKER_01 Сделали меньше модальных окошек, в частности теперь дебаггинг визуалайзеры не модальные. -3217.78 3226.10 SPEAKER_01 Это те окошки, которые вы можете, например, в дебаг в очаг открыть, для того, чтобы посмотреть более подробно какой-то объект или что-то еще. -3226.10 3232.40 SPEAKER_01 В общем, раньше каждое окошко можно было открыть только в одном экземпляре, оно полностью перекрывало абсолютно всю работу. -3232.40 3239.50 SPEAKER_01 Сейчас же их можно пооткрывать несколько штучек и в это же время продолжать редактировать код, что очень удобно. -3239.50 3242.46 SPEAKER_01 Сделана улучшая поддержка Multiproject Configuration. -3242.46 3253.46 SPEAKER_01 Это когда вы можете для запуска ваших нескольких проектов, то есть, допустим, у вас есть Solution, и в Solution есть несколько проектов, допустим, несколько микросервисов, которые друг с другом взаимодействуют. -3253.46 3260.30 SPEAKER_01 Вы можете настроить Visual Studio так, чтобы при нажатии F5 у вас поднималось сразу, запускалось сразу несколько этих проектов. -3260.30 3262.62 SPEAKER_01 И вы, естественно, оттачались к ним сразу. -3262.62 3266.74 SPEAKER_01 Это было, в принципе, всегда, насколько я помню, в Visual Studio. -3266.74 3275.42 SPEAKER_01 А вот теперь в новой версии вы можете сохранить вот эти способы запуска в определенный файлик, в определенный профиль. -3275.42 3276.42 SPEAKER_01 И эти профили менять. -3276.42 3286.86 SPEAKER_01 Ну, например, если у вас очень большой Solution, то у вас может быть профиль с сервисами для бухгалтерии, профиль с сервисами для продажников, профиль с сервисами для инфраструктурного обслуживания. -3286.86 3294.22 SPEAKER_01 И вот вы между ними можете переключаться и запускать не все сразу, а определенный набор запускабельных сервисов. -3294.22 3296.18 SPEAKER_01 Тоже вполне удобно. -3296.18 3303.38 SPEAKER_01 У Razor файлов появилась возможность делать мультитаргет фреймворк, поддержку мультитаргет фреймворков. -3303.38 3306.06 SPEAKER_01 То есть можно комбинировать их в мультитаргеты теперь. -3306.06 3314.06 SPEAKER_01 У Razor scaffold'ов вышла поддержка, соответственно, scaffold'инга для Entity Framework. -3314.06 3321.06 SPEAKER_01 То есть, например, вы можете сказать, у меня вот стандартная сущность есть, сгенерикаю для нее стандартные Blazor компоненты. -3321.06 3323.46 SPEAKER_01 И у вас магическим образом сгенерится UI'ка. -3323.46 3350.90 SPEAKER_01 В этой UI'ке может сгенерироваться табличка, в этой табличке будут стандартные крут-операции, которые за вас уже будут удалять все, апдейтить, читать и прочие такие стандартные мелочи, которые как бы помогают на примитивных операциях, когда вы какие-то справочники делаете, то одной кнопкой можно для справочников нагенерить и обвязку вокруг Entity Framework'а и обвязку вокруг Blazor'а, и контроллеры вам там еще сами сгенерятся и мапперы сами построятся. -3350.90 3364.54 SPEAKER_01 Здесь можно ответить, что данный scaffold'инг использует Static Server Site Rendering, который был недавно зарелизан, то есть все это делается довольно оптимально, красиво и с поддержкой современных технологий. -3364.54 3370.62 SPEAKER_01 Еще классная штука – это улучшенная поддержка экосистемы. -3370.62 3373.62 SPEAKER_01 Так, под этим мудрым заголовком подразумевается довольно примитивная вещь. -3373.62 3437.58 SPEAKER_01 Вот у вас очень часто бывает в компании такая штука как расширение к студии, и эти расширения вам нужны для какого-то конкретного проекта, ну может быть какие-то там ростлин анализаторы или какой-нибудь рисовальщик графиков, или какой-нибудь компилятор ресурсов, или оптимизатор картинок, или оптимизатор css файлов, в общем плагинов в Visual Studio очень много, и часто бывает так, что какой-то конкретный проект от этих плагинов грубо говоря зависит, то есть чтобы вам нормально собрать что-то, вам нужны эти плагины, и вот сделали такую поддержку, что если вы в специальный файлик, который называется VSConfig, добавите описание тех расширений, которые вам нужны для этого проекта, Visual Studio их поймет, то есть при загрузке вашего солюшена, она проанализирует файлик VSConfig, если она найдет там обязательные плагины для этого солюшена, она спросит человека, который создал этот солюшен, а не хочет ли он случайно установить эти плагины, установить эти экстеншены, и если он вдруг случайно захочет, то она их пойдет и установит. -3437.58 3456.10 SPEAKER_01 Это все особенно прекрасно в рамках того, что VSConfig это отдельный файлик, то есть по сути вы его можете зачекинить в репозиторий, выложить в какую-то шару, распространять между членами команды и так далее и тому подобное, то есть это обычный файлик, и распространяется довольно легко. -3456.10 3465.98 SPEAKER_01 И нужно признать, что это была одна из самых запрашиваемых фич для студии, которая только была там в голосовалке. -3465.98 3481.42 SPEAKER_01 И эта фича в принципе сейчас уже есть в какой-то превью-версии, но она все еще находится под активной разработкой, поэтому если вдруг что-то не сработает, не судите строго, но я думаю тем, кому это было нужно, те уже могут смело пробовать. -3481.42 3494.02 SPEAKER_01 Такие нововведения у нас есть в Visual Studio, в принципе она старается не отставать от основного фреймворка, а если судить по чинь-жам, то даже сильно его перегоняет, потому что фреймворк что-то, вообще она запаздывает. -3494.02 3495.02 SPEAKER_01 Поэтому студия молодец. -3495.02 3501.70 SPEAKER_00 Да, я как раз хотел сказать, что прям в студии гораздо больше чинь-жам в превью, чем в основном фреймворке. -3501.70 3526.70 SPEAKER_00 Ну да ладно, с другой стороны, мне кажется, что, опять же, студия много чего копит по всяким разным своим превьюшкам, зато к релизу выпускает красивые статьи про то, что ах, как вы много всего сделали, поэтому приятно видеть, что инструмент развивается, мне действительно интересно, сколько лет они еще будут держать название 2022, и главное, зачем тогда держать это Visual Studio 2022, пусть оно будет просто 17.9. -3526.70 3531.70 SPEAKER_01 А никакого ishu на гитхабе нету, ну то есть должен был народ поинтересоваться таким же вопросом? -3531.70 3538.26 SPEAKER_00 Нет, студия же не на гитхабе живет никак, это полностью closed source, у нее, по-моему, даже никакого репозитория типа там с ishu за меня нету. -3538.26 3539.46 SPEAKER_01 И трекера ничего такого, да? -3539.46 3540.46 SPEAKER_00 Нет, нету. -3540.46 3542.06 SPEAKER_00 User Voice, помнишь такой? -3542.06 3549.82 SPEAKER_01 Ну да, User Voice помню, но именно вот там эти фичи все и были, ну надо в User Voice завести, типа, чуваки, вы забыли заинкрементировать на 2 года версию. -3549.82 3564.46 SPEAKER_00 Ну зачем, нет, ну возможно они будут инкрементировать только в том случае, если там будет какой-то мажорный, не знаю, перепишут на что-нибудь, плюс платформеры сделают, окей, ладно, вы не инкрементируете мажорный, но уберите, ну не знаю, короче, не знаю, 2022 как-то, уже 24-й год, странно. -3564.46 3573.26 SPEAKER_01 Ну да, ну то же самое, 17.9, 17.10 у них есть, они могут просто это убрать, использовать цифру 17 вместо года, зачем тащить, непонятно. -3573.26 3576.50 SPEAKER_00 И вообще 17. убрать и просто вижу услуги, 9, 10. -3576.50 3577.50 SPEAKER_01 Да? -3577.50 3583.14 SPEAKER_01 Ну вот как C# там делает, у них уже, 12-й C#, 11-й C#, вполне рабочие. -3583.14 3587.22 SPEAKER_00 Там много, номеров можно долго, какая-то я первая была, 2003, да? -3587.22 3588.22 SPEAKER_00 А, нет, 98, нет. -3588.22 3594.02 SPEAKER_01 Что-то мне кажется, что я 5-й, или я там не с виду работаю. -3594.02 3600.26 SPEAKER_00 Нет, 5.0, 6.0 были, а потом была, по-моему, сразу 2000, вижу в студию.net, 2002, наверное, или 2003, какая-то такая она -3600.26 3601.26 SPEAKER_01 была. -3601.26 3605.50 SPEAKER_01 Так, не пались, а то ты выдаёшь нас, торпёров, давай, и нас там хипстеры тоже должны их слушать. -3605.50 3611.30 SPEAKER_00 Вот, и, короче, до 2000-х ещё столько релизов можно сделать, короче, нормально, чисел хватит. -3611.30 3612.30 SPEAKER_00 Да-да, прокатит. -3612.30 3613.30 SPEAKER_00 На всех. -3613.30 3616.42 SPEAKER_00 Если что, потом пропустим, там всё уже забыло, почему 2000. -3616.42 3620.18 SPEAKER_00 Короче, к тому моменту можно уже и 2000 называть, все уже не будут знать, что это такое. -3620.18 3622.06 SPEAKER_00 Давай дальше, дальше у нас Andrew Locke. -3622.06 3628.14 SPEAKER_01 Да, давай что-нибудь более лёгенькое такое, что-то про новинки, про хардкоры, про оптимизации. -3628.14 3637.34 SPEAKER_01 Andrew Locke решил задаться непростым вопросом, а каким образом вы можете изменить урл, по которому ваш кестрил слушает все входящие запросы? -3637.34 3645.38 SPEAKER_01 Ну, для того, чтобы ISP.NET обрабатывал все запросы и отсылал контроллер, он должен их где-то слушать, на каком-то порту, на каком-то хосту, по какому-то протоколу. -3645.38 3650.02 SPEAKER_01 И вот какие способы есть для того, чтобы изменить этот хост? -3650.02 3657.46 SPEAKER_00 Погоди, погоди, погоди, мы такую статью точно обозревали года три назад, давно, короче, где-то благодаря подкасту. -3657.46 3664.82 SPEAKER_01 У Andrew Locke есть такая интересная хобби, он эту статью пишет в каждой новой версии .NET, потому что он находит новые способы запуска. -3664.82 3669.06 SPEAKER_01 И поэтому он не мог себя удержать и выпустил последнюю версию все-таки. -3669.06 3672.66 SPEAKER_01 Как теперь, вот на данный момент это можно и нужно задавать? -3672.66 3673.66 SPEAKER_01 Ну, давай посмотрим. -3673.66 3676.10 SPEAKER_01 Быстренько пробежимся. -3676.10 3685.46 SPEAKER_01 Итак, по дефолту, если вы ничего не настраиваете, просто поставили себе ISP.NET, завели контроллер, нажали F5, то ваше приложение запустится на Localhost 5000. -3685.46 3689.78 SPEAKER_01 Это стандартный порт, который, в принципе, ничем не плох, ничем не хорош. -3689.78 3690.78 SPEAKER_01 Это нормальный дефолт. -3690.78 3697.58 SPEAKER_01 Вы можете поменять это значение, вы можете поменять его, например, изменить порт или указать конкретный IP-адрес. -3697.58 3712.46 SPEAKER_01 Нужно понимать, что если на вашем компьютере установлено несколько сетевых карт или настроено несколько network протоколов, или настроено просто несколько IP-адресов, то вы, может быть, не хотите, чтобы ваш сервис слушал на каждом из них. -3712.46 3717.98 SPEAKER_01 Ну, например, один IP-адрес у вас может уходить в интернет, а другой адрес может уходить в локальную сеть. -3717.98 3722.86 SPEAKER_01 И вы хотите свой веб-сервер настроить только для локальной сети. -3722.86 3727.26 SPEAKER_01 В этом случае вам нужно прибаниться только к IP-адресу локальной сети. -3727.26 3740.42 SPEAKER_01 Ежели вы просто укажете Localhost или там какую-нибудь звездочку, то ISP прибанится ко всем адресам, то есть он будет доступен с любой сети, хоть с интернета, хоть с локальной, хоть с любой другой, к которой к нему можно обратиться. -3740.42 3742.02 SPEAKER_01 И тут немножко поаккуратнее. -3742.02 3745.90 SPEAKER_01 И по дефолту он как раз-таки слушает Localhost 5000. -3745.90 3751.10 SPEAKER_01 Вы можете указать один конкретный адрес, вы можете указать несколько адресов, разделяя их разделителем. -3751.10 3757.78 SPEAKER_01 Опять же, это невозбранно, или можете сказать, что слушай вообще все адреса, которые найдешь на моем локальном хосте. -3757.78 3760.18 SPEAKER_01 Как же теперь их можно поменять? -3760.18 3771.98 SPEAKER_01 Ну, наверное, самое очевидное, хотя, может быть, и не самое очевидное, это использовать специальный метод расширения для веб-аппликейшн-билдера, который называется UseUrls. -3771.98 3786.14 SPEAKER_01 То есть в нашем программ.cs файле мы создаем веб-аппликейшн-билдер, это, наверное, одна из тех строчек, которые все еще не убрали, которые все еще нам доступны, и у этого билдера у нас есть куча свойств для настройки нашего будущего сервиса. -3786.14 3794.26 SPEAKER_01 В частности, есть .webhost.useurls, и туда вы в качестве строки можете передать вот этот URL, по которому вам нужно слушать. -3794.26 3813.18 SPEAKER_01 Другое интересное нововведение, нововведение его ввели в шестом дотнете, почему его раньше не было, никто не знал, и, наверное, все очень сильно хотели, это заключается в том, что вы можете этот URL настроить не только у билдера, но и непосредственно в своем уже конкретном аппликейшне. -3813.18 3822.78 SPEAKER_01 То есть вы билдер позадавали, вызвали метод билд, вам вернулся аппликейшн, и у этого аппликейшна вам все еще есть возможность настроить URL для прослушивания. -3822.78 3829.54 SPEAKER_01 У аппликейшна есть свойство, которое называется .urls, и к нему можно добавить такой же точно URL. -3829.54 3855.90 SPEAKER_01 За сценой этот urls, это свойство, на самом деле ходит к сервер-фичам, то есть это специальный такой классик, который хранит все возможные свойства, которыми обладает текущий сервер, и вытаскивает оттуда специальный сервис, который называется iservice-address-feature, то есть фича, которая поддерживает оповещения, даже не оповещения, поддерживает коллекцию всех сервисных адресов, которые нужно послушать. -3855.90 3861.70 SPEAKER_01 И вот в этот сервис-адрес-фичу оно записывает новый адрес, который вы добавили. -3861.70 3865.34 SPEAKER_01 На самом деле к этой фиче обращается очень много методов. -3865.34 3884.74 SPEAKER_01 В частности, вы, например, можете вызвать app-run, то есть запустить ваш аппликейшн, и в ране есть перегрузка, которая точно так же принимает URL, по которому нужно послушать, по которому нужно запустить кестрил, и этот URL, который принимает в ране, делает абсолютно то же самое. -3884.74 3891.06 SPEAKER_01 Он берет сервис-адрес-фичу и просто-напросто да, этот URL записывает, а эту фичу уже потом потребляет кестрил. -3891.06 3895.08 SPEAKER_01 В общем, поэтому есть несколько endpoint, которые под капотом используют одно и то же. -3895.08 3897.66 SPEAKER_01 В общем, мы их рассматривать не будем, будем считать, что это одно и то же. -3897.66 3898.66 SPEAKER_01 Дальше. -3898.66 3909.58 SPEAKER_01 Для того, чтобы настроить еще этот URL, вы, возможно, захотите воспользоваться стандартным интерфейсом опций, который пришел к нам в ASP.NET и также во весь .NET. -3909.58 3918.78 SPEAKER_01 Опции позволяют вам комбинировать и загружать настройки, конфигурацию из нескольких источников, из нескольких провайдеров опций. -3918.78 3935.38 SPEAKER_01 По умолчанию, Configuration Manager использует в качестве источника для своих настроек Upsettings JSON-файл, а также Upsettings с Environment JSON-файл, то есть, когда вы хотите отдельно для Production, отдельно для Development, отдельно для стейджинга сделать файлики. -3935.38 3938.42 SPEAKER_01 Это тоже в стандартную поставку, в стандартный комплект входит. -3938.42 3947.46 SPEAKER_01 Также он загружает секреты, после этого Environment Variables и в последнюю очередь Command-Line-аргументы, которые перебивают абсолютно все, что было вышесказано. -3947.46 3956.14 SPEAKER_01 В общем, из вот этой всей шарманки, из вот этой всей каши он, соответственно, может вам сгенерить конечные настройки. -3956.14 3961.62 SPEAKER_01 И в любом из этих провайдеров, если он найдет настройку URL, он ее, естественно, затащит. -3961.62 3967.66 SPEAKER_01 Настройка URL может быть с помощью определенного названия, определенного ключа. -3967.66 3972.02 SPEAKER_01 Ключ может называться URLs, может называться ISPnetCoreURLs или .NETURLS. -3972.02 3983.10 SPEAKER_01 А ISPnetCore и .NET по умолчанию отрезаются, как только вы загружаете все ваши конфигурации через Configuration Manager, поэтому они сводятся все все едино к URLs. -3983.10 3996.58 SPEAKER_01 Поэтому очень легко, если вы хотите, допустим, настраивать через переменное окружение, ваш URL, по которому запускается сервачок, вы можете просто выставить переменное средоокружение и после этого запустить приложение. -3996.58 4000.84 SPEAKER_01 И по умолчанию он подхватит переменную, если она названа правильно. -4000.84 4010.40 SPEAKER_01 Дальше, если мы начнем задумываться, что наш сервис принимает в качестве того, что он будет слушать, он принимает URL. -4010.40 4014.42 SPEAKER_01 На самом деле он использует из этого URL не полное подмножество. -4014.42 4023.06 SPEAKER_01 Он может использовать протокол, он может использовать порт, а вот название хоста в этом URL у него довольно ограниченное. -4023.06 4027.18 SPEAKER_01 То есть вы не можете сказать, что я хочу свой сервис запустить на URL Яндекс.Ру, допустим. -4027.18 4031.18 SPEAKER_01 Ну потому что прибавиться к этому интерфейсу вы не сможете. -4031.18 4033.90 SPEAKER_01 Вы сможете прибавиться только то, что у вас есть на локальном хосте. -4033.90 4045.26 SPEAKER_01 И вот чтобы такой диссонанс убрать, недавно было введено новые переменные, новые настройки, которые называются HTTP Port и HTTPS Port. -4045.26 4054.82 SPEAKER_01 То есть вы можете менять, по сути, только порты, но и при изменении этих портов ваш сервер будет слушать на любом IP-адресе. -4054.82 4059.90 SPEAKER_01 То есть он, по сути, прибавится ко всем IP-адресам, и вы будете настраивать только порты. -4059.90 4064.22 SPEAKER_01 Вы можете настроить несколько портиков точно так же, как и с несколькими адресами. -4064.22 4073.58 SPEAKER_01 И начиная с .NET 8, у вас есть переменная SPNet Core HTTP Ports, которую вы можете настраивать. -4073.58 4088.26 SPEAKER_01 Здесь еще нужно сказать, что начиная с .NET 8, по умолчанию во всех официальных .NET Docker images, в Docker images используется эта переменная, и она проставлена в значение 8080. -4088.26 4098.50 SPEAKER_01 Это еще связано с rootless контейнерами, чтобы мы там не бандились на адресах, которые меньше какого-то определенного системного пользователя и так далее. -4098.50 4108.26 SPEAKER_01 В общем, вот эта переменная пригодилась, и каждый из вас, кто использует докер-контейнеры для запуска вашего .NET-приложения, там явно или не явно, эту переменную подкомпотом юзают. -4108.26 4115.54 SPEAKER_01 Еще один способ, как переписать адреса – это, естественно, командная строка. -4115.54 4119.82 SPEAKER_01 Наверное, опять же, тоже, может быть, не для всех очевидный способ. -4119.82 4134.32 SPEAKER_01 Вы можете запустить ваше приложение и в качестве параметра указать --urls, и в этом значении после этого urls-ключа вы можете передать список тех адресов, которые теперь нужно слушать. -4134.32 4136.66 SPEAKER_01 Еще одно место – это upsettings.json. -4136.66 4149.26 SPEAKER_01 В upsettings.json вы прямо в самом ротовом элементе можете указать свойства, которые называются urls, можете указать свойства, которые называются http_ports, которые было выше упомянуто, и оба они потянутся без всяких проблем. -4149.26 4155.50 SPEAKER_01 Дальше у нас есть еще один JSON-файл, который не так очевиден. -4155.50 4156.98 SPEAKER_01 Это launch_settings.json. -4156.98 4161.26 SPEAKER_01 Это специальный файл, который находится в папочке properties. -4161.26 4171.54 SPEAKER_01 И его использует в основном Visual Studio для того, чтобы предоставить вам очень удобный drop-down-лист с профилями запуска. -4171.54 4180.54 SPEAKER_01 Допустим, ваше приложение может быть запущено под IS-экспресса, может быть запущено в виде EXE, может быть запущено под или развернуто под настоящий IS. -4180.54 4184.10 SPEAKER_01 В общем, есть различные профили запуска вашего приложения. -4184.10 4188.26 SPEAKER_01 И вот эти профили запуска, они как раз-таки все и описываются в launch_settings.json, очень полезный файлик. -4188.26 4202.74 SPEAKER_01 И у этого launch_settings.json есть свойство, которое называется application_url, которое вы точно так же можете настроить и которое точно так же скажет, на каком адресе ваше приложение должно слушать входящие запросы. -4202.74 4208.50 SPEAKER_01 Также в launch_settings.json очень удобно настраивать переменное окружение. -4208.50 4230.90 SPEAKER_01 Допустим, если вы хотите, чтобы загружать ваше приложение под какими-нибудь разработческими настройками, с разработческими environment variables или с какими-нибудь тестовыми настройками, переменными среды окружения, вы можете просто запустить два профиля, у каждого из профилей обозначить свои переменные окружения, и в Visual Studio очень удобно переключаться между этими профилями. -4230.90 4233.98 SPEAKER_01 В общем, полезный файлик, про него тоже полезно знать. -4233.98 4246.46 SPEAKER_01 Ну и самый последний, самый хардкорный, самый низкоуровневый, самый оптимизируемый способ – это указать Кестрилу напрямую, откуда ему брать этот адрес. -4246.46 4248.50 SPEAKER_01 То есть вы можете сконфигурировать Кестрил. -4248.50 4252.58 SPEAKER_01 В обычной жизни вам этим, скорее всего, не приходится заниматься, но в этом нет ничего сложного. -4252.58 4260.86 SPEAKER_01 У вышеупомянутого билдера есть свойство webhost и у этого свойства есть метод, который называется ConfigureCastKestril. -4260.86 4280.30 SPEAKER_01 Это свойство принимает Kestril Server Options в качестве аргумента, и у этих опционов есть метод Listen, который принимает кучу аргументов, у него есть куча перегрузок и в частности он может вам получить конкретный адрес, получить конкретный порт и прибандить Кестрил именно туда. -4280.30 4297.62 SPEAKER_01 У этих опций очень много возможностей, там сертификаты туда можно подставлять, какие-нибудь буферы кестриловские, оптимизировать какие-нибудь свои собственные протоколы проставлять вместо TCP/IP, в общем, там черт ногу сломит, но в частности, портики и адреса туда тоже можно записывать. -4297.62 4312.70 SPEAKER_01 Вот такой набор свойств, у каждого из них есть какие-то плюсы и какие-то минусы, у каждого можно захардкодить, каждый можно динамически в рандайме выяснить, какой и какие можно в файлах прописать, наверное, какой ближе к вам, какой ближе к вашей ситуации, такой и стоит использовать. -4312.70 4316.14 SPEAKER_00 Мне приятно, что видите такое разнообразие, действительно. -4316.14 4327.34 SPEAKER_00 Не уверен, что я наизусть, например, помню все их, но обычно просто это либо через параметр командной строки, либо через переменное окружение недостаточно, но удобно, что только всего есть. -4327.34 4360.42 SPEAKER_01 Ну, вот приятная штука, знаешь, что есть еще специальная опция, когда ты можешь поднять свой сервис и настроить прослушивание на любом рандомном порту, на любом свободном открытом, потому что ты не можешь сто процентов гарантировать, что у тебя порт 8080 абсолютно везде настроен, абсолютно везде открыт, и у тебя есть право вообще к нему бандиться, поэтому можно на любом рандомном, например, открывать, на любом рандомном открытом, опять же, открывать и гарантировать тем, что, допустим, твои интеграционные тесты всегда найдут себе свободный порт. -4360.42 4370.34 SPEAKER_01 Ну, в этом случае у тебя, Павел, получается проблема, что как только ты открываешь, грубо говоря, на рандомном портике, ты не знаешь, а на каком портике запустился твое приложение и куда клиенты должны обращаться. -4370.34 4381.98 SPEAKER_01 И вот там, например, есть, можно, опять же, взять сервер фикчу, у нее спросить, где ты слушаешь, но она не всегда есть, например, когда ты хотишься пдисом, ее у тебя нет. -4381.98 4396.46 SPEAKER_01 И вот там уже другие способы работают, например, динамически самому найти свободный порт, динамически его указать уже через конфигурацию, допустим, того же самого кестрала или аппликейшн билдера, и то есть на момент старта программы его, несмотря на то, что он рандомный, его уже знать. -4396.46 4398.66 SPEAKER_01 И когда ты его знаешь, ты уже можешь его куда-то запаблишить. -4398.66 4405.78 SPEAKER_01 В общем, случаи получаются всякие, и как бы на момент запуска самого экзешника, может быть, тебе порт и неизвестен будет. -4405.78 4422.02 SPEAKER_00 Ну, а еще можно, мы, по-моему, один раз такое делали, я не помню, пушится ли он по дефолту, или мы добавляли это сами, запушить его как метрику наружу, сочетать эту метрику и таким образом узнать, ну, типа, метрики есть. -4422.02 4423.02 SPEAKER_01 Ну, это такой очень экзотический способ. -4423.02 4424.02 SPEAKER_01 Как метрика. -4424.02 4425.02 SPEAKER_01 Да, метрика, это сильно. -4425.02 4426.02 SPEAKER_01 Ну, число же число. -4426.02 4427.02 SPEAKER_01 У тебя она всегда будет одинаковая. -4427.02 4428.02 SPEAKER_01 Да? -4428.02 4429.02 SPEAKER_01 Ну, а что такого? -4429.02 4430.02 SPEAKER_00 Действительно, действительно. -4430.02 4432.26 SPEAKER_00 Почему бы и нет? -4432.26 4434.26 SPEAKER_00 Ладно, давай пойдем дальше. -4434.26 4444.10 SPEAKER_00 А дальше у нас, ну, как, тема, мне кажется, последних трех, больше выпусков, это «Дональд Эспаир». -4444.10 4451.10 SPEAKER_01 Если еще считать анонсы, мы там про него начали говорить, да, потом в декабре там что-то тоже было, и тут в январе полностью выпуск про него был. -4451.10 4453.50 SPEAKER_00 Ну, в общем, да, популярный чувак, знаешь. -4453.50 4454.50 SPEAKER_00 Короче, «Эспаир». -4454.50 4455.50 SPEAKER_00 «Дональд Эспаир превью-3». -4455.50 4457.38 SPEAKER_00 Что в нем поменялось? -4457.38 4459.66 SPEAKER_00 В нем поменялось довольно много всего. -4459.66 4462.86 SPEAKER_00 Во-первых, напомню, что что такое вообще в принципе «Эспаир». -4462.86 4479.54 SPEAKER_00 Да, «Эспаир» - это некоторый такой opinionated stack, библиотека набор компонентов от Microsoft, который позволяет вам удобнее разрабатывать локальное приложение, локально разрабатывать клауд-приложение, да, то есть микросервисы, грубо говоря. -4479.54 4483.54 SPEAKER_00 И потом их чуть более удобно деплойть, дальше уже куда вы их там деплойте. -4483.54 4486.86 SPEAKER_00 И концептуально он состоит из нескольких частей. -4486.86 4487.86 SPEAKER_00 Одна из частей - это дэшборд. -4487.86 4498.14 SPEAKER_00 Дэшборд - это, пожалуй, главное, что обновилось в превью-3, потому что они много чего в нем отрефакторили, много чего в нем переделали и в итоге вытащили его в абсолютно отдельный тул. -4498.14 4500.90 SPEAKER_00 Что позволяет дэшборд делать? -4500.90 4507.06 SPEAKER_00 Дэшборд позволяет вам смотреть, что же у вас запущено, какие там контейнеры, процессы, приложения и так далее. -4507.06 4510.46 SPEAKER_00 Позволяет смотреть логи, позволяет смотреть метрики, позволяет смотреть трейсы. -4510.46 4528.38 SPEAKER_00 Короче, красиво делать практически полное обзервабилити, если не сказать полной обзервабилити вашего приложения, причем все это локально и в виде одного как бы, по сути одного проектика, одного как бы тула, а не трех-четырех контейнеров, которые должны работать там вместе. -4528.38 4529.82 SPEAKER_00 Графана, Прометеус и все остальное. -4529.82 4541.02 SPEAKER_01 А скажи, вот этот дэшборд, он как запускается, отдельный контейнер или я могу его в end-process со своим приложением запустить, если мне не нужны контейнеры, у меня есть один всего-навсего экзешничек и я хочу его тогда встроить? -4541.02 4545.54 SPEAKER_00 Пока вроде как в экзешничек я не видел, чтобы встраивали. -4545.54 4564.30 SPEAKER_00 Пока вроде как отдельно, но поскольку это первый превью, в котором это вышло, ну в смысле превью третий, но это первый раз, когда они такое сделали, то сейчас начались эксперименты, в комьюнити видно по всяким разным твитам и прочему, что прикольно, работает, так что посмотрим, может и в end-process занесут как-нибудь. -4564.30 4573.94 SPEAKER_01 Ну да, мне кажется, для таких небольших приложений, которые состоят из одного экзешника, которые может быть даже не очень контейнеры используют, тоже был бы последний дэшборд, такой эмбарик, если его сделают. -4573.94 4577.90 SPEAKER_00 Да, сейчас пока это просто, как они пишут, это independent executable. -4577.90 4578.90 SPEAKER_00 Ну, посмотрим. -4578.90 4603.50 SPEAKER_00 Много чего поменяли в дэшборде на тему локализации и аксессибилити, улучшили ресурс детейлс, более красиво, чтобы все показывалось, добавили улучшений в телеметрию, какие-то гистограммы, метрик, спаны, венты, короче, много чего такого, пользуйтесь, посмотрите, будет выглядеть лучше. -4603.50 4604.50 SPEAKER_00 По компонентам. -4604.50 4632.10 SPEAKER_00 Это вторая большая часть Aspire, это компоненты, которые позволяют легко добавить в ваш продукт некоторую стандартную функциональность, тоже хорошо сконфигурированную, то есть, например, добавить хорошо сконфигурированное что-то по эклиен, со всякими поли, ну короче, ретраями, резилиенсом, вот этим всем, или там добавить стандартные настройки для RADIS, или еще для чего-нибудь. -4632.10 4640.42 SPEAKER_00 Добилось несколько новых компонентов, во-первых, ну куда же без Azure AI Open AI Component, никуда не делась. -4640.42 4670.22 SPEAKER_00 Второй компонент это Kafka, причем не только, как это сказать, не только подключает возможность коннекта Kafka в ваше приложение, но если вам нужно для локальной отладки, вы теперь можете в Aspire конфигурации в C# написать что-нибудь типа with Kafka, я не помню как там, пишется точно, и у вас будет локально подниматься преконфигурированная Kafka для вашей локальной разработки. -4670.22 4683.54 SPEAKER_00 Ну, то есть, понятно, что это просто поднимается контейнер с Kafka, но вот теперь достаточно просто написать в одном месте C# кода with Kafka и все, у вас есть готовый сервер Kafka, когда у вас приложение работает. -4683.54 4712.70 SPEAKER_00 Дальше, соответственно, появились интеграции для работы через Entity Framework с Oracle и с MySQL, можно теперь сделать с Cosmos DB то же самое, как я только что говорил, с Kafka, то есть при необходимости, у Cosmos DB есть локальный эмулятор, вы можете поднять, не обязательно ходить в Azure для этого, можно поднять локальную копию Cosmos DB, точнее локальную базу данных, которая эмулирует поведение Cosmos DB, вот теперь есть компонент, который позволяет это легко сделать. -4712.70 4785.18 SPEAKER_00 В Redis завезли логирование, точнее не в сам Redis, а в библиотеку доступа от Second Exchange, завезли логирование, и поскольку все это еще в превью, то у нас есть ряд breaking-чинджей, ну например поменяли API, то, что раньше называлось withServiceBinding, теперь называется withEntryPoint, если вы обновляете на третью превью, у вас перестает все собираться, потому что поменялись названия методов, такой нормальный breaking-чиндж, ну превью, что вы хотели, зато для контейнеров теперь можно указывать специальную функцию withEntryPoint и таким образом просто прямо указывать, что запустить внутри контейнера, когда он поднимется, дальше из полезняшек таких добавилось, например у вас была компонента Postgres, она позволяла настроить вам ConnectedPostgres, прокидывала там всякие connection-стринги к базе, вот это все, теперь туда можно еще дописать метод расширения withPgoadmin, после чего у вас поднимется дополнительный контейнер с Pgoadmin рядышком, и такая же штука для Redis Commander, это веб-менеджмент для Redis, короче они делали максимально удобно, максимально односрочно, так скажем, дефолтные конфигурации для самых популярных тулов. -4785.18 4876.98 SPEAKER_00 Внезапно в DotNet Espire Preview 3 добавили поддержку орлинсов, вот уж чего-чего, не думал, что так быстро сделают, но видимо кому-то надо было, очень надо, поэтому добавили, и добавили три новых проекта, примеров проектов, прямо в репозитории DotNet Espire лежит, три новых проекта, во-первых, называется Espire with JavaScript, это проект, который показывает как работать с Espire, если у вас есть DotNet Espire Application плюс дополнительно еще Node.js приложение зачем-то, плюс какой-нибудь SPA frontend типа Angular, React или Vue, как это все вместе сдружить и все это работает в Espire, дальше есть проект под названием ClientAppsIntegration, которое показывает как подружить DotNet Espire с WinForm или WPF и собирать с них аналогии, трейдсы и все такое, ну и последний проект это PersistentVolumeMount, это проблематика следующая, Espire вот этот вот дэшборд и сервер, который собирает все менеджеры, логи и так далее, он все это делает в памяти, т.е. как только вы говорите закончить там отладку или еще что-нибудь, хост DotNet Espire, дэшборда опускается и он теряет все, что у него было, т.е. если вам после этого захочется посмотреть логи прошлого запуска, вы уже не сможете, но есть возможность подключить нормальную базу данных либо файловую систему для того, чтобы хранить все по-человечески, вот этот пример показывает как это сделать. -4876.98 4904.14 SPEAKER_00 Ну и последнее изменение для превью 3, это добавили два новых шаблончика, т.е. до превью 3, что вы могли сделать, вы могли создать новый проект с поддержкой Espire, а вот если вам нужно было добавить поддержку Espire к существующему проекту, то вам откуда-то нужно было взять вот эти два шаблонных проекта, UpHost и ServiceDefault, в которых собственно и описывается вся инфраструктура и настройки. -4904.14 4919.18 SPEAKER_00 Вот теперь есть два шаблончика, которые позволяют в уже готовом солюшене написать DotNet New Espire UpHost или DotNet New Espire ServiceDefault и вам к существующему солюшену добавится два вот этих вот новых нужных для работы Espire проекта, т.е. -4919.18 4922.42 SPEAKER_00 ServiceDefault не то чтобы сильно нужен, но по крайней мере обычно есть. -4922.42 4935.66 SPEAKER_00 Вот такие дела, Espire живет, развивается, смотрим что будет дальше с Dashboard, насколько комьюнити его полюбит, примет и будет использовать, может быть даже отдельно от DotNet будем посмотреть. -4935.66 4936.66 SPEAKER_01 Пока не видел. -4936.66 4960.82 SPEAKER_01 Слушай, а нету ли примеров с тестами, потому что интересная тема, у нас же есть отдельный контейнер тестов, грубо говоря, а здесь кажется, что эта штука примерно их покрывает, потому что если мы под разработческим окружением можем одной кнопкой запустить все наши кавки, как ты сказал, Orleans, то мы наверняка же захотим это делать и в интеграционных тестах, вот нет ли каких-то примеров, как она дружит с интеграционными тестами? -4960.82 4965.30 SPEAKER_00 Пока я не видел, пока это чисто девелоперский тулинг из того, что я видел. -4965.30 4975.46 SPEAKER_01 Ну, то есть, понимаешь, у нас теперь будет как бы мы эту кавку и Orleans будем настраивать в девелоперском тулинге, а потом то же самое будем идти и делать в тест-контейнерах. -4975.46 4976.82 SPEAKER_01 Звучит как довольно странно. -4976.82 4986.34 SPEAKER_00 Я согласен, и скорее всего надо внимательно почитать репозитории Espire, может быть там что-то про это есть, я просто настолько внимательно и не изучал их в части. -4986.34 5000.50 SPEAKER_00 Можно посмотреть к следующему разу, если что-то нароется, я периодически туда заглядываю, ради того, чтобы понять, есть ли что-то новенькое, а может и превью какую-нибудь выпустят в следующем выпуску, или когда выпустят следующий превью, я постараюсь не забыть посмотреть на эту тему. -5000.50 5001.50 SPEAKER_01 Давай. -5001.50 5003.50 SPEAKER_01 Не дадим вам отдохнуть от Espire ни одного выпуска, -5003.50 5004.50 SPEAKER_00 да? -5004.50 5008.02 SPEAKER_00 Ну, я надеюсь, что они не успеют за 2 недели выпустить следующий превью. -5008.02 5015.10 SPEAKER_01 Ладно, погнали, времени осталось мало, а тут еще пару интересных статей, которые хотелось бы вбросить. -5015.10 5021.78 SPEAKER_01 Марк Симон, давно мы не обращались к нашему гуру, хотелось бы повысить градус гиковости. -5021.78 5029.38 SPEAKER_01 Давайте посмотрим, у него есть хорошая статья вышла, которая называется «Категории ошибок и ошибки категорий». -5029.38 5041.78 SPEAKER_01 Казалось бы, да, что сейчас мы снова про категории, но нет, здесь все довольно более приземисто, здесь автор рассуждает о том, на какие типы и виды он делает где-то ошибки, каким образом он их обрабатывает и как к этому вопросу подходит. -5041.78 5058.58 SPEAKER_01 Вообще вопрос обработки ошибок, он очень нетривиальный, несмотря на его очевидность и, казалось бы, продуманность уже не одно десятилетие, многие языки все еще перезабретают какие-то подходы к ошибкам, как их обрабатывать, что надо обрабатывать, что не надо обрабатывать и прочие-прочие эти вещи. -5058.58 5065.38 SPEAKER_01 Поэтому тема глобальная, тема большая, ну, так поверхностно немножко про ней пошелся Марк. -5065.38 5071.42 SPEAKER_01 Прежде всего нужно осознать, что в любом программном приложении есть ошибки или будут ошибки. -5071.42 5086.10 SPEAKER_01 Вы никогда не будете застрахованы от всего, начинать можно с обычного user input, если у вас есть user input, то пользователь вам может ввести невалидные данные, которые ваше приложение не способно, не хочет и не будет обрабатывать. -5086.10 5119.10 SPEAKER_01 К вам могут попасть какие-то поврежденные данные, какие-то поврежденные конфиги, которые у вас уже есть, у вас может случиться проблема с сетью, у вас может быть наведенка от рентгеновских лучей, у вас может быть какие-то параллельные вычисления, которые дадут вам risk condition или concurrent exception или еще что-то, ну и в крайнем случае в вашем коде всегда могут быть баги, то есть мы разрабатываем все наши приложения всегда оперируя тем, что вокруг нас есть ошибки того или иного уровня сложности, критичности и так далее. -5119.10 5120.10 SPEAKER_01 Это уже не суть важно. -5120.10 5125.94 SPEAKER_01 Важно то, что наше приложение не всегда работает так, как мы это задумывали в идеальном success path. -5125.94 5132.42 SPEAKER_01 И по версии Марка ошибки можно разделить на начальном этапе на три категории. -5132.42 5145.82 SPEAKER_01 Во-первых, это предсказуемые ошибки, которые мы можем обработать, предсказуемые ошибки, которые мы не можем обработать и, соответственно, непредсказуемые ошибки, которые мы не можем никак предсказать. -5145.82 5147.22 SPEAKER_01 Давайте рассмотрим их поподробнее. -5147.22 5152.58 SPEAKER_01 Ну прежде всего большинство ошибок, которые есть в наших приложениях, мы вполне способны предсказать. -5152.58 5156.54 SPEAKER_01 Например, к ним относится уже вышеупомянутый ввод пользователя. -5156.54 5165.30 SPEAKER_01 Когда пользователь вводит какие-то данные в ваше приложение, вы на сто процентов можете быть уверены, что рано или поздно он в этих данных ошибется. -5165.30 5169.34 SPEAKER_01 Поэтому там существует стандартный процесс валидации пользовательских данных. -5169.34 5171.06 SPEAKER_01 В общем, от этого вы никуда не денетесь. -5171.06 5174.10 SPEAKER_01 И это то, что мы можем предсказать на сто процентов. -5174.10 5177.66 SPEAKER_01 То есть, это тот слой, который обязательно должен присутствовать в вашем приложении. -5177.66 5182.46 SPEAKER_01 Немножко сложнее обстоит дело с получением данных из другой системы. -5182.46 5188.94 SPEAKER_01 То есть, когда не пользователь вам вводит эти данные, а другая система вводит данные, здесь есть тонкости, от которых мы немножко позже посмотрим. -5188.94 5200.02 SPEAKER_01 То есть, для того, чтобы избежать ошибок пользовательского ввода, вам необходимо настроить свой слой валидации и каким-то образом проинформировать пользователя о плохих данных, которые он вам ввел. -5200.02 5206.54 SPEAKER_01 Выдать сообщение об ошибке, написать в лог, написать в консольку или каким-то другим образом. -5206.54 5213.66 SPEAKER_01 Дальше следующая категория – это тоже предсказуемые ошибки, но немножко более сложные. -5213.66 5220.34 SPEAKER_01 Например, ваше приложение, скорее всего, может зависеть от базы данных. -5220.34 5222.30 SPEAKER_01 А эта база данных может быть недоступна. -5222.30 5225.18 SPEAKER_01 Может покарабкаться, может отвалиться винт, может отвалиться сеть. -5225.18 5229.58 SPEAKER_01 И вообще у вас может отвалиться сеть, например, с другими сервисами, которые необходимы вам для работы. -5229.58 5234.54 SPEAKER_01 Например, ваше приложение могли плохо сконфигурировать. -5234.54 5236.82 SPEAKER_01 Например, задать неправильный connection string. -5236.82 5242.74 SPEAKER_01 Отчего оно, естественно, работать не сможет, с базой данной приконектиться не сможет и вообще основные функции выполнять не сможет. -5242.74 5244.98 SPEAKER_01 У вас, может быть, банально кончится место на диске. -5244.98 5250.30 SPEAKER_01 Может быть, не знаю, сервер закрашивался из-за какой-то ошибки. -5250.30 5253.30 SPEAKER_01 Может закрашивалась какая-то из ваших зависимостей, которая вам нужна. -5253.30 5258.70 SPEAKER_01 В общем, очень много существует инфраструктурных, технических проблем, от которых вы абсолютно никак не застрахованы. -5258.70 5265.86 SPEAKER_01 Вы должны понять, что любая сеть падает, любая датабаза сломается, любой диск заполняется. -5265.86 5270.58 SPEAKER_01 Эти штуки можно решить, можно попытаться решить, давайте так. -5270.58 5286.94 SPEAKER_01 Можно сделать ретрай, можно сделать какие-нибудь дополнительные приседания, попробовать через какое-то время уменьшить количество запросов, circle bracket поставить, можно еще что-то сделать. -5286.94 5290.94 SPEAKER_01 Но в общем случае, единственное, что вы сможете сделать, это залогировать проблему. -5290.94 5295.26 SPEAKER_01 Ну и не факт, что вообще ваш лог сможет куда-то записаться, потому что все зависит от проблем. -5295.26 5313.66 SPEAKER_01 И надо понимать, что если, допустим, у вас ваше приложение зависит от базы данных, и база данных почему-то или повреждена, или не отвечает, или мы не можем получить правильный connection string к ней, то ваше приложение, по сути, становится неработоспособным. -5313.66 5317.46 SPEAKER_01 Это значит, что вы не можете обработать эту ошибку. -5317.46 5324.32 SPEAKER_01 То есть, когда мы раньше в эту категорию спускались, мы ее рассматривали как предсказуемые ошибки. -5324.32 5327.98 SPEAKER_01 И вот это те предсказуемые ошибки, которые вы обработать не в состоянии. -5327.98 5339.26 SPEAKER_01 Да, вы можете пытаться хоть целый день ретраить на базу данных, но вы должны понимать, что рано или поздно лимит ретраива у вас закончится, и все равно ваше приложение не способно будет работать полноценно. -5339.26 5348.82 SPEAKER_01 Поэтому у нас появляется вот такая отдельная категория, что ошибки, которые мы теоретически можем предсказать, да, все рано или поздно ломается, но сделать мы с этим ничего не сможем. -5348.82 5354.50 SPEAKER_01 Также нужно понимать, что часто ошибки бывают контекстно зависимыми. -5354.50 5362.14 SPEAKER_01 Ну, например, рассмотрим наш предыдущий сценарий, когда у нас есть пользователь, который вводит невалидные данные. -5362.14 5366.42 SPEAKER_01 Когда он вводит невалидные данные, мы ему выдаем сообщение об ошибке, и здесь все хорошо. -5366.42 5370.62 SPEAKER_01 Теперь возвращаемся к примеру, когда эти невалидные данные к нам присылает какой-то другой сервис. -5370.62 5376.90 SPEAKER_01 И этот другой сервис, допустим, с ним нет какого-то канала связи, вы не можете ему там сказать просто exception и все. -5376.90 5379.90 SPEAKER_01 Он вам просто загружает какой-то файл и говорит «обрабатывай». -5379.90 5380.90 SPEAKER_01 И никого не волнует этот файл. -5380.90 5383.22 SPEAKER_01 Может быть с плохими данными, с плохими, с еще какими-то. -5383.22 5387.54 SPEAKER_01 Что можно сделать в случае, если вдруг у вас там есть в этом файле невалидные данные? -5387.54 5395.90 SPEAKER_01 Ну, во-первых, конечно, можно всегда бросить ошибку, отказаться отрабатывать этот файл, послать bad request, сделать reject. -5395.90 5399.54 SPEAKER_01 То есть, в принципе, как вариант тоже может быть. -5399.54 5404.98 SPEAKER_01 Можно попытаться найти из этого файла только валидные какие-то значения и обработать только их. -5404.98 5415.22 SPEAKER_01 Можно послать какое-то асинхронное сообщение, что типа «я не смог обработать этот файл», приложить файл, объяснить почему, и типа попытайтесь снова через какое-то время или еще что-то с этим файлом сделать. -5415.22 5417.14 SPEAKER_01 В общем, как-то оповестить админов. -5417.14 5433.82 SPEAKER_01 Все это нас приводит к тому выводу, что если у нас есть проверка пользовательского ввода, то есть, допустим, обычная валидация инпута, то то, как мы будем реагировать на эту валидацию инпута, вполне контекстно зависимо. -5433.82 5440.26 SPEAKER_01 И тот сам процессор, который валидирует этот файл, может быть, даже не знает, каким образом это правильно нужно отвалидировать. -5440.26 5445.62 SPEAKER_01 Знает только тот, кто этот файл в этот процессор отдал. -5445.62 5449.06 SPEAKER_01 То есть, некий враппер сверху, который может принять решение. -5449.06 5457.38 SPEAKER_01 Есть у него текущий интерактивный пользователь или у него просто какой-нибудь машин-то машин-коммуникация и он как-то может другой машине сообщить о проблемах. -5457.38 5471.58 SPEAKER_01 Нужно также понимать, что обработка ошибок всегда связана с неким трейдовом, то есть, у вас всегда есть какие-то плюсы, какие-то минусы и вы всегда должны уметь чем-то жертвовать. -5471.58 5484.70 SPEAKER_01 Возвращаясь к примеру с базы данных, когда мы получаем недоступную базу данных, то вы можете сколько угодно ретраиться, но рано или поздно вы придёте к осознанию, что вы не можете ничего с этим сделать. -5484.70 5492.38 SPEAKER_01 И в обычном банальном случае вы можете отказаться от обработки этой операции, от обработки команды. -5492.38 5496.50 SPEAKER_01 Это как бы 100% скорее всего нашей повседневной бизнес-задачи. -5496.50 5508.90 SPEAKER_01 Когда к нам приходит какой-то реквест на создание пользователя, мы идём в базу, она недоступна, ну мы просто падаем и всё с криками, ай-яй-яй, не могу создать пользователя, программа наша выполнила недопустимую ошибку и будет открыта, и будет закрыта. -5508.90 5517.42 SPEAKER_01 Это самый распространённый кейс, но подумайте, что будет, если вдруг вы пишете программу, которая обрабатывает какие-нибудь медицинские данные, от которых зависит жизнь человека. -5517.42 5529.50 SPEAKER_01 Или если вы запускаете какой-нибудь зонд в космос, где у вас нет возможности просто-напросто поднять ручки и сказать "всё, нишмогла", там вам нужно как-то мучиться, что-то делать. -5529.50 5531.22 SPEAKER_01 И мучиться можно на разных уровнях. -5531.22 5539.34 SPEAKER_01 Можно, как я уже говорил, напрячь сисадминов, которые поставят вам какой-нибудь файловер к базе данных, чтобы она была не одна, чтобы она была более отказоустойчивая. -5539.34 5549.46 SPEAKER_01 Можно запаять к вам в ящик несколько сетевых карт, чтобы если одна отвалилась, у нас всегда был резервный канал связи, мы могли пойти на другую карту. -5549.46 5557.26 SPEAKER_01 Но всё это более-менее от нас не зависит, мы можем это бросить как-то на админов, но как разработчики, грубо говоря, этот путь нам не интересен. -5557.26 5565.10 SPEAKER_01 Нам интересен другой путь, мы на это можем повлиять с точки зрения архитектуры программного приложения. -5565.10 5566.10 SPEAKER_01 Каким образом? -5566.10 5580.90 SPEAKER_01 Ну, например, если у нас недоступна база данных, но при этом доступен, допустим, какой-нибудь асинхронный обмен событиями, там Kafka или Rabbit, мы вполне можем послать себе какое-нибудь асинхронное сообщение, допустим, попытаясь сделать ту же операцию через какой-то промежуток времени. -5580.90 5592.14 SPEAKER_01 Если эти сообщения ещё отправляются через какую-нибудь дюрибл очередь, то есть очередь, которая может сохраниться себе на диск и гарантировать нам какую-то доставку, то вообще прекрасно. -5592.14 5597.26 SPEAKER_01 Могут быть какие-то другие ситуации, которые мы можем каким-то образом по-другому обрабатывать. -5597.26 5614.62 SPEAKER_01 Но, например, если недоступна сеть, вам нужно срочно отправить логи, а недоступна сеть, вы можете вполне сделать у себя локально на диске какой-то буфер с этими логами и как только сеть поднимется, вы этот буфер можете, например, запаблишить куда-нибудь в ваше официальное хранилище. -5614.62 5620.34 SPEAKER_01 То есть можно предусматривать на уровне кода, на уровне программистов вот обход вот таких вот ситуаций. -5620.34 5625.34 SPEAKER_01 Но, опять же, нужно понимать, что всему есть предел. -5625.34 5629.22 SPEAKER_01 Вы не можете бесконечно буферировать в диск, потому что диск сломается. -5629.22 5637.58 SPEAKER_01 Если у вас отказала база данных, то, скорее всего, можете отказать и шинка, в которую вы можете забрасывать сообщения. -5637.58 5649.66 SPEAKER_01 Таким образом, у нас все-таки ситуация, когда у нас есть предсказуемые ошибки, которые вы якобы могли бы обработать, мы можем уменьшить вот этот эффект, который мы могли бы обработать. -5649.66 5655.74 SPEAKER_01 Мы можем и на локальный диск писать, и в другие источники записывать, и как-то это все кэшировать, и как-то повторять. -5655.74 5666.06 SPEAKER_01 Но рано или поздно мы понимаем, что все возможные ситуации предусмотреть невозможно, и постепенно эта категория все равно сваливается в категорию ошибок, которая называется предсказуемые ошибки, которые мы не можем отработать. -5666.06 5679.50 SPEAKER_01 Поэтому нужно ли загоняться вот этими всеми оптимизациями, которые мы пытаемся сделать с ошибками, которые мы якобы можем предсказать, но не можем обработать? -5679.50 5686.74 SPEAKER_01 Нужно ли все-таки ресайленты делать, буферы делать, ретраи делать каждый раз на любом вашем приложении? -5686.74 5687.74 SPEAKER_01 Ответ по дефолту нет. -5687.74 5697.86 SPEAKER_01 Это все очень большое усложнение, которое дается очень большими силами разработчиков, а самое главное, оно ввозит в ваше приложение дополнительную сложность. -5697.86 5706.02 SPEAKER_01 Вся эта сложность, это прямое следствие этой сложности будут дополнительные баги, какие-то проблемы по эксплуатации, какие-то проблемы с метриками, еще чего-то. -5706.02 5712.90 SPEAKER_01 В общем, все это очень-очень сложно, поэтому зря, просто так, ради интереса, по дефолту в эту сложность вписываться не надо. -5712.90 5717.14 SPEAKER_01 И опять же, вся эта сложность, она не дает вам никаких гарантий. -5717.14 5724.74 SPEAKER_01 У вас все равно диск закончится, ретраи кончатся, все базы данных и очереди отвалятся, т.е. у вас все равно гарантий никаких нет. -5724.74 5726.66 SPEAKER_01 Поэтому здесь вам нужно взвешивать. -5726.66 5730.30 SPEAKER_01 Опять же, если у вас критикал-система, то да, стараемся изо всех сил. -5730.30 5734.78 SPEAKER_01 Если что-то средненькое, ну, пробуем какие-то базовые ретраи того же самого поля запустить. -5734.78 5741.02 SPEAKER_01 Если пользователь прекрасно переживет bad-request, то просто бросаем им ошибку и не загоняемся ни о чем. -5741.02 5744.66 SPEAKER_01 Это будет просто, красиво, понятно, а самое главное – поддерживаемо. -5744.66 5750.06 SPEAKER_01 Есть еще одна интересная категория ошибок, которая называется баги, они же инциденты. -5750.06 5755.18 SPEAKER_01 Третья категория, к которой относятся категории невозможно предсказать. -5755.18 5762.66 SPEAKER_01 Ну, т.е. мы все можем предсказать, что баги у нас, конечно, есть, но мы абсолютно не понимаем ни в каком месте они выстрелят, ни как программа будет после этого себя вести. -5762.66 5766.22 SPEAKER_01 Поэтому эта категория относится невозможно предсказать. -5766.22 5768.18 SPEAKER_01 Но мы точно знаем, что они будут. -5768.18 5777.34 SPEAKER_01 И если у вас был баг один раз, допустим, он стрельнул и исчез, то это прямое следствие того, что он может стрельнуть и второй раз, поэтому это очень опасная штука. -5777.34 5786.02 SPEAKER_01 И в этот момент мы можем для себя решить, мы будем этот баг искать и фиксить или есть еще другой вариант, можно не искать и не фиксить. -5786.02 5797.50 SPEAKER_01 Если мы не можем это сделать, мы можем вполне себе сами честно ответить, что этот баг, который мы фиксить не будем, он не так уж сильно влияет на наше приложение. -5797.50 5801.06 SPEAKER_01 Мы его можем вполне описать, сказать, что оно происходит раз в год и в принципе забить. -5801.06 5807.26 SPEAKER_01 Когда мы говорим про моделирование ошибок, у нас есть очень много подходов. -5807.26 5816.38 SPEAKER_01 К сожалению, человечество до сих пор не придумало идеальные подходы, которые бы нам позволяли хорошо работать со всеми вот этими ошибками, которые здесь были описаны. -5816.38 5821.18 SPEAKER_01 Но были придуманы некие вспомогательные методы. -5821.18 5826.74 SPEAKER_01 Например, самая прекрасная вещь, которую придумала человечество для того, чтобы бороться с ошибками, это стронг тайпинг. -5826.74 5837.98 SPEAKER_01 Именно поэтому языки с сильной статической типизацией очень сильно выиграют языку с динамической типизацией или без типизации, или со слабой типизацией, в общем, со всем этим шлаком в виде джаваскрипта. -5837.98 5846.92 SPEAKER_01 Потому что то, что джаваскриптеры, питанисты и прочие люди должны выявлять в тестах, у нас делает компилятор на уровне компиляции. -5846.92 5854.86 SPEAKER_01 Большинство из тех проблем, которые случаются в рантайме в этих языках, в строго типизированных языках, мы отлавливаем в компайл тайме. -5854.86 5863.30 SPEAKER_01 У нас также есть на основании строгих типов еще их дополнительные фишки, дополнительные плюшки. -5863.30 5873.06 SPEAKER_01 Прежде всего, это null-reference-types, это просто мега-фича, мега-взрывная штука и ее можно прям сравнить, как будто у вас не было раньше типа, а вы типы добавились. -5873.06 5891.38 SPEAKER_01 Потому что null-reference-types дают вам огромное количество прекрасных возможностей избежания самой популярной в мире проблемы, это null-reference-exception, если вдруг вы почему-то до сих пор уже не пользуетесь все еще null-reference-types, то обязательно изучите вопрос, оно того стоит, оно спасает просто мега-сильно. -5891.38 5912.02 SPEAKER_01 Также, благодаря тому, что у нас есть нормальные строгие типы, у нас полно линтеров и анализаторов, которые не просто там какие-то буквы анализируют, а могут нормально построить семантическое, синтаксическое дерево, пройтись, проанализировать, посмотреть свои типы и в памяти даже проинтерпретировать вам некоторый код для того, чтобы прям найти какие-нибудь определенные, например, векторы атаки. -5912.02 5914.26 SPEAKER_01 Этим часто грешат там security-сканеры уязвимостей. -5914.26 5928.30 SPEAKER_01 В общем, линтеры, анализаторы, NRT, strong-types, эти все инструменты как раз были призваны нам для того, чтобы уменьшить то количество ошибок, которые у нас возможно будут порождаться в рантайме и свести это на самый эффективный уровень – на билд-тайм. -5928.30 5939.86 SPEAKER_01 Другие способы, как работать с ошибками – это введение специальных явных результатов, которые нам говорят о том, что данный метод может вернуть ошибку. -5939.86 5946.46 SPEAKER_01 Это наверняка всем известный вам result-type, он же either в других методах, в других языках или maybe. -5946.46 5950.70 SPEAKER_01 То есть это обычно тип, который может принимать два значения. -5950.70 5956.66 SPEAKER_01 Или он успешно выполнился, и вам успешный результат, или не успешно выполнился, и какое-то описание ошибки возвращает. -5956.66 5960.02 SPEAKER_01 В общем, этот подход тоже очень популярен в различных языках. -5960.02 5969.22 SPEAKER_01 Ну и у нас еще есть методология, то есть у нас есть TDD, который позволяет нам покрывать тестами максимальное количество задач. -5969.22 5971.22 SPEAKER_01 То есть это уже ловля на уровне рантайма. -5971.22 5977.26 SPEAKER_01 У нас есть код-ревью, который тоже помогает уменьшить количество проблем на каких-то ранних этапах. -5977.26 6002.98 SPEAKER_01 В общем, человечество придумало очень много всего, и включая инструментарии, включая методологии, включая подходы и чуть ли не целые концепции в языках программирования, которые отталкивались от ошибок, и как вести себя с ошибками, и как, например, перезапускать проблемы с ошибками, как это сделано, допустим, в АКИ, когда у нее есть целая стратегия, когда мы из ошибок перезапускаем целый кластер акторов. -6002.98 6012.70 SPEAKER_01 В общем, ошибки драйвят очень сильно нашу систему, и пока человечество не выдумало что-то такое хорошее, где можно описать красиво все и решить все эти проблемы. -6012.70 6019.94 SPEAKER_01 Поэтому мы пока остаемся на уровне методологии, на уровне договоренности, на уровне концепции, а также строгих типов и кучи анализаторов, которые нам в этом помогают. -6019.94 6026.90 SPEAKER_00 Ну, вообще, с одной стороны, звучит все это масштабно, классификация, все такое. -6026.90 6030.78 SPEAKER_00 С другой стороны, это не из разряда нормально делать нормально будет. -6030.78 6038.38 SPEAKER_00 Ну, то есть, подходи, так сказать, с умом к тому, насколько критична твоя система, и сообразно планируй. -6038.38 6043.82 SPEAKER_00 Это же все не просто разработчик решает, они сделают для меня тут ретрай. -6043.82 6054.94 SPEAKER_00 Это же как-то все, не знаю, должно проговариваться на каком-то плюс-минус критикурном уровне, пусть даже с самим разработчиком, но с каким-то более опытным разработчиком. -6054.94 6055.94 SPEAKER_01 Не знаю. -6055.94 6056.94 SPEAKER_01 Проговариваться – это одно. -6056.94 6063.94 SPEAKER_01 Но так как мы в нашем повседневном коде сталкиваемся с миллионом мест, где может случиться ошибка, все это проговорить невозможно. -6063.94 6071.42 SPEAKER_01 Поэтому у тебя должен быть очень высокий уровень сознательности, а уровень сознательности подразумевает под собой какой-то практический опыт. -6071.42 6082.34 SPEAKER_01 Пока ты не натолкнешься на то, что база данных у тебя может отсутствовать, что тебе connection string могут неправильно записать, пока ты на практике вот это не испытаешь, скорее всего, большинство людей об этом даже не задумываются. -6082.34 6090.94 SPEAKER_00 Ну, или connection string есть, но у тебя мастер базы данных умерла, а реплика живет в рядомом режиме, и у тебя половина только с программой работает. -6090.94 6094.46 SPEAKER_00 Типа, гетпоинты работают, а посты не работают. -6094.46 6099.22 SPEAKER_01 И приложение может быть устроено так, что при первой попытке записи у тебя оно просто рушится. -6099.22 6105.86 SPEAKER_01 Можно было поставить его, чтобы только начание работало, но ты это как-то не предусмотрел, и у тебя на записи оно просто все падает. -6105.86 6107.30 SPEAKER_01 Например, такое тоже может быть. -6107.30 6128.02 SPEAKER_00 Ну, в общем, подходите с умом, думайте о том, когда вы пишете код, что здесь может пойти не так, и если вам кажется, что что-то может пойти не так, и либо сами принимаете решение, как бы с этим бороться, либо сначала посоветуйтесь с кем-то еще в проекте, нужно с этим бороться, или пусть падает, потому что по факту вам окей. -6128.02 6135.74 SPEAKER_00 Хорошо, давай попробуем на сегодня успеть последнюю темку, наверное, быстренько пробежаться. -6135.74 6136.74 SPEAKER_01 Ну, давай. -6136.74 6140.22 SPEAKER_01 Ну, я думаю, что шансов мало. -6140.22 6141.22 SPEAKER_01 Ладно. -6141.22 6142.22 SPEAKER_01 Погнали. -6142.22 6152.22 SPEAKER_01 Топ 10 визуал студийных фич, которые были выпущены в 2023 году, и которые понравились товарищу Джеймс Монтемангону. -6152.22 6163.02 SPEAKER_01 Этот товарищ довольно знаменит, особенно в средах мобайл-разработчиков, очень много библиотек написал, очень много статей написал, в общем, товарищ просто золото. -6163.02 6176.22 SPEAKER_01 К сожалению, в наших статьях, в наших подкастах он звучит редко, потому что по профилю немножко не подходит, но в основном человек очень крутой, поэтому нет никаких резонов ему не верить. -6176.22 6184.26 SPEAKER_01 Давайте посмотрим, что он для себя открыл в 2023 году, даже не открыл, наверное, посчитал самыми хорошими инструментами, которые появились в визуал студии. -6184.26 6194.06 SPEAKER_01 Прежде всего, это DevTunnels, туннели для разработчиков, которые позволяют вам, ваш локальный хост, выставить голой попой, например, в интернет. -6194.06 6209.62 SPEAKER_01 То есть, данный сервис помогает вам сформировать специальный урл, и если кто-то зайдет по этому урлу, любой человек в интернете зайдет по этому урлу, он будет перенаправлен на ваш локальный сервак, на ваш локальный порт, который, допустим, у нас сейчас под студией запущен. -6209.62 6215.30 SPEAKER_01 И вы, например, можете этот запрос отдебажить или что-то показать, например, вашу презентацию, или еще что-то. -6215.30 6218.30 SPEAKER_01 Это просто мега-фича для мобильных разработчиков. -6218.30 6228.42 SPEAKER_01 Когда у вас есть миллион девайсов, эти все миллионы девайсов никаким образом не подключены к вашей, допустим, корпоративной сети, у них нормально, если есть интернет. -6228.42 6244.70 SPEAKER_01 И вот вы этим девайсам даете ссылочку, и эти девайсы заходят на ваш сервер, который сейчас запущен у вас под отладчиком, и делают там всякое, вызывают запросы, проходит авторизация, вы это все можете видеть, дебажить, смотреть, как бы снимать дампы, в общем, золотая штука. -6244.70 6262.06 SPEAKER_01 А также, если вы просто хотите, например, показать в вашем веб-сайте, который вы недавно разработали какому-то, не корпоративному, а наоборот, внешнему клиенту, вы точно так же можете дать им урлик вот этот и не паблишить этот сайтик никуда, запустить его под Visual Studio, и по этому урлу ваш внешний потребитель все это увидит, все это посмотрит. -6262.06 6265.30 SPEAKER_01 Короче, прекрасная штука, которая для некоторых сфер просто критикал необходима. -6265.30 6276.98 SPEAKER_01 Дальше он отмечает вторую фичу, которая ему понравилась, это HTTP файлы и Endpoint Explorer, вообще не связаны между собой вещи, кроме там слова HTTP, наверное, но обе прекрасны. -6276.98 6285.18 SPEAKER_01 HTTP файл – это возможность в Visual Studio сделать специальный файлик с расширением HTTP и писать там обычным текстом запросы. -6285.18 6292.66 SPEAKER_01 Типа, дай мне такой сервис, и вы нажимаете специальную кнопочку, о, не дай, а вызови мне такой-то HTTP урл, допустим, какой-то Endpoint какой-то. -6292.66 6301.34 SPEAKER_01 Нажимаете специальную кнопочку, и у вас этот урл вызывается, и показывается ответ от удаленного сервиса в виде такого же текстового файлика. -6301.34 6313.38 SPEAKER_01 Казалось бы, идея примитивная, т.е. это обычный курл, грубо говоря, т.е. но более в удобном виде, в удобном файлике, который можно сохранить, передать и т.д., но это действительно на практике безумно удобно. -6313.38 6331.98 SPEAKER_00 Ну, и эта штука поддержана не только в Visual Studio, она поддержана многими и IDE, и RIDER такой умеют, в общем, такой плюс-минус стандарт, что ли, VVS-код, всё это пошло, на самом деле, из VVS-кода, где кто-то написал отличный экстенджер, который, собственно, эту идею предложил, насколько я понимаю. -6331.98 6334.46 SPEAKER_00 Ну и дальше это потихонечку растянулось во все места. -6334.46 6337.86 SPEAKER_01 Я даже уже не боюсь предположить, откуда это первый раз пошло. -6337.86 6344.86 SPEAKER_01 Ну, я, например, допользуюсь Visual Studio кодом, мне там удобнее такую штуку делать, но надо понимать, что Visual Studio тоже это умеет. -6344.86 6379.82 SPEAKER_01 И второй подпункт – это Endpoint Explorer, тоже прекрасная тулза, которая позволяет вам просканировать весь ваш проект, притом не надо его запускать, сканируется исходный код, и посмотреть все endpoints, которые у вас есть, и посмотреть, где они в одном единственном окошечке, что они вызывают, а самое приятное – это сгенерировать для них реквест, и этот реквест как раз генерируется в подобном http-файле, т.е. вы можете открыть, нажать кнопочку "Generate" и позапускать запросы прямо к вашему endpoint, и увидеть сразу в этом же файле ответы к этому endpoint, вообще прекрасно. -6379.82 6395.30 SPEAKER_01 Третий пункт – это GitHub Copilot, GitHub Copilot Chat, в общем, все, что связано с искусственными интеллектами, которые помогают нам давать подсказки в реальном времени, а также помогают кодить, помогают генерить файлы, тесты, рефакторинг, объяснять код и прочее-прочее. -6395.30 6427.82 SPEAKER_01 Четвертый пункт – это GIT и улучшения в пул реквестах, т.е. вы в Visual Studio можете создать и управлять GIT-репозиториями с помощью интегрированного в Visual Studio UI, вы можете прилинковать коммиты из GitHub-ов, из GitHub-issues для более тщательного общения там и по отслеживанию истории того, что вы делаете, и также в Visual Studio есть встроенный пул реквест-креатор, который умеет создавать пул реквесты прямо из Visual Studio. -6427.82 6432.06 SPEAKER_01 Игорь, ты пользуешься Visual Studio и вообще вот этой интеграцией с GIT-ом? -6432.06 6442.54 SPEAKER_00 У меня GIT либо command-line, либо веб, так сказать, вариант, либо сторонник-клиент, из Visual Studio я GIT-ом практически не пользуюсь. -6442.54 6450.94 SPEAKER_01 Да, у меня похожая ситуация, но судя по картинкам это выглядит все прекрасно, в общем-то, гораздо лучше, чем, например, пул реквесты смотреть в вебке. -6450.94 6453.74 SPEAKER_01 Но надо пересилиться и попробовать, наверное. -6453.74 6471.14 SPEAKER_00 Нет, я таким пользуюсь в Райдере, когда я смотрю гитлабовские мерч реквесты, там это называется, там есть специальное расширение, которое позволяет прямо нативно, она подтягивает сразу чек-аутик, нужную веточку тебе, все дифы, сразу все навигации тут же работают, все прекрасно работают, шикарно. -6471.14 6474.06 SPEAKER_00 Если в студии сделали так же, это прекрасно. -6474.06 6476.14 SPEAKER_01 Ну вот судя по скриншотам, да, там тоже пытались что-то -6476.14 6477.14 SPEAKER_00 подобное сделать. -6477.14 6483.90 SPEAKER_00 Ну слушай, мы весь прошлый год в превьюхах, каждое превьюху было что-то улучшение в GIT-е, так что я не удивлен. -6483.90 6498.30 SPEAKER_01 Пятый пункт, вообще не поверите, вот рядом с АИ, девтуннелями, гитхабами, копайлотами стоит такая прекрасная штука, как разноцветные скобочки фигурные. -6498.30 6505.38 SPEAKER_01 Заключается смысл в том, что Visual Studio, кстати, с подачи Мэтта Торгессона, не Мэтта Торгессона, а как главный наш писатель? -6505.38 6506.38 SPEAKER_01 Мэтс Кристенсен. -6506.38 6550.74 SPEAKER_01 Мэтс Кристенсен, да, позаводили Мэтсов, с подачи Мэтса Кристенсена эта штука появилась в Visual Studio, естественно, я сначала плагин под ним написал, штука, которая позволяет вам раскрашивать фигурные скобочки, ну открыть-закрыть блок в разные цвета, и дает это два преимущества, во-первых, вы видите фигурные скобочки, они у вас выделяются, и во-вторых, вы вложенность, видите уже вложенные фигурные скобочки, вы уже видите совершенно другим цветом, да, и это визуально помогает вам улучшить читабельность и улучшить идентификацию скобочек друг от друга, то есть пару ей найти очень быстро визуально, и это по мнению Джеймса, в общем, достойная мега фича, которую срочно стадо упомянуть, и он не понимает, как он без этого раньше жил. -6550.74 6553.66 SPEAKER_00 Ну, может, код у него такой, с кучей скобочек он пишет. -6553.66 6556.42 SPEAKER_01 Ну, код с кучей скобочек у нас у всех, да. -6556.42 6562.06 SPEAKER_00 Слушай, ну следующая ему тоже, spellcheck, ну блин, spellcheck, как бы, что такое? -6562.06 6567.14 SPEAKER_01 Ну, да, он есть у многих, просто в Visual Studio недавно появился, я, например, тоже живу долго с spellcheck. -6567.14 6571.66 SPEAKER_00 Сколько у меня ошибок оказывается, да, сказал он, ну какая полезная штука, ну да. -6571.66 6577.78 SPEAKER_00 А вот следующая мне, кстати, даже непонятна на самом деле, давай вот я так быстро перебрыгну. -6577.78 6585.10 SPEAKER_00 Это accessibility checker, если ты говоришь, что он в основном про мобильную разработку, а тут в основном про ВПФ, насколько я вижу. -6585.10 6589.42 SPEAKER_01 Ну, он про мобильную разработку в терминах Xamarin, а Xamarin это -6589.42 6591.42 SPEAKER_00 ВПФ, поэтому что-то удивляешься. -6591.42 6592.42 SPEAKER_00 Ладно, хорошо. -6592.42 6609.34 SPEAKER_01 Ну то есть accessibility checker довольно полезная вещь, она умеет сканировать ваши десктопы визуальные там или мобильные, короче, любое приложение, у которого есть разметка визуальная, юайка, которая есть, правильно сказать, да, и подсвечивает вам какие-то ошибки, которые можно устранить и которые можно прооптимизировать для лучшей доступности. -6609.34 6610.34 SPEAKER_01 Прикольно. -6610.34 6617.14 SPEAKER_01 Восьмой пункт, это его вдохновляет, тотнет эспайр и всё, что с ним происходит, в общем, без эспайра ни на одной темы ни одного дня у нас. -6617.14 6618.82 SPEAKER_01 Ну, надо же профушить. -6618.82 6619.82 SPEAKER_00 Ну, наверное, да. -6619.82 6620.82 SPEAKER_00 Да, все дела, да. -6620.82 6638.66 SPEAKER_01 Несмотря на то, что у них там есть эспайр-темплейт, который позволяет вам создавать новые проекты, вы также можете добавить эспайр в существующие проекты благодаря Visual Studio, и также ему нравится, что там прекрасные дефолты есть, которые подключают сразу и трейсинг, и метрики, и дают красивые дашборды, и всё это красиво без единой там нажатия кнопочки. -6638.66 6641.10 SPEAKER_00 Звучит, как типичный рекламный текст. -6641.10 6642.10 SPEAKER_01 Давай дальше. -6642.10 6643.10 SPEAKER_01 Это точно. -6643.10 6663.62 SPEAKER_01 Visual Studio UI Refresh, я долго думал, кто там рефрешит у Visual Studio что-то, оказывается, Visual Studio в прошлом году сильно улучшило свой дизайн, он теперь стал более современным, например, появились скругленные уголочки, табики начали вести себя немножко по-другому, и подтянулись новые темы, и также эти темы прооптимизировались. -6663.62 6664.62 SPEAKER_01 Прекрасно. -6664.62 6665.62 SPEAKER_01 Да. -6665.62 6671.70 SPEAKER_01 И последний, десятый пункт – это C# WebKit for Visual Studio Code. -6671.70 6672.70 SPEAKER_00 Давай, DevKit. -6672.70 6674.54 SPEAKER_00 Всё-таки не WebKit, а DevKit. -6674.54 6678.34 SPEAKER_00 Это, да, набор плагинов для VS Code. -6678.34 6698.46 SPEAKER_01 Для Visual Studio, который над Language Service, настраивает вам нормальный Solution Explorer, даёт хорошие темплейты, тест Discovery, тест Solution, дебаггинг хороший, IntelliSense тот же самый подключает, в общем, делает практически вот из Visual Studio Code полноценную Visual Studio, ну, по крайней мере, пытается на том Language Service, который у неё есть. -6698.46 6712.78 SPEAKER_00 Нет, ну там как раз Language Service это неплохой, потому что, я так понимаю, что они туда тянут свой, который закрытый и хороший, а я так понимаю, что эта цель как раз какая-никакая замена в Visual Studio for Mac, потому что таким образом на VS Code вы можете нормально писать. -6712.78 6715.66 SPEAKER_00 Ну, кроссплатформенной версии, да, что-то такое. -6715.66 6716.66 SPEAKER_00 Да, да. -6716.66 6717.66 SPEAKER_00 Давай, у тебя три минуты. -6717.66 6721.82 SPEAKER_00 У меня три минуты, так у меня же тема называется «Кратко о разном». -6721.82 6722.82 SPEAKER_00 Никаких проблем. -6722.82 6723.82 SPEAKER_00 Кратко так кратко. -6723.82 6740.16 SPEAKER_00 Во-первых, вышла статья от Джеймса Ньютон Кинга про то, что, напоминаем, что у нас, у Майкрософта есть очень классные дэшбордики для графана, то есть Aspire это, конечно, хорошо, но графану мы не забываем. -6740.16 6748.20 SPEAKER_00 Короче, есть репозитории, где лежат полезные дэшборды, которые очень круто показывают состояние вашего Asp.NET приложения. -6748.20 6752.88 SPEAKER_00 Так что, если вы пользуетесь графаной и пишете на дот.нете Asp.NET приложение, посмотрите обязательно. -6752.88 6760.56 SPEAKER_00 И вторая новость это, если вы не знаете, есть такой, не знаю, продукт, библиотека, Enquire. -6760.56 6761.56 SPEAKER_00 Кто он? -6761.56 6762.56 SPEAKER_00 Библиотека, мне кажется. -6762.56 6763.56 SPEAKER_00 Библиотека или фреймворк. -6763.56 6764.56 SPEAKER_00 Фреймворк, да. -6764.56 6765.56 SPEAKER_00 Вот такое. -6765.56 6773.24 SPEAKER_00 Это все, всякие там про таймеры, запуск, про расписание, вот это все, короче, шедулер, вот все вокруг этого. -6773.24 6779.88 SPEAKER_00 Они написали библиотечку, которая называется Kronos, которая позволяет на дот.нете парсить крон-экспрессион. -6779.88 6791.44 SPEAKER_00 То есть, если вот эти все ваши стандартные там, один звездочка-звездочка-звездочка-звездочка, вот это все, библиотечка, которая позволяет это все распарсить, причем она поддерживает ряд кастомизаций, там интервалы можно задавать. -6791.44 6817.12 SPEAKER_00 Поддерживает нормальный парсинг, поддерживает нормальный удобную API-шку вида, а дай мне, пожалуйста, когда случится следующее событие согласно этому крону от текущего момента, или дай мне, пожалуйста, все события, которые случатся в интервале ближайший год для вот этого крон-выражения, и он вам вернет набор дэйт таймов, когда же случится то, что должно было случиться по вашему запрограммированному крону. -6817.12 6828.92 SPEAKER_00 Короче, если пользуетесь вдруг крон-синтаксисом зачем-то, посмотрите на кроны, скажется, что это довольно неплохая библиотека от чуваков, которые знают, что такое шедулеры и явно, скорее всего, парсить крон умеют. -6828.92 6832.40 SPEAKER_01 Да, судя по фичам, очень крутая библиотечка, стоит -6832.40 6833.40 SPEAKER_00 попробовать. -6833.40 6874.96 SPEAKER_00 Ну, на этом все, мы посмотрели на DotNet 9 Vision, посмотрели на DotNet 9 Preview 1, узнали, как мы собираемся ломать C# 13-й версии, посмотрели на Visual Studio 20.22, 17.9 и 17.10 Preview 1, узнали у Эндрю Лока очередной раз, как же мы можем настраивать урлы и порты для Espanet Core приложения, посмотрели на новинки Aspire Preview 3, поразмышляли об категориях ошибок, об ошибках категорий вместе с Марком Симоном, ну и узнали крутые 10 новых фич в Visual Studio за 2023 год, по мнению Джеймса Монтеманио. -6874.96 6876.88 SPEAKER_00 И на этом все. -6876.88 6883.32 SPEAKER_01 Всем до новых встреч, лайки, шарики, репосты, ждём ваших комментариев, присылайте письма, всем пока. -6883.32 6883.96 SPEAKER_01 Всем пока. +0.00 11.40 "Анатолий Кулаков" Здравствуйте, дорогие друзья, в эфире Radio.net, выпуск номер 88. +11.40 15.72 "Анатолий Кулаков" И сегодня с вами его постоянный ведущий Анатолий Кулаков +15.72 16.92 "Игорь Лабутин" и Игорь Лабутин. +16.92 17.92 "Игорь Лабутин" Всем привет. +17.92 34.44 "Анатолий Кулаков" А также большая-большая армия наших помогаторов, в частности Александр, Сергей, Владислав, Шевченко Антон, Лазарев Илья, Гурий Самарин, Виктор, Руслан Артамонов, Александр Ерыгин, Сергей Бензенко, Александр Лапердин и Ольга Бондаренко. +34.44 36.40 "Анатолий Кулаков" Всем спасибо, друзья, кто нас поддерживает. +36.40 46.20 "Анатолий Кулаков" Если вы не знаете, про что я говорю, заходите на Boosty и поддержите мелкой копеечкой ваш любимый подкаст и посмотрите также, что у нас там еще есть интересного для вас. +46.20 66.32 "Анатолий Кулаков" Так, из неофициальных новостей у нас все еще продолжается CFP на .NEXT, поэтому если вы хотите стать звездой и блистать на самой большой конференции по .NET, то обязательно поддавайтесь на спикерство, поддавайтесь на доклады, мы поможем с тренировками, с подготовками, со всем и сделаем отличную конференцию вместе. +66.32 68.52 "Анатолий Кулаков" Поэтому всех ждем, всех милости просим. +68.52 73.00 "Анатолий Кулаков" И, кажется, из неофициального это все, можно приступать к выпуску. +73.00 74.00 "Анатолий Кулаков" Как у нас там с материалами? +74.00 75.00 "Анатолий Кулаков" Микрософт подтянулся? +75.00 94.20 "Игорь Лабутин" Да, Майкрософт нашел, чем нас порадовать, ну или погрустить тут же, я не знаю, кому как, и выпустил не только статью про то, что там у нас новый превью, у нас там еще что-нибудь, а у нас прям теперь есть статья под названием «Новый вижен .NET 9», точнее не то, что новый, просто вижен .NET 9. +94.20 99.96 "Игорь Лабутин" То есть что же Майкрософт в целом хочет сделать за этот наступающий год, так скажем. +99.96 109.24 "Анатолий Кулаков" Знаешь, интересно, после статей, как бы мы переписываем .NET сервисы на раст от Майкрософта, уже прям страшно такие вижены смотреть, открывать, так знаешь, страничку. +109.24 134.24 "Игорь Лабутин" Ну открываешь вижен, на самом деле там начинается все с типичных, ну я бы сказал баз вардов, то есть там написано, что самый главный фокус для нас это Cloud Native и Intelligent App Application Development, ну имеется в виду, конечно же, все, что связано с искусственным интеллектом, ну и куда же без тщательное и значительное вложение в Performance, Productivity и Security. +134.24 142.16 "Игорь Лабутин" Короче, все максимально общие слова, такое можно, наверное, сказать практически про любую платформу, про любой релиз, но вот тем не менее, вижен и вижен. +142.16 149.64 "Игорь Лабутин" Но этими словами не только ограничивается, точнее не только ими все ограничивается, есть расшифровка, что же это все значит. +149.64 188.96 "Игорь Лабутин" Начнем мы с раздела номер один, называется он Platform for Cloud Native Developers, и здесь Майкрософт говорит примерно следующее, что они хотят сделать более легким, то есть не то, чтобы развивать именно сам .NET, а сделать так, чтобы у тех, кто пишет на .NET были простые и легкие способы использовать популярную инфраструктуру, которую все и так используют в Prod, ну например, не знаю Kuber или еще что-нибудь, там Redis, более так сказать прямолинейным путем из .NET, то есть сделать так, чтобы все было попроще. +188.96 195.00 "Игорь Лабутин" И конечно же, главный кусочек здесь это .NET Aspire, тут куда же без него, мы про него уже каждый выпуск говорим. +195.00 239.28 "Игорь Лабутин" Кроме того, это конечно же найти фауты Trimming, потому что это позволяет уменьшать размеры кода в контейнере и размеры в контейнерах, дальше туда же уходит новый режим Garbage Collector, который был в The Religion в прошлом .NET, это Dynamically Adaptable to Application Size, то есть штука, которая позволяет подгонять размеры потребляемой памяти, а точнее количество куч, которые использует Garbage Collector внутри себя для разных режимов работы вашего приложения и в динамике их менять, ну и всякие более прикладные вещи, типа там Rate Limiting вот этого всего, то что без чего сейчас не живет ни одно Cloud Native приложение, вот это все будет, так сказать, в фокусе команды на ближайший релиз. +239.28 241.60 "Игорь Лабутин" Это то, что касается платформы. +241.60 306.48 "Игорь Лабутин" Есть еще раздел Tools for Cloud Native Developers, и с тулингом тут опять буду повторять те же самые слова, это опять же найти фаут, сейчас для того, чтобы что-то скомпилить в найти фаут, вам нужно поюзать, ну скажем так, как написано в Microsoft, это требует установки тулов, которые большинство дотнет-девелоперов, вообще говоря, обычно не используют, ну типа, например, докера или VSL, Windows Subsystem for Linux, а цель Microsoft сделать так, чтобы любой пользователь Visual Studio мог это все спокойно делать, поэтому они будут расширять поддержку Ahead of Time компиляции в Visual Studio каким-то образом, не знаю, пока каким, ну а также, конечно же, дотнет Aspire, куда войдет более тщательная интеграция с Visual Studio и Visual Studio Code, конфигурация компонентов, отладка, включая Hot Reload, ну и какая-то интеграция с тем самым дэшбордом, то есть, видимо, так, чтобы этот дэшборд можно было смотреть не только в браузере, но, возможно, прямо из студии в каком-нибудь там тулинг окошке, не знаю пока. +306.48 324.16 "Игорь Лабутин" Никуда мы не деваемся от искусственного интеллекта, Microsoft, наверное, не был бы Microsoft, если бы не сказал, что они не будут делать никакой искусственный интеллект на дотнете, конечно же, будут, и, конечно же, там ведется некоторое количество разработок уже. +324.16 340.56 "Игорь Лабутин" Основная цель — это не то, чтобы прямо на дотнете все это писать, а именно сам искусственный интеллект, а больше цель на то, чтобы интегрировать в себя все те тулы, которые сейчас есть, то есть более легкое использование там всяких OpenAI и других открытых моделей. +340.56 364.08 "Игорь Лабутин" Ну и дальше, так скажем, сотрудничество со всякими тем же самым OpenAI, сотрудничество с HRSDK, чтобы более удобно использовать всякие Artificial Intelligence сервисы из Azure, и все такое прочее, просто чтобы было попроще на дотнете использовать искусственный интеллект, ну потому что все этим, конечно, сейчас занимаются. +364.08 377.32 "Игорь Лабутин" Кроме того, несмотря на то, что у нас есть как бы отдельная статья под названием DotNet 9, overview, да, как там называется, Roadmap Vision, есть еще Roadmap отдельных команд. +377.32 389.20 "Игорь Лабутин" И я ради интереса заглянул в эти Roadmap, может быть, оно немножко пересечется с превью, который мы будем обсуждать чуть позднее в этом выпуске, но первым мне на глаза попался Maui Roadmap. +389.20 392.72 "Игорь Лабутин" Как ты думаешь, что же у нас в Maui Roadmap? +392.72 396.52 "Анатолий Кулаков" Перформанс, интеграции, стабилити и все такое? +396.52 397.52 "Игорь Лабутин" Типа того. +397.52 409.08 "Игорь Лабутин" У них это называется Product Quality Across Layout, то есть они будут улучшать layouting, они будут улучшать контролы, они будут улучшать надежность тулинга, вот. +409.08 423.52 "Игорь Лабутин" И может быть, как у них написано, these items are under consideration, будет interrupt со свифтом, чтобы ты мог свифтовые кусочки на iPhone отдергать, может быть, они подумают про кастомные курсоры. +423.52 426.56 "Анатолий Кулаков" Во-во, вот это замахнулись прямо. +426.56 438.36 "Игорь Лабутин" Да, и на том же уровне у них стоит, что они часть контролов подвинули в Maui Core слой для того, чтобы они были, ну там, видимо, можно их быстрее писать, там я не знаю еще как, что. +438.36 448.00 "Игорь Лабутин" Вот они move, короче, remainder of controls, оставшиеся контролы тоже подвинуть в Maui Core Layer для того, чтобы стало лучше с перформансом и стабилити. +448.00 452.08 "Игорь Лабутин" Короче, мы что-то будем делать, но мы пока не знаем, что мы будем делать. +452.08 454.32 "Игорь Лабутин" Quality и стабилити как бы. +454.32 456.36 "Игорь Лабутин" Quality и стабилити, да. +456.36 464.72 "Игорь Лабутин" Значит, дальше я посмотрел на SPNet Core Roadmap, там много всего, прям очень много, но все это под одним большим жирным заголовком – Blazor. +464.72 475.16 "Игорь Лабутин" То есть из прям таких больших, ну как сказать, не мега-фич, а таких направлений, да, это Blazor, Blazor, Blazor, еще Blazor, все для Blazor. +475.16 478.60 "Игорь Лабутин" Конечно, там будут другие улучшения, но вот это основное. +478.60 487.00 "Анатолий Кулаков" Смотри, как интересно, это же Blazor, он же никуда не вписывается, это и не Artificial Intelligence, и не CloudNet, и вообще никуда. +487.00 490.00 "Анатолий Кулаков" Зачем они у него столько сил вкладывают, непонятно. +490.00 491.00 "Игорь Лабутин" Не знаю пока. +491.00 532.20 "Игорь Лабутин" Ну вот посмотрим, то есть я действительно пытался найти в SPNet какие-то, ну прям такие, в вышках, которые там приведены в качестве Roadmap, какие-то более приземленные, что ли, или относящиеся к SPNet штуки, но там есть, конечно, там тема раутинг здесь, там какие-то форм-байнинги там, но они очень мелкие на самом деле, какие-то мелкие полировка всего того, что уже есть в Minimal API и в остальных местах, почему, не знаю, ну может быть они пытаются таким образом как-то, не знаю, тех, кто пишет на дотнете, десктопы, например, писал, и сейчас пересаживается на современный дотнет, типа можно JS не учить? +532.20 538.92 "Анатолий Кулаков" Ну десктопы, мне кажется, уже давно волна прошла, которых пересаживали, ну там, естественно, они еще сохранились, но все же первая активная волна была потом. +538.92 547.00 "Анатолий Кулаков" Мне кажется, наоборот, они видят, что не хватает фронтовиков и пытаются все-таки пересадить, ну побороться с JavaScript в этом плане, с WB Assembly и все такое. +547.00 552.28 "Игорь Лабутин" Ну побороться, откусить маленький кусочек, может быть. +552.28 553.28 "Игорь Лабутин" Ну да, наверное. +553.28 557.84 "Анатолий Кулаков" Ну ты же понимаешь, что там даже если от слонака бы маленький откусить, тут уже как бы много. +557.84 558.84 "Анатолий Кулаков" Это да. +558.84 559.84 "Игорь Лабутин" Уже хватит всем. +559.84 560.84 "Игорь Лабутин" Это правда. +560.84 563.60 "Игорь Лабутин" Поэтому может быть и действительно имеет смысл кусать. +563.60 580.16 "Игорь Лабутин" Дальше у нас есть C# Roslyn, там все очень непонятно, потому что там есть некоторый список VNEXT, который можно было бы принять за то, что вот это может быть и войдет в следующую версию C#, но проблема в том, что некоторые сущности в этом VNEXT живут уже годами. +580.16 588.36 "Игорь Лабутин" Какие-нибудь как Rawls Extensions там или, не знаю, Paramspans, они, по-моему, уже два релиза живут, не срелизятся. +588.36 589.36 "Игорь Лабутин" Вот. +589.36 590.36 "Игорь Лабутин" Но посмотрим. +590.36 602.00 "Игорь Лабутин" Из очередных таких полукрышесносящих штук, которые мы скорее всего будем, если их сделают, мы будем разбирать и пытаться понять, нафига это сделано, это будут refstruct интерфейсы. +602.00 608.32 "Игорь Лабутин" То есть спаны можно будет делать, спаны смогут реализовывать интерфейсы. +608.32 620.96 "Анатолий Кулаков" Жестоко, refstruct интерфейсы, ну то есть с интерфейсами, которые реализуют методы, мы уже сталкивались, теперь интерфейсы, которые только для структур, по идее, будут и не просто для структуры, а только для reference structure. +620.96 629.92 "Игорь Лабутин" Короче, да, если еще вспомнить, что есть еще readonly, refreadonly, вот это все, то, короче, сделают фичу, посмотрим. +629.92 633.80 "Анатолий Кулаков" Ужас, ужас, что-то куда-то не туда она идет. +633.80 634.80 "Игорь Лабутин" Да. +634.80 665.88 "Игорь Лабутин" Ну и есть у F# отдельный roadmap, там на самом деле довольно все прикольно сгруппировано, они будут пилить, ну или обновлять скорее, ленгвич сервер, короче, LSP для Visual Studio, Visual Studio Code, они будут улучшать перформанс компилятора и вот этого самого LSP, ну и докидывать там кучку аналайзеров, вот это все, как всегда, догонять по фичам в C#, когда C# что-нибудь зарелизит, такое, что не очень совместимо с F#, им придется срочно пилить совместимость, чтобы ничего не развалилось. +665.88 666.88 "Игорь Лабутин" Ну, в общем, как-то так. +666.88 672.12 "Игорь Лабутин" Вот, примерно, такой у нас vision.net. +672.12 682.56 "Анатолий Кулаков" Ну и тут, в принципе, наверное, важно понимать, что это как бы не roadmap уже конечных фич, потому что почему-то Microsoft никогда не рассказывает те большие фичи, над которыми они работают. +682.56 690.12 "Анатолий Кулаков" Они все еще, у меня от себя не знаю, какая-то коммерческая компания, которая во время релиза сообщает какие-то громкие навидки интересные, которые нас встречают. +690.12 692.36 "Анатолий Кулаков" Ну, можем вспомнить много примеров. +692.36 704.80 "Анатолий Кулаков" Поэтому это, наверное, какой-то такой действительно общий roadmap, те мелкие вещи, которые уже известны, но, скорее всего, в рукавах там есть несколько больших фич, которые будут релизиться, будут выпускаться, о которых мы еще понятия не имеем. +704.80 706.64 "Игорь Лабутин" Может быть, даже и они понятия не имеют. +706.64 723.08 "Игорь Лабутин" Кажется, что Aspire, например, поскольку он вышел только на dotnet.conf в виде первого превью, да, то есть не факт, что он там с фероля начал делаться, может быть, какие-то идеи позднее появились, потому что я думаю, что тогда бы они dotnet.conf чего-нибудь более табильное бы выпустили. +723.08 726.80 "Анатолий Кулаков" Может быть, они даже не думали, что оно вообще выстрелит и кому-то это будет интересно. +726.80 731.56 "Игорь Лабутин" Ну или что успеют, в принципе, доделать dotnet.conf хоть как-то, хотя бы до первого превью. +731.56 737.56 "Игорь Лабутин" Так что будем смотреть, да, давайте поглядим дальше, ближе к делу. +737.56 738.56 "Анатолий Кулаков" Давай дальше. +738.56 745.92 "Анатолий Кулаков" Ну и тут как раз, да, как раз недалеко от вижена вышел превью 1, девятки, как бы всех фреймворков, которые связаны и так далее. +745.92 760.80 "Анатолий Кулаков" И самое, наверное, запоминающееся в этом превью 1 в том, что эти господа изменили структуру анонсов, которые раньше были оформлены в виде хороших блокпостов, которые было прекрасно читать, прекрасно вам рассказывать и прекрасно искать и ссылаться. +760.80 781.44 "Анатолий Кулаков" Теперь они там превратили это все в какой-то ад, они сделали все анонсы в гитлабе, о, в гитхабе, они сделали все анонсы в гитхабе, при том половина из них в виде ишисов, половину тегами к релизам, половину маркдаун-файлы, которые не забросили репозиторий, и еще есть штучки три разновидностей на сайтах микрософта, leon, whatsnew, там и еще где-то в блогах. +781.44 796.88 "Анатолий Кулаков" В общем, получилась адская смесь, ну не знаю, с одной стороны, конечно, плохо, с другой стороны у вас теперь точно не будет никакого шанса самим это читать, вам придется нас слушать, потому что мы все это сагрегировали, задистинктили и доносим вам понятным, упорядоченным языком. +796.88 808.56 "Анатолий Кулаков" Поэтому, не знаю, я сначала, когда собирал анонс, я думал, что я половину не нашел, как бы того, что заанонсили, я все-таки не нашел 10-20 лишних ресурсов, где это тайком нам рассказали. +808.56 813.08 "Анатолий Кулаков" Ну на самом деле нет, я в принципе нашел все, и анонс сам по себе довольно бедненький. +813.08 818.30 "Анатолий Кулаков" Кажется, что это, знаешь, как Hello World, его выкатывают не ради функциональности, а ради того, чтобы обкатать новую инфраструктуру. +818.30 828.00 "Анатолий Кулаков" Так и здесь они вот надумали себе каких-то глупостей, не хотят обкатать инфраструктуру, поэтому надо было выпустить хоть что-то, хотя бы даже без изменений, просто версию поднять. +828.00 837.64 "Игорь Лабутин" Зато смотри, зато теперь тебе не нужен какой-нибудь клевый автор на девблог, просто сами разработчики закидали маркдаун файлик в репозитории, вот тебе и релиз ноутс. +837.64 848.88 "Анатолий Кулаков" Так и есть, и это в лучшем варианте, если взять какой-нибудь там капам в EF Core, там просто дали тебе эту сотню ссылок на исчез и все, вот наш what's new. +848.88 852.48 "Анатолий Кулаков" Как бы легче всего, что за спринт закрыли, вот это и разбирайте. +852.48 857.92 "Игорь Лабутин" Это они и в прошлом году так делали, от них статьи не было, в общем-то, одна или две за весь год. +857.92 865.20 "Анатолий Кулаков" Ну, как бы то, что вы спихнули на разработчиков написание документации еще не решит проблему, а скорее всего даже усугубит ее. +865.20 869.00 "Игорь Лабутин" Ну ладно, давай посмотрим, что в итоге рано-насобиралось. +869.00 893.28 "Анатолий Кулаков" Ну начнем с фреймворка, .NET 9, тут одни из самых главных нововведений, это то, что в JSON Serializer Options теперь засунули два необходимых всем свойства, это Ident Size и Ident Character, то есть то, как мы будем отбивать наши отступы в сериализованном JSON-файлике, и то, каким символом мы будем это делать, ну как бы, как мы без этого жили непонятно. +893.28 898.20 "Анатолий Кулаков" Дальше, вот это еще более-менее нормальная тема, добавили в линку парочку полезных методов. +898.20 903.92 "Анатолий Кулаков" Во-первых, это Count By, который позволяет вам вычислить то же самое количество, но уже по определенному ключу. +903.92 911.32 "Анатолий Кулаков" Есть часто случаи оптимизации, когда это намного удобнее, чем сделать Select, а по нему уже Count, или что-то типа того городить. +911.32 918.32 "Анатолий Кулаков" Aggregated By, который похож на основной Aggregate, но тоже умеет воспринимать в особых местах ключик, где тоже это полезно. +918.32 929.68 "Анатолий Кулаков" И довольно концептуально новая вещь, это новый метод Index, который возвращает нам tuple, где мы получаем элемент вместе с его индексом. +929.68 934.80 "Анатолий Кулаков" Это очень похоже на Select с индексом, вы наверняка таким могли пользоваться. +934.80 942.24 "Анатолий Кулаков" Что есть метод Select, который принимает в качестве аргументов порядковый номер этого элемента в единомерабле и сам элемент. +942.24 945.60 "Анатолий Кулаков" И на основании это что-то делает, что-то происходит. +945.60 951.80 "Анатолий Кулаков" Вот здесь же этот номер и элемент, они просто возвращаются, они не передаются в какое-то замыкание. +951.80 954.04 "Анатолий Кулаков" Вот поэтому их, например, удобно в фурриче прокручивать. +954.04 970.68 "Анатолий Кулаков" Дальше, про фреймворк в Priority и Q немножко изменилось, тогда добавили метод Remove, это сделало возможным эмулировать изменение приоритетов в этой Priority и Q, потому что раньше это было невозможно, и поэтому некоторые хорошие оптимизированные алгоритмы невозможно было сделать. +970.68 972.32 "Анатолий Кулаков" В общем, теперь это возможно. +972.32 985.40 "Анатолий Кулаков" У Security области добавилась поддержка алгоритма KeemAC, это к МАК, поэтому в дотинной девятом к МАК со всех сторон пропихивают, рассовывают во всякие места, чтобы он везде поддерживался. +985.40 1001.24 "Анатолий Кулаков" Небольшое изменение в Assembly Builder, в билдере его сделали persistent имплементацию, то есть теперь мы в рантайме можем собирать код через Reflection Emit, и не только собирать, но и теперь мы можем его сохранять в виде сборки. +1001.24 1005.72 "Анатолий Кулаков" В общем, это тоже возможно после превью первого. +1005.72 1009.84 "Анатолий Кулаков" Саму фреймворк, в принципе, это все, давай по другим компонентам посмотрим. +1009.84 1012.16 "Анатолий Кулаков" Прежде всего, рантайм. +1012.16 1021.60 "Анатолий Кулаков" В рантайме есть оптимизация в NetEvo Auto, сюда притащили Object Writer, новый Object Writer, который был написан на чистом C#. +1021.60 1032.00 "Анатолий Кулаков" До этого в 7, 8 версии использовался тот же самый Object Writer, который базировался на LLVM версии в библиотеке и использовался везде он. +1032.00 1040.72 "Анатолий Кулаков" Это специальный объект, специальный классик, с помощью которого записывалась дебаг информации и всякие дебажные символы для NetEvo Auto. +1040.72 1045.40 "Анатолий Кулаков" То есть полезная в хозяйстве вещь, но была использована через интеропы всякие. +1045.40 1050.92 "Анатолий Кулаков" А теперь на чистом C#, теперь она стала быстрее, у нее удобный интерфейсик и куча простора для оптимизации. +1050.92 1051.92 "Анатолий Кулаков" Ну как и все. +1051.92 1057.28 "Анатолий Кулаков" Идти и кроссплатформенно, и отвязались от лишних нативных лип, что тоже не может не радовать. +1057.28 1068.20 "Анатолий Кулаков" Дальше есть много луп-оптимизаций, то есть оптимизаций циклов, как их красиво выравнивать, разворачивать, выносить неизменяющиеся конструкции за пределы цикла и вот это вот все. +1068.20 1081.80 "Анатолий Кулаков" Также добавилась поддержка AMD64, SVE и SVE2 инструкций, это Scalable Vector Extensions, которые очень широко используются, например, в машин-ленингах и во всяких high-performance компьютингах. +1081.80 1085.60 "Анатолий Кулаков" Наверное, тоже богатым и жирным принесет много удовольствия. +1085.60 1089.76 "Игорь Лабутин" Я тебя только тут поправлю, это не AMD64, это все-таки ARM64. +1089.76 1097.40 "Игорь Лабутин" На AMD64 у нас давно всякая параллелизация и прочее есть, векторизация, а вот на ARMах с ней было, ну вроде тоже неплохо, но сейчас стало получше. +1097.40 1101.72 "Анатолий Кулаков" Да, точно, спасибо, на ARM. +1101.72 1116.62 "Анатолий Кулаков" Оптимизации у JITA приехали также в Registered Allocation Improvements, ну это как раз та часть, которая сильно страдала при стартапе, в общем, там тоже что-то подшаманили, что теперь стартап или сделают, или будут делать быстрее и красивше. +1116.62 1138.08 "Анатолий Кулаков" В SDK, в самом Build Tool, которым мы пользуемся, добавили Terminal Logger по дефолту включенный, мы обсуждали же Terminal Logger, это специальная версия аутпута, когда вы запускаете те же самые .NET Build, Restore, Pack и прочие вещи, а вот аутпут, который выдается, теперь будет намного красивее. +1138.08 1148.56 "Анатолий Кулаков" В частности, там появятся кликабельные ссылки, продолжительность различных операций, т.е. таймеры внедрятся, различные подсветки, разноцветные подсветки, уборнингов и роров. +1148.56 1152.64 "Анатолий Кулаков" В общем, станет все очень красивенько и нативненько, и модненько, и стильненько. +1152.64 1171.88 "Анатолий Кулаков" Естественно, этот логгер, он не включается, если вдруг ваш терминал такого не поддерживает, т.е. он там все динамически анализирует и смотрит, что если у вас новый модный терминал с линками и эмоджиками, то он загружается и показывает что-то красивенькое вам. +1171.88 1177.12 "Анатолий Кулаков" Также немножко изменилось поведение команды .NET Tool Install. +1177.12 1190.52 "Анатолий Кулаков" Теперь, если вы вызываете .NET Tool Install и такой пакет на вашем компьютере уже установлен, но у вас находится более старая версия, то Install обновляет эту версию до самой последней, которую он найдет. +1190.52 1199.88 "Анатолий Кулаков" Раньше такого было делать не можно, раньше вам необходимо было вызывать отдельно .NET Tool Update, и с тем же самым эффектом практически. +1199.88 1212.46 "Анатолий Кулаков" А SP-Core практически спит, он добавил JSON-полиморфик Type-support для SignalEra, т.е. в SignalEra-хабах вы теперь можете децерализовать полиморфические ДТОшки, ну, допустим. +1212.46 1227.70 "Анатолий Кулаков" У Entity Framework из заметного, это поддержка комплекс-тайпов в Execute-Update, напомню, Execute-Update это мега шикарная штука, когда вы можете целую пачку по какому-то условию запихнуть в нее Update. +1227.70 1233.04 "Анатолий Кулаков" В общем, очень полезная вещь для многих сценариев, для многих алгоритмов, прям вообще класс. +1233.04 1250.48 "Анатолий Кулаков" А комплекс-тайпы тоже мы обсуждали как раз недавно, это специальные такие Entity в Entity Framework, которые инкапсулируют в себя какие-то более сложные типы, более сложные value-обжекты, которые могут раскладываться, допустим, на несколько полей. +1250.48 1256.20 "Анатолий Кулаков" И теперь вы такие сложные объекты тоже можете обновлять по условию. +1256.20 1261.72 "Анатолий Кулаков" Там синтаксис, конечно, немножко непривычен для нормального человека, но, к сожалению, там по-другому не сделаешь. +1261.72 1264.60 "Анатолий Кулаков" Поэтому если вам это нужно, вы даже этим будете радоваться. +1264.60 1275.60 "Анатолий Кулаков" Ну и MAUI тоже выпустил превью первый, но там практически ничего нет, про что можно сказать в приличном обществе, поэтому про него просто промолчим. +1275.60 1276.60 "Анатолий Кулаков" Ну, Performance, Stability. +1276.60 1279.32 "Анатолий Кулаков" Да, да, да, вот этот все. +1279.32 1291.40 "Игорь Лабутин" Я прямо вижу наши вот заметки к этому выпуску, и там видно там заголовок такой-то, там SDK Update, какие-то заметки, там SPNET, заметки Entity Framework, заметки про MAUI, только заголовок. +1291.40 1293.36 "Игорь Лабутин" Прям прекрасно, да. +1293.36 1299.16 "Анатолий Кулаков" Ну, просто про все остальные команды можно было хотя бы один параметр вытащить, а здесь вот просто ничего. +1299.16 1310.04 "Анатолий Кулаков" В общем, превью довольно бедный, практически никчемный, но, наверное, просто чтобы обкатать какую-то инфраструктуру для релизов или просто новую версию выпустить, чтобы что-то было. +1310.04 1328.40 "Игорь Лабутин" Ну, да, посмотрим, когда это будет уже нормальные следующие превью, превью 2, я надеюсь, там будет что-то ценное и хорошее, и, может быть, даже заметки как-то обретут, может быть, они какую-нибудь ретру проведут на тему того, что как неудобно это все читать и будут экспериментировать дальше. +1328.40 1344.52 "Анатолий Кулаков" Ну, я, кстати, лазил по гитхабу с целью как бы увидеть гневные комментарии, и, если честно, гневных не нашел, а таких нейтральных есть парочку, но не кажется, знаешь, что у них будет какой-то материал для того, чтобы проводить ретроспективы насчет их заметок. +1344.52 1348.72 "Игорь Лабутин" Ну, может, они сами на самом деле фиг знают, поймут еще что-нибудь. +1348.72 1350.84 "Игорь Лабутин" Ладно, глянем, давай дальше. +1350.84 1355.28 "Игорь Лабутин" Дальше у нас про C# и про breaking changes. +1355.28 1371.64 "Игорь Лабутин" В гитхабе появилось ищу, в котором, ну, точнее, как в гитхабе, в главном репозитории C# ленга появилось ищу, в котором Мэтт Скридсонсон в том числе рассуждает на тему того, как они собираются вносить breaking changes в C#. +1371.64 1384.56 "Игорь Лабутин" То есть надо понимать, что C# — язык, в который очень строго блюдет принцип обратной совместимости и фича, единожды добавленная в язык, в общем-то живет в этом языке, ну, можно сказать, вечно. +1384.56 1393.32 "Игорь Лабутин" Можно по пальцам, может быть, даже одной руки пересчитать случаи, когда в языке что-то прямо существенно серьезно ломалось. +1393.32 1407.88 "Игорь Лабутин" Но проблема заключается в том, что если таким образом жить дальше, то, ну, получается, что довольно много изменений в язык не сделать, потому что они, ну, ломающие по сути своей. +1407.88 1410.28 "Игорь Лабутин" И вот Мэтт приводит несколько примеров. +1410.28 1418.00 "Игорь Лабутин" Например, то, что сейчас давно хотят и, может быть, это появится в ближайшем C#, это так называемый field access. +1418.00 1419.00 "Игорь Лабутин" То есть что это такое? +1419.00 1425.20 "Игорь Лабутин" Напомню, у нас есть в классе, мы можем объявить property, мы можем объявить поле, field. +1425.20 1441.40 "Игорь Лабутин" При этом в свойстве вы можете написать setter, getter, и внутри setter вы можете, например, использовать неявную переменную типа value для того, чтобы ее, ну, присвоить тому полю, в который вы хотите его присвоить. +1441.40 1447.92 "Игорь Лабутин" То есть это то, что передали вам, когда присваивали в это поле, в это свойство что-то. +1447.92 1458.36 "Игорь Лабутин" Но для того, чтобы это работало, то есть если вам нужна какая-то кастомная логика в setter или getter, приходилось заводить собственно реальное физическое поле, куда это значение, например, складывать. +1458.36 1475.20 "Игорь Лабутин" Довольно давно висит пропозал про то, что ну раз у нас есть такое специальное переменное, типа псевдопеременное под названием value, давайте заведем псевдопеременное под названием field, и компилятор нам будет автоматически генерить вот это самое то, что на английском называется backing field. +1475.20 1480.92 "Игорь Лабутин" То есть поле, которое лежит под этим свойством и, собственно, занимается тем, что хранит это значение. +1480.92 1491.00 "Игорь Лабутин" А в setter или getter мы будем там писать field присвоить value, да, и там в getter и return field, грубо говоря, если прямо вот такое самое простейшее свойство написать, с явным getter и setter. +1491.00 1506.60 "Игорь Лабутин" Все бы хорошо, но эта штука является breaking change, потому что если у вас уже есть в классе, в области видимости getter или setter, поле под названием field, то внедрив такую новую штуку в язык, вы потенциально поменяете поведение. +1506.60 1529.80 "Игорь Лабутин" То есть либо вы начнете использовать вот этот новый field, новое псевдопеременное внутри setter и таким образом поменяете поведение, потому что раньше ваш setter, например, обращался к полю field, или, наоборот, вы добавите фичу в язык, но ради сохранения обратной совместимости внутри setter field не будет означать то, ради чего его добавляли в язык, ну тоже как бы странное поведение. +1529.80 1535.56 "Игорь Лабутин" Короче, breaking change — это то, что новенького, то, что еще не сделано. +1535.56 1548.72 "Игорь Лабутин" Но на самом деле, те фичи, которые вы хорошо знаете, они тоже в каком-то смысле были добавлены, ну скажем так, с определенными приседаниями, чтобы избежать breaking change. +1548.72 1554.04 "Игорь Лабутин" Например, всем известное слово var — это ключевое слово языка. +1554.04 1561.92 "Игорь Лабутин" И его добавление — это тоже было breaking change, потому что технически у вас мог быть класс по имени var маленькими буквами. +1561.92 1566.80 "Игорь Лабутин" Это, наверное, очень странный класс, но по идее он мог быть. +1566.80 1573.08 "Игорь Лабутин" Например, я допускаю такой пример, что он мог бы быть автосгенерен из какой-нибудь, не знаю, грамматики. +1573.08 1580.16 "Игорь Лабутин" У вас там в вашем домене var — это нормальный термин для какого-нибудь бизнес-объекта, и у вас мог бы быть такой класс, ну для удобства. +1580.16 1582.84 "Игорь Лабутин" Да, это не по C# стилю, но почему нет? +1582.84 1589.76 "Анатолий Кулаков" Ну проблема точно такая же, как и с field, то есть field тоже должен быть маленькими буквами назван так, класс, чтобы это было каким-то breaking changes. +1589.76 1595.92 "Игорь Лабутин" Нет, в field как раз необязательно, у тебя в field может быть private поле, названное уже field, и всё. +1595.92 1598.84 "Анатолий Кулаков" А, private поле, ну да, private поле может быть. +1598.84 1616.72 "Анатолий Кулаков" Ну вот, да, мне просто хочется сделать небольшую заметку, что если вам вдруг почему-то режется лук, когда мы говорим, что breaking changes возможны, то вот подумайте, что если бы Microsoft не пошёл на breaking changes, то у вас никогда бы не было слова var, потому что var — это реально мог такой класс существовать. +1617.04 1637.24 "Анатолий Кулаков" Но если подумать разумно, то вероятность этого очень-очень мала, и вот ради парочки извращенцев в мире, у кого такое могло бы быть, как бы не развивать полностью язык, это ещё хуже решение, чем вот такими людьми там или проектами такими пренебречь немножко или как-нибудь там компиляторам помочь им проапдейтиться или ещё что-то. +1637.24 1641.60 "Анатолий Кулаков" То есть breaking changes нужны, без них никуда не денешься, ну естественно в каких-то разумных пределах. +1641.60 1642.60 "Игорь Лабутин" Ну вот. +1642.60 1661.20 "Игорь Лабутин" Так вот, когда вводили var, то было принято следующее решение, что var означает «выведи, пожалуйста, тип этой переменной автоматически только в том случае, если нет в скоупе, в том месте, где вы написали var, класса под названием var, видимо». +1661.20 1696.08 "Игорь Лабутин" И как пишет Мэттс у себя в статье выше, если вы помните, там когда только вводили var, были всякие споры, да, там типа var или не var, использовать var или использовать var только там, где тип явно виден из правой части, ну короче там даже в райдере есть, или в шерпе такие настройки типа, да, когда автоконвертить в var, то многие, кто были абсолютно против вара, делали простую штуку, они заводили какой-нибудь утилитный, в утилитном пакете, который включается во все там ваши проекты, компании, класс под названием var маленькими буквами и всё, у вас везде var не работает. +1696.08 1697.08 "Игорь Лабутин" Вот. +1697.08 1699.72 "Игорь Лабутин" Такая простая как бы штука. +1699.72 1715.08 "Игорь Лабутин" И Мэттс говорит, что это как раз очень плохо, не в смысле тот факт, что заводили такую штуку, а тот факт, что заведение класса где-то далеко в каком-нибудь чёрт знает каком нугете влияет на поведение программы в совершенно несвязанном логическом месте. +1715.08 1718.84 "Игорь Лабутин" Тот факт, что просто эта штука видна в скоупе не означает, что она должна влиять. +1718.84 1719.84 "Игорь Лабутин" Вот. +1719.84 1722.56 "Игорь Лабутин" Ну, тем не менее, в общем, штука есть. +1722.56 1723.56 "Игорь Лабутин" Дальше. +1723.56 1753.24 "Игорь Лабутин" Есть такая фича в C#, называется она, я, кстати, не знаю, как это на русском называется, я её называю дискард, ну по-английскому называется дискарды, это когда вы можете написать одиночное подчёркивание вместо символа, вместо имени переменной, и в этом случае компьюратор будет понимать, что вам вообще не важно, что там, такое часто используют, например, для out-параметров, то есть если у вас есть функция, которую вам нужно вызвать, у неё есть out-параметр, но вам он не нужен, то вы просто туда пишете там out, не знаю, там int подчёркивание, и компьюратор знает, что подчёркивание в принципе как бы можно игнорировать. +1753.24 1754.24 "Игорь Лабутин" Вот. +1754.24 1765.88 "Игорь Лабутин" Но технически, опять же, подчёркивание - это валидное имя переменной, никто никогда не запрещал в C# заводить такое имя переменной, наверное, это опять же странное имя, но почему нет? +1765.88 1767.04 "Игорь Лабутин" Вот. +1767.04 1788.00 "Игорь Лабутин" Поэтому, когда вводили эту фичу, то ввели её, задумайся, с приседаниями следующими, что она будет, вот одиночное подчёркивание будет работать дискардом только в тех случаях, которые синтаксически были невозможны в прошлых версиях C#. +1788.00 1791.08 "Игорь Лабутин" Ну, типа, это в таком случае точно не breaking change. +1791.08 1798.60 "Анатолий Кулаков" То есть, когда ты не мог написать var подчёркивание, потому что тебе нужно было бы раньше указать тип какой-нибудь, да? +1798.60 1812.08 "Игорь Лабутин" Ну, не var, это не var подчёркивание, это int подчёркивание можно тоже, или там string подчёркивание, ну, в смысле, в каком-нибудь таком месте, в каком-нибудь, например, там tuple deconstruction, вот не было их раньше, вот тут появились, и вот тут можно дискарды, а в других местах нельзя. +1812.08 1825.52 "Игорь Лабутин" И более того, если есть хотя бы одно использование в качестве, ну, как бы, обычной переменной, то, опять же, дискардность отменяется, и подчёркивание становится валидной переменной. +1825.52 1847.20 "Игорь Лабутин" Короче, то есть такое ощущение, что ради того, чтобы сделать как можно лучше избежать потенциального breaking change, приходится в компиляторе, скорее всего, генерить огромное количество вот этой лишней логики по проверкам на тему, значит, а вот в каком ли мы месте, в каком мы контексте, в каком ли мы версии языка, вот это всё. +1847.20 1848.20 "Игорь Лабутин" Короче, сложно. +1848.20 1856.16 "Анатолий Кулаков" Ну, и сам язык это делает некрасивым, неконсистентным, неудобным, сложным для объяснения, сложным для понимания, тебе надо учитывать какие-то неявные контексты. +1856.16 1860.08 "Анатолий Кулаков" Ну, по-разному, по-разному, мне кажется, вот здесь надо жёстче. +1860.08 1957.00 "Игорь Лабутин" Да, и поэтому следующий как раз раздел – это про то, что, окей, breaking change кажется, что нужны, но breaking нужно делать так, чтобы вся команда, ну, короче, это не должно быть просто так, что типа, ой, я придумал новую фичу, кажется, на breaking, окей, у нас есть алгоритм, как мы будем работать с этим breaking change, ну, технически, да, там, кейнтворнинг, там ещё что-то, поэтому делаем спокойно и не паримся, нет, всё-таки надо минимизировать количество breaking change и делать их максимально безопасными, да, так скажем, и поэтому вот Мэдс предлагает в это ищу, и там дальше есть какое-то обсуждение, я не знаю, не дочитал там какое-то огромное обсуждение, но кажется, что они плюс-минус пришли к следующим критериям того, даже не критериям, а каким-то, ну, набору соображений, не знаю, лозунги, наверное, неправильное слово, как подходить к вопросу, нужно ли и как, если нужно делать этот самый breaking change, то есть, во-первых, это должно быть достаточно редко и с прям вот очевидными преимуществами для потенциальных пользователей, то есть, если действительно у нас есть какая-то старая фича C#, которая, ну, логически неудобна, а мы можем придумать новую, удобную и она точно будет полезна большинству пользователей C#, тогда есть смысл делать, если кому-то там, не знаю, трём человеком хочется какую-нибудь странную фичу в C# и остальные её никогда не будут использовать, но это breaking change, нет, тогда не будем делать. +1957.00 1986.96 "Игорь Лабутин" Дальше, даже если это breaking change, то технически, как ты раньше говорил, в адекватном, в среднестатистическом C# коде, скорее всего, breaking change не будет, ну, мало кто объявляет классы с именем var маленькой буквы, или мало кто поля объявляет с полем field, ну, обычно всё-таки чуть, в смысле, с названием field, обычно чуть более говорящие названия, да, у полей, то есть в реальном коде, скорее всего, breaking change не будет. +1986.96 2012.48 "Игорь Лабутин" Дальше, каждый конкретный breaking change должен быть объяснён соответствующими диагностическими месседжами, то есть не просто про то, что типа, а, чувак, ты использовал новую версию компилятора, может у тебя что-то сломается, ну, может быть это будет про слово field, а прям конкретно в нужном месте, вот здесь вот подчеркивается какое-нибудь использование слова field, да, и говорится, вот тут у тебя сломается так-то, вот. +2012.48 2065.44 "Игорь Лабутин" И последнее четвёртое, для каждого такого случая должен быть хороший дефолтный фикс, который можно применить в EDE-шке, грубо говоря, да, там типа, ну, родственники, да, условно говоря, аналайзеры и фикс к нему, который будет а) простой, то есть не потребует переписывания половины проекта, б) железно работающий, то есть не то, что он там типа в большинстве случаев починит, но 50 на 50, кто-то может ещё сломать, вот, и полностью автоматизируемый, то есть типа, а, и самое главное, я забыл, он должен как это, сохранять смысл кода, то есть, грубо говоря, значит, вы должны иметь возможность каким-то образом поймать эти варнинги, я сейчас объясню каким, после чего, посмотрев на них, сказать, ага, понятно, сказать, применить фикс ко всему solution и быть уверенным, что после этого ваш solution нормально будет работать. +2065.44 2070.96 "Анатолий Кулаков" Ну, типа какой-нибудь migrate процесс запустить и замигрировать на новую версию C#. +2070.96 2079.72 "Игорь Лабутин" Ну, типа такого, там скорее должно быть case by case, в смысле по каждому из breaking changes, вы должны посмотреть, понять, ага, может быть, что-то руками самому поправить. +2079.72 2086.36 "Игорь Лабутин" О, блин, кто у нас называл класс, слово var, давайте перепишем, вот, либо просто автоматически что-то сделать. +2086.36 2103.04 "Игорь Лабутин" Вот, и вот как раз-таки на примере Филда, он говорит, что типа, ага, давайте примерим эту штуку к Филду, вот эти принципы, да, как бы, есть ли у нас явная, так сказать, польза для пользователей. +2103.04 2116.72 "Игорь Лабутин" Ну, как бы, да, есть, в том смысле, что это одна из, она это, наверное, не самая высоко залайканная фича в гитаре PC#, но довольно высоко, то есть, есть такая просьба. +2116.72 2128.92 "Игорь Лабутин" Ну, и она звучит логично, имея value, имеет еще и field, но все хорошо с точки зрения, так сказать, adoption от community, все будут, скорее всего, рады. +2128.92 2159.16 "Игорь Лабутин" Второе, будет ли тот факт, как бы, будет ли соблюдаться тот факт, что реальный breaking change будет действительно встречаться редко в реальном коде, и да, таки будет, потому что для того, чтобы это было breaking change, добавление филда ключевого там слова или какого-то специального слова внутри сеттера или геттера для property будет breaking change, только если внутри такого геттера или сеттера есть доступ к чему-либо под названием field маленькими буквами. +2159.16 2162.70 "Игорь Лабутин" Ну, что это, скорее всего, означает private поле. +2162.70 2165.72 "Игорь Лабутин" Как я сказал, вряд ли вы называете private поля просто словом field. +2165.72 2169.48 "Игорь Лабутин" Я не могу придумать, зачем, но технически такое возможно. +2169.48 2170.48 "Игорь Лабутин" Дальше. +2170.48 2173.96 "Анатолий Кулаков" В этой ситуации, надо признать, может встретиться гораздо чаще, чем в R-классе. +2173.96 2185.24 "Игорь Лабутин" Ну, я согласен, какой-нибудь там, не знаю, опертка над чем-нибудь, где у тебя единственное поле, но я все равно как-то не думаю, что это действительно часто. +2185.24 2186.24 "Игорь Лабутин" Не думаю. +2186.24 2190.88 "Игорь Лабутин" Это чаще, чем в R, конечно, может быть, но все равно абсолютный процент очень мало. +2190.88 2200.04 "Анатолий Кулаков" Ну вот смотри, можно, например, привести пример, это недалеко ушло от поля под названием value, а поле под названием value применяется много где, в том числе и самим Microsoft. +2200.04 2211.60 "Анатолий Кулаков" Вспомним, например, класс Nullable, то есть структуру Nullable, у которой есть field value, допустим, или там, по моему, гуйда там какой-то value есть, или урла, ну то есть, или options. +2211.60 2215.40 "Анатолий Кулаков" Ну то есть, есть много классов, у которых есть поле value от самого Microsoft. +2215.40 2220.00 "Анатолий Кулаков" Но кажется, что поле field недалеко ушло от такого названия. +2220.00 2226.76 "Игорь Лабутин" Все верно, я согласен, возможно, действительно так, вопрос, но тебе нужно не только поле field, но тебе еще нужна пропертя. +2226.76 2245.12 "Игорь Лабутин" То есть тебе нужен класс, у которого есть внутреннее поле, плюс поверх него есть пропертя, которая внутри доступается к этому полю, ну, наверное, есть такие, но, короче, Microsoft, возможно, опять же, они же не просто так считают это из воздуха, они как-то явно это, не знаю, ищут по кодовой базе GitHub, например. +2245.12 2250.40 "Игорь Лабутин" Непонятно, насколько она репрезентативна, но думаю, что для некоторых… У них просто выбора нет +2250.40 2251.40 "Анатолий Кулаков" особо. +2251.40 2252.40 "Игорь Лабутин" Ну да. +2252.40 2259.92 "Игорь Лабутин" Дальше, с точки зрения диагностики, тут тоже все четко, вот там, где ты использовал field, в этом месте его можно подчеркнуть и сказать, вот тут будет breaking change. +2259.92 2267.76 "Игорь Лабутин" И дефолтный фикс тоже довольно простой, вы просто меняем это на this.field и все, и у тебя все продолжает работать. +2267.76 2273.44 "Игорь Лабутин" То есть тут без вариантов, все хорошо, все нормально. +2273.44 2276.44 "Игорь Лабутин" Как, собственно, с этим будут жить? +2276.44 2284.20 "Игорь Лабутин" Мы вот про это уже когда-то говорили, теперь это оформлено в виде уже вот полноценного такого issue, так сказать, в письменном виде, нормально зафиксировано. +2284.20 2293.56 "Игорь Лабутин" Смотрите, значит, допустим, мы в новой версии C# что-то делаем breaking, да, вот сейчас выйдет у нас новый C#. +2293.56 2299.52 "Игорь Лабутин" Ну сейчас, больше, чем через полгода, мы в нем сделаем breaking change. +2299.52 2309.56 "Игорь Лабутин" Компилятор версии новый, когда он компилирует для любой версии старее, чем новая, ну то есть выйдет у нас какой сейчас, тринадцатый будет, да? +2309.56 2312.40 "Игорь Лабутин" Я же ничего не путаю, или я уже запутался в числах? +2312.40 2313.40 "Игорь Лабутин" Или тринадцатый вышел? +2313.40 2314.40 "Анатолий Кулаков" Давай. +2314.40 2315.40 "Анатолий Кулаков" Ну следующее, короче. +2315.40 2316.40 "Игорь Лабутин" Не это самое, а это самое. +2316.40 2319.64 "Игорь Лабутин" VNEXT, давай, не будем с числами, что-то я уже путаюсь в числах. +2319.64 2328.60 "Игорь Лабутин" Короче, выйдет VNEXT, а мы берем, в общем, если мы компилируем под любую версию старше, чем VNEXT, то будет ворнинг в коде. +2328.60 2330.60 "Игорь Лабутин" То вот тут будет все плохо. +2330.60 2331.60 "Игорь Лабутин" Вот. +2331.60 2342.92 "Игорь Лабутин" В ворнинге будет, соответственно, тот самый message, который там из критерия номер три выше, да, будет suggested fix, который, соответственно, из критерия номер четыре. +2342.92 2345.48 "Игорь Лабутин" Все, в общем, по-моему, все идеально. +2345.48 2350.46 "Игорь Лабутин" И всякие DE-шки, всякие миграторы должны все эти фиксы, конечно же, предлагать. +2350.46 2372.14 "Игорь Лабутин" А теперь вопрос, кто, ну как бы, такая стратегия не гарантирует того, что про этот breaking change узнают все, потому что многие просто апгрейдят, ну, ты типа апгрейдишься до последнего, ты апгрейдишь SDK, тут же апгрейдишь target, и типа все хорошо. +2372.14 2381.26 "Игорь Лабутин" Но поскольку версия языка, под которой компилируется, определяется таргетом, то не будет ситуации, когда весь шаро-компилятор компилирует под старую версию языка. +2381.26 2382.90 "Игорь Лабутин" Это пока открытый вопрос. +2382.90 2385.62 "Игорь Лабутин" Что с этим делать? +2385.62 2389.78 "Игорь Лабутин" Ну, про него чуть-чуть дальше, может быть, еще скажу. +2389.78 2393.50 "Игорь Лабутин" Теперь смотрите, дальше Мэттс говорит интересную штуку. +2393.50 2419.06 "Игорь Лабутин" На самом деле, если у вас есть код, он компилировался в старой версии компилятора, работал, у вас там стоит warnings as errors, вот это все, и вы добавляете новые ворнинги на существующий код, то само по себе это вообще, так говорят, тоже breaking change, то есть борясь с breaking change на уровне языка, мы вносим breaking change на уровне билда. +2419.06 2421.30 "Игорь Лабутин" То есть у вас проект собирался, теперь перестал. +2421.30 2429.46 "Игорь Лабутин" Да, вы, конечно, переехали на новый, не знаю, на новый таргет, но тем не менее, как бы тоже breaking change. +2429.46 2449.46 "Игорь Лабутин" Но здесь Мэттс говорит следующее, что, во-первых, мы уменьшаем количество этих ворнингов, уменьшаем точнее количество мест и раз, когда это может встретиться, ну типа раз в год, вот это может случиться, вот когда мы SDK проапгрейдили, тогда случилось, поэтому это будет редко. +2449.46 2460.42 "Игорь Лабутин" Второе, у компилятора будет специальный флаг, называется выключить нахрен все breaking change ворнинги, вот эти все специальные ворнинги, конкретно про breaking change будет специальный флаг, который вы говорите, вот их конкретно выключи, остальные не оставь, а эти выключим. +2460.42 2461.42 "Игорь Лабутин" Почему? +2461.42 2485.10 "Игорь Лабутин" Потому что, во-первых, у вас могут быть какие-то там легаси проекты, в которых вы знаете, что вы никогда ничего не будете фиксить, и вам неинтересно видеть эти ворнинги, ну то есть вы апгрейдите SDK, но вы не собираетесь обновлять target framework на них, это как раз тот кейс, когда ворнинги вам нужно показать, но вы знаете, что вы не будете обновлять target framework у этих проектов, поэтому ворнинги можно выключить. +2485.10 2505.82 "Игорь Лабутин" И второе, на самом деле, как говорит Мэттс, в принципе на билд-серверах эти ворнинги тоже по идее не нужны, потому что эти ворнинги то, с чем может программист что-то сделать, поэтому они нужны при билде вашем локальном, чтобы вы их видели, а на билд-сервере, ну как бы, пока оно собирается под старый target, там все работает по старому, они не нужны. +2505.82 2515.90 "Анатолий Кулаков" Ну если бы только локально, они могли бы сделать это просто отдельной командой, типа check for migrate, vnext или что-нибудь в этом духе, ну тогда никакого смысла их бы не было в компи засовывать. +2515.90 2519.98 "Анатолий Кулаков" Никто не будет запускать отдельную команду, ну ты что. +2519.98 2525.66 "Анатолий Кулаков" Ну опять же, Visual Studio будет, если мы говорим только про локально, вот пожалуйста, Visual Studio будет запускать эту команду. +2525.66 2528.86 "Анатолий Кулаков" А те, кто умные, те руками могут и сами определенно раз в месяц запускать. +2528.86 2530.94 "Игорь Лабутин" Ну в общем, пока принято. +2530.94 2539.22 "Анатолий Кулаков" Мне кажется, что как раз-таки наоборот, на CI, если у тебя будет CI падать с этими ворнингами, с этими break-in-changes, то это будет хороший показатель. +2539.22 2542.22 "Анатолий Кулаков" Ты увидишь, ты точно увидишь, ты это не пропустишь никогда. +2542.22 2549.86 "Анатолий Кулаков" Ну и если ты хочешь подавить, пожалуйста, присылаешь флажочек, который говорит, что не надо мне падать на break-in-changes, и он проходит дальше. +2549.86 2553.06 "Анатолий Кулаков" То есть это не то, чтобы сильно ухудшает работоспособность. +2553.06 2555.82 "Игорь Лабутин" Я так понимаю, что они так и будут делать. +2555.82 2559.62 "Игорь Лабутин" То есть не так, что компилятор будет понимать, что он в CI, и тут же глушить. +2559.62 2560.62 "Игорь Лабутин" Нет. +2560.62 2567.10 "Игорь Лабутин" Это скорее, что ты типа должен в своем CI этот флажок написать явно. +2567.10 2568.10 "Игорь Лабутин" Хочешь, пиши, хочешь, не пиши. +2568.10 2570.94 "Игорь Лабутин" Ну вот это хорошо, вот это нормальный в принципе выбор. +2570.94 2575.42 "Игорь Лабутин" И последний момент тоже довольно важный. +2575.42 2588.74 "Игорь Лабутин" Как вы знаете, у нас, как вот мы сейчас только что говорили, точнее, компилятор, когда он компилирует ваш C# код, он знает target language level, так называемый, или target версию языка. +2588.74 2591.42 "Игорь Лабутин" Обычно она определяется таргетом вашего проекта. +2591.42 2603.98 "Игорь Лабутин" То есть если вы указываете там какой-нибудь .NET, не знаю, 6, возьмется тот C#, который был релизный на момент .NET 6 в качестве таргетного, то есть компилятор будет считать, что вы пишете на том C#. +2603.98 2608.46 "Игорь Лабутин" Если вы таргетите .NET какой-нибудь 8, вот возьмется последний. +2608.46 2612.66 "Игорь Лабутин" Но есть две специальных версии. +2612.66 2616.98 "Игорь Лабутин" Версия на специальный номер 1 – это latest. +2616.98 2635.34 "Игорь Лабутин" Вы можете в C++ указать lang version, по-моему, называется пропертя, указать туда latest, ну и да, естественно, вы можете указать любую другую фиксированную, то есть вы даже в таргете .NET 6 можете сказать lang version, вот какая сейчас у нас текущая, и он будет компилить ее под текущую нормальную, но можно указать latest. +2635.34 2639.86 "Игорь Лабутин" И тогда он берет, типа, максимально новую, которую я могу. +2639.86 2648.50 "Игорь Лабутин" И понятно, что никаких breaking, change warning тогда не будет, потому что у вас нету кейса, когда новый компилятор компилирует под старую версию языка. +2648.50 2662.10 "Игорь Лабутин" И здесь медс говорит, что, скорее всего, версию под названием latest уберут, ее будет указывать нельзя, ну, точнее, указывать будет можно, но это будет warning. +2662.10 2667.62 "Анатолий Кулаков" Блин, ну это вообще беспредел, это моя самая любимая опция была. +2667.62 2671.98 "Анатолий Кулаков" Так не хотелось вот с этими старперами жить, которые раз в 4 года обновляют эту версию. +2671.98 2674.50 "Анатолий Кулаков" Я всегда под latest сижу, мне все нравится. +2674.50 2676.70 "Игорь Лабутин" Ну вот, пока не сломали. +2676.70 2687.82 "Игорь Лабутин" Вот, и для тебя будет специальная опция, которая сможет, так сказать, засопросить этот warning про то, что не надо ворнинги про latest. +2687.82 2692.94 "Игорь Лабутин" Ну то есть у них убрать в английском это у них называется retire и в кавычках. +2692.94 2699.74 "Игорь Лабутин" То есть я так понимаю, что типа они не будут промоутить ее использование, но прям убирать-убирать совсем ее не планируют. +2699.74 2703.14 "Игорь Лабутин" То есть она останется, но будет всегда под warning, который можно всегда убрать. +2703.14 2705.94 "Анатолий Кулаков" Опять какие-то костыли непонятные, блин. +2705.94 2708.74 "Игорь Лабутин" Вот да, смотри, а мы обсуждаем breaking change, да? +2708.74 2709.74 "Игорь Лабутин" Вот тебе breaking change. +2709.74 2728.18 "Анатолий Кулаков" Ну подожди, а давай вот вернемся к той идее, что если б у нас все-таки была бы отдельная команда, которая говорит товарищ компилятор, проверь мне вот этот мой код, я собираюсь там перейти с дотнета 6 на 7, проверь мой код и выдай мне ворнинги, на которые я должен обратить внимание. +2728.18 2730.10 "Анатолий Кулаков" Ну это же решило бы абсолютно вообще все проблемы. +2730.10 2736.58 "Анатолий Кулаков" Не надо было бы запрещать там latest, не надо было бы там какие-то флажки, не надо какие-то дизейблы придумать, просто, блин, сделайте отдельную команду и все. +2736.58 2741.62 "Анатолий Кулаков" И как часто ее запускать, то я сам решу, в конце до конца у меня есть MCI-настрой, который каждую ночь ее будет запускать и проверять что-то. +2741.62 2742.62 "Игорь Лабутин" Ты такой умный. +2742.62 2748.70 "Игорь Лабутин" Настроишь, и ты точно знаешь, с какой версии языка ты переходишь на какую версию языка. +2748.70 2759.90 "Игорь Лабутин" Большинство, кажется, народу, Microsoft видео все-таки ориентируется на большинство, они тупо сидят в Visual Studio, жмут кнопку publish, и у них все работает. +2759.90 2766.74 "Игорь Лабутин" И вот как бы для их кейса никто не будет запускать все эти тулы, там CI-настроить, вот это все. +2766.74 2769.58 "Игорь Лабутин" Но при этом их код тоже нельзя ломать. +2769.58 2780.74 "Анатолий Кулаков" Просто мы придем постепенно с таким путем, мы придем к тому, что у нас в дотнет-билде будет интегрирован какой-нибудь дотнет-мигрейт, который будет знать, и делать, и проверять, и все на свете. +2780.74 2786.82 "Анатолий Кулаков" У тебя билд будет или медленный, или сложный, или то другое вместе. +2786.82 2790.50 "Игорь Лабутин" Не знаю, это, может быть, надо смотреть. +2790.50 2797.74 "Игорь Лабутин" То есть, опять же, надо понимать, что это все не окончательно финальное решение, которое с нами теперь на десятки лет. +2797.74 2845.66 "Игорь Лабутин" Это некоторый пропозал, который сейчас у МЭДСа родился и сформировался в некоторую уже документированную, структурированную штуку, которую они, скорее всего, собственно говоря, которую они попробуют на том самом филде, вот этот филд аксессор, который внутри пропертий, они его собираются сделать в следующем C# 13, и на нем отработать эту штуку, и посмотреть, какой будет фидбэк от комьюнити, что все остальные скажут, какой фидбэк будет не только от комьюнити, надо понимать, что фидбэк от комьюнити будет это, как сказать, народ типа тебя, который понимает, что они делают, в большинстве своих, могут настроить себя и все остальное, и так далее. +2845.66 2867.50 "Игорь Лабутин" Возможно, будет фидбэк от каких-нибудь там first, second, third party, кастомеров, где какие-то, возможно, более бизнес там, ну такие, как интерпрайс-программисты сидят, которые только вижу в студии что-то делают, условно говоря, в таком духе, то есть и вероятно к C# 14 следующей версии может что-то еще изменится, посмотрим, пока не знаю. +2867.74 2891.50 "Игорь Лабутин" Вот, еще последний момент, то, что я недорассказал, помимо лейтеста есть еще специальная версия под названием превью, вот, с ней делать ничего не хотят, если ты такой крутой, что ты указал превью в своем C#, ты, значит, сам лучше Майкрософта знаешь, какие breaking changes могут быть в своем коде, тебя вообще ни о чем предупреждать не будут, вот такие вот дела нас ждут в C#. +2891.50 2906.46 "Анатолий Кулаков" Ну, хорошо, хорошо, вроде звучит вполне разумно, но мне нравится сама ситуация, что наконец-то начали съезжать с этой пьяной точки, когда блюли всякие различные совместимости просто без оглядки, как бы обязательно-обязательно совместимость. +2906.46 2916.86 "Анатолий Кулаков" Наверное, в каких-то вещах это хорошо, но не здесь, ну, вот, например, совместимость в Windows мне нравится, да, когда мы можем на последней винде запустить там какой-нибудь DOS и проиграть в старинные игры, которые делались еще под MS-DOS. +2916.86 2927.70 "Анатолий Кулаков" Вот это нормально, ну, потому что действительно очень много кейсов в мире существует, когда непонятно, под чем и кто сейчас сидит, и что и кто сейчас запускает. +2927.70 2938.82 "Анатолий Кулаков" Но когда мы разговариваем с программистами, у которых кажется, что должно охватить ума, как бы запустить пару команд и посмотреть пару отчетов, то здесь, мне кажется, уже какая-то избыточная паранойя пошла. +2938.82 2942.66 "Игорь Лабутин" Ну, может быть, они что-то понимают о своих заказчиках? +2942.66 2946.74 "Анатолий Кулаков" Ну, может быть, может быть, я в это искренне верю. +2946.74 2954.98 "Анатолий Кулаков" В общем, хорошая тенденция на то, что мы начали об этом думать, начали каким-то образом ломать breaking changes, в общем, и будем надеяться, что мы дальше пойдем по этой дорожке. +2954.98 2970.78 "Анатолий Кулаков" Я уверен, что мы сильно не углубимся, как бы не будет у нас разницы, как между питонами, но вот такие мелкие вещи, как классы вар с маленькой буквы, их надо истреблять, и под них не надо подстраиваться. +2970.78 2977.78 "Игорь Лабутин" Ну, будем надеяться, посмотрим, что будет, а у нас тем временем вышел релиз Visual Studio. +2977.78 2992.50 "Анатолий Кулаков" Visual Studio версия 20.22.17.9, когда они уже нормальные версии начнут давать, а также вышел превью, соответственно, 17.10, и вот эти два экземпляра, два анонса мы сегодня с вами и рассмотрим. +2992.50 2999.50 "Анатолий Кулаков" Прежде всего, конечно же, в каждом релизе выходит что-то про копайлот, GitHub-копайлот. +2999.50 3007.02 "Анатолий Кулаков" Нужно напомнить, что для этого вам нужна отдельная платная подписка на GitHub-копайлот, иначе вы ничего этого не увидите. +3007.02 3033.18 "Анатолий Кулаков" И прежде всего, Visual Studio уже в релизе научилась генерировать commit-месседжи, т.е. у вас есть какой-то нобор файлов, которые вы поменяли, и самое сложное – это, конечно же, не реализовать фичу, не протестировать ее, не написать на нее какой-то технический анализ, а самое сложное – это придумать commit-месседж к этой фиче, когда вы пытаетесь запустить ее вашим коллегам на pull-request или в Git-репозиторий, или куда-то туда. +3033.18 3041.98 "Анатолий Кулаков" И вот теперь вам поможет кнопочка, которая запустит GitHub-копайлот и сгенерит вам, проанализирует все ваши изменения и сгенерит вам описание. +3041.98 3051.58 "Анатолий Кулаков" Нужно сказать, что описание – это не просто какой-то однострочник, который у вас там будет появляться, это такой полноценный, блин, прямо вот статья, прямо анонс. +3051.58 3055.34 "Анатолий Кулаков" Т.е. он реально под каждую фичу расписывает там чуть ли не по абзацу. +3055.34 3059.46 "Анатолий Кулаков" Я не знаю, настраивается это где-то или не настраивается, но прямо это хороший документ получается. +3059.46 3060.46 "Игорь Лабутин" Так вот так вот нужно. +3060.46 3070.82 "Игорь Лабутин" Они может такое на этих самых перейдут, на своих анонсах превью, что закинул им набор коммитов, как вот в EF Core там сейчас, и все, и вот тебе готовая статья. +3070.82 3082.38 "Анатолий Кулаков" Ну может быть, может быть, но там, мне кажется, нужно 10 уровней и потом еще самурайзеров вставить, строить, потому что если он там для трех файлов выдает абзацы текста, то у Микрософта этих файлов там тысячи летают. +3082.38 3086.26 "Анатолий Кулаков" Поэтому нужен какой-то самурайзер очень умный, который все это способен объединить. +3086.26 3090.46 "Игорь Лабутин" И обратно сложить, а потом еще выделить основные тезисы для нас. +3090.46 3096.22 "Анатолий Кулаков" Да, отдельно там для разработчиков, для маркетологов, для анонсеров, для конференций и так далее. +3096.22 3100.02 "Игорь Лабутин" Ладно, да, надо еще допиливать Микрософт, Капайлот, окей. +3100.02 3108.38 "Анатолий Кулаков" Вот, еще поддержаны так называемые слэш-команды, это когда вы у Капайлота просите какие-то стандартные для программиста вещи. +3108.38 3115.78 "Анатолий Кулаков" Ну, например, пофикси мне этот код, или напиши документацию к этому методу на основании его содержимого, или объясни вообще, что этот метод делает. +3115.78 3120.22 "Анатолий Кулаков" В общем, есть маленькие команды, которые с помощью слэша вызываются очень быстро и удобно. +3120.22 3138.46 "Анатолий Кулаков" Еще одна прикольная штучка – это инлайн-чат, это когда вам не нужно отвлекаться на какое-то левое окошко, вы прямо в коде пишите, у вас прямо в коде всплывает какое-то окошко, куда можно повзаимодействовать с Капайлотом, дать ему какие-то команды, попросить отрефакторить текущий код, где сейчас сидит курсор. +3138.46 3142.14 "Анатолий Кулаков" В общем, это все сделать удобно и меньше отвлекаться. +3142.14 3148.42 "Анатолий Кулаков" В общем, это кажется, что довольно полезная штука будет и продуктивность она должна хорошо улучшать. +3148.42 3149.42 "Анатолий Кулаков" Про Visual Studio. +3149.42 3154.06 "Анатолий Кулаков" Также у нас есть оптимизации и улучшения в Memory2Log. +3154.06 3166.10 "Анатолий Кулаков" Прежде всего, это Event Handler Leak поисковик, т.е. у вас теперь в Memory Management вкладочке есть такая специальная опция – это найти все Event Handler Leaks. +3166.10 3174.02 "Анатолий Кулаков" Это один из самых популярных ликов, которые существуют, т.е. утечек памяти, когда вы подписываетесь на какие-то события и забываете про них отписаться. +3174.02 3179.70 "Анатолий Кулаков" Особенно, если мы говорим про UI-разработку на десктопах, винформах, DPF-ах и прочем. +3179.70 3181.46 "Анатолий Кулаков" Там эта проблема очень актуальна. +3181.46 3189.10 "Анатолий Кулаков" И также прорабатывается HotPath ToRoot, это показывается вам самые горячие точки для оптимизации. +3189.10 3204.98 "Анатолий Кулаков" Т.е. если вы захотели прооптимизировать перформанс в вашей программе, то самое лучшее, что вы можете сделать, это посмотреть на вот этот HotPath, который вам посоветует, опять же Memory2Log, и попытаться его каким-то образом простимулировать, прооптимизировать. +3204.98 3209.50 "Анатолий Кулаков" И это даст вам самый лучший прирост в вашей программе, который вы могли бы только придумать. +3209.50 3212.22 "Анатолий Кулаков" Еще из нововведений. +3212.22 3217.78 "Анатолий Кулаков" Сделали меньше модальных окошек, в частности теперь дебаггинг визуалайзеры не модальные. +3217.78 3226.10 "Анатолий Кулаков" Это те окошки, которые вы можете, например, в дебаг в очаг открыть, для того, чтобы посмотреть более подробно какой-то объект или что-то еще. +3226.10 3232.40 "Анатолий Кулаков" В общем, раньше каждое окошко можно было открыть только в одном экземпляре, оно полностью перекрывало абсолютно всю работу. +3232.40 3239.50 "Анатолий Кулаков" Сейчас же их можно пооткрывать несколько штучек и в это же время продолжать редактировать код, что очень удобно. +3239.50 3242.46 "Анатолий Кулаков" Сделана улучшая поддержка Multiproject Configuration. +3242.46 3253.46 "Анатолий Кулаков" Это когда вы можете для запуска ваших нескольких проектов, то есть, допустим, у вас есть Solution, и в Solution есть несколько проектов, допустим, несколько микросервисов, которые друг с другом взаимодействуют. +3253.46 3260.30 "Анатолий Кулаков" Вы можете настроить Visual Studio так, чтобы при нажатии F5 у вас поднималось сразу, запускалось сразу несколько этих проектов. +3260.30 3262.62 "Анатолий Кулаков" И вы, естественно, оттачались к ним сразу. +3262.62 3266.74 "Анатолий Кулаков" Это было, в принципе, всегда, насколько я помню, в Visual Studio. +3266.74 3275.42 "Анатолий Кулаков" А вот теперь в новой версии вы можете сохранить вот эти способы запуска в определенный файлик, в определенный профиль. +3275.42 3276.42 "Анатолий Кулаков" И эти профили менять. +3276.42 3286.86 "Анатолий Кулаков" Ну, например, если у вас очень большой Solution, то у вас может быть профиль с сервисами для бухгалтерии, профиль с сервисами для продажников, профиль с сервисами для инфраструктурного обслуживания. +3286.86 3294.22 "Анатолий Кулаков" И вот вы между ними можете переключаться и запускать не все сразу, а определенный набор запускабельных сервисов. +3294.22 3296.18 "Анатолий Кулаков" Тоже вполне удобно. +3296.18 3303.38 "Анатолий Кулаков" У Razor файлов появилась возможность делать мультитаргет фреймворк, поддержку мультитаргет фреймворков. +3303.38 3306.06 "Анатолий Кулаков" То есть можно комбинировать их в мультитаргеты теперь. +3306.06 3314.06 "Анатолий Кулаков" У Razor scaffold'ов вышла поддержка, соответственно, scaffold'инга для Entity Framework. +3314.06 3321.06 "Анатолий Кулаков" То есть, например, вы можете сказать, у меня вот стандартная сущность есть, сгенерикаю для нее стандартные Blazor компоненты. +3321.06 3323.46 "Анатолий Кулаков" И у вас магическим образом сгенерится UI'ка. +3323.46 3350.90 "Анатолий Кулаков" В этой UI'ке может сгенерироваться табличка, в этой табличке будут стандартные крут-операции, которые за вас уже будут удалять все, апдейтить, читать и прочие такие стандартные мелочи, которые как бы помогают на примитивных операциях, когда вы какие-то справочники делаете, то одной кнопкой можно для справочников нагенерить и обвязку вокруг Entity Framework'а и обвязку вокруг Blazor'а, и контроллеры вам там еще сами сгенерятся и мапперы сами построятся. +3350.90 3364.54 "Анатолий Кулаков" Здесь можно ответить, что данный scaffold'инг использует Static Server Site Rendering, который был недавно зарелизан, то есть все это делается довольно оптимально, красиво и с поддержкой современных технологий. +3364.54 3370.62 "Анатолий Кулаков" Еще классная штука – это улучшенная поддержка экосистемы. +3370.62 3373.62 "Анатолий Кулаков" Так, под этим мудрым заголовком подразумевается довольно примитивная вещь. +3373.62 3437.58 "Анатолий Кулаков" Вот у вас очень часто бывает в компании такая штука как расширение к студии, и эти расширения вам нужны для какого-то конкретного проекта, ну может быть какие-то там ростлин анализаторы или какой-нибудь рисовальщик графиков, или какой-нибудь компилятор ресурсов, или оптимизатор картинок, или оптимизатор css файлов, в общем плагинов в Visual Studio очень много, и часто бывает так, что какой-то конкретный проект от этих плагинов грубо говоря зависит, то есть чтобы вам нормально собрать что-то, вам нужны эти плагины, и вот сделали такую поддержку, что если вы в специальный файлик, который называется VSConfig, добавите описание тех расширений, которые вам нужны для этого проекта, Visual Studio их поймет, то есть при загрузке вашего солюшена, она проанализирует файлик VSConfig, если она найдет там обязательные плагины для этого солюшена, она спросит человека, который создал этот солюшен, а не хочет ли он случайно установить эти плагины, установить эти экстеншены, и если он вдруг случайно захочет, то она их пойдет и установит. +3437.58 3456.10 "Анатолий Кулаков" Это все особенно прекрасно в рамках того, что VSConfig это отдельный файлик, то есть по сути вы его можете зачекинить в репозиторий, выложить в какую-то шару, распространять между членами команды и так далее и тому подобное, то есть это обычный файлик, и распространяется довольно легко. +3456.10 3465.98 "Анатолий Кулаков" И нужно признать, что это была одна из самых запрашиваемых фич для студии, которая только была там в голосовалке. +3465.98 3481.42 "Анатолий Кулаков" И эта фича в принципе сейчас уже есть в какой-то превью-версии, но она все еще находится под активной разработкой, поэтому если вдруг что-то не сработает, не судите строго, но я думаю тем, кому это было нужно, те уже могут смело пробовать. +3481.42 3494.02 "Анатолий Кулаков" Такие нововведения у нас есть в Visual Studio, в принципе она старается не отставать от основного фреймворка, а если судить по чинь-жам, то даже сильно его перегоняет, потому что фреймворк что-то, вообще она запаздывает. +3494.02 3495.02 "Анатолий Кулаков" Поэтому студия молодец. +3495.02 3501.70 "Игорь Лабутин" Да, я как раз хотел сказать, что прям в студии гораздо больше чинь-жам в превью, чем в основном фреймворке. +3501.70 3526.70 "Игорь Лабутин" Ну да ладно, с другой стороны, мне кажется, что, опять же, студия много чего копит по всяким разным своим превьюшкам, зато к релизу выпускает красивые статьи про то, что ах, как вы много всего сделали, поэтому приятно видеть, что инструмент развивается, мне действительно интересно, сколько лет они еще будут держать название 2022, и главное, зачем тогда держать это Visual Studio 2022, пусть оно будет просто 17.9. +3526.70 3531.70 "Анатолий Кулаков" А никакого ishu на гитхабе нету, ну то есть должен был народ поинтересоваться таким же вопросом? +3531.70 3538.26 "Игорь Лабутин" Нет, студия же не на гитхабе живет никак, это полностью closed source, у нее, по-моему, даже никакого репозитория типа там с ishu за меня нету. +3538.26 3539.46 "Анатолий Кулаков" И трекера ничего такого, да? +3539.46 3540.46 "Игорь Лабутин" Нет, нету. +3540.46 3542.06 "Игорь Лабутин" User Voice, помнишь такой? +3542.06 3549.82 "Анатолий Кулаков" Ну да, User Voice помню, но именно вот там эти фичи все и были, ну надо в User Voice завести, типа, чуваки, вы забыли заинкрементировать на 2 года версию. +3549.82 3564.46 "Игорь Лабутин" Ну зачем, нет, ну возможно они будут инкрементировать только в том случае, если там будет какой-то мажорный, не знаю, перепишут на что-нибудь, плюс платформеры сделают, окей, ладно, вы не инкрементируете мажорный, но уберите, ну не знаю, короче, не знаю, 2022 как-то, уже 24-й год, странно. +3564.46 3573.26 "Анатолий Кулаков" Ну да, ну то же самое, 17.9, 17.10 у них есть, они могут просто это убрать, использовать цифру 17 вместо года, зачем тащить, непонятно. +3573.26 3576.50 "Игорь Лабутин" И вообще 17. убрать и просто вижу услуги, 9, 10. +3576.50 3577.50 "Анатолий Кулаков" Да? +3577.50 3583.14 "Анатолий Кулаков" Ну вот как C# там делает, у них уже, 12-й C#, 11-й C#, вполне рабочие. +3583.14 3587.22 "Игорь Лабутин" Там много, номеров можно долго, какая-то я первая была, 2003, да? +3587.22 3588.22 "Игорь Лабутин" А, нет, 98, нет. +3588.22 3594.02 "Анатолий Кулаков" Что-то мне кажется, что я 5-й, или я там не с виду работаю. +3594.02 3600.26 "Игорь Лабутин" Нет, 5.0, 6.0 были, а потом была, по-моему, сразу 2000, вижу в студию.net, 2002, наверное, или 2003, какая-то такая она +3600.26 3601.26 "Анатолий Кулаков" была. +3601.26 3605.50 "Анатолий Кулаков" Так, не пались, а то ты выдаёшь нас, торпёров, давай, и нас там хипстеры тоже должны их слушать. +3605.50 3611.30 "Игорь Лабутин" Вот, и, короче, до 2000-х ещё столько релизов можно сделать, короче, нормально, чисел хватит. +3611.30 3612.30 "Игорь Лабутин" Да-да, прокатит. +3612.30 3613.30 "Игорь Лабутин" На всех. +3613.30 3616.42 "Игорь Лабутин" Если что, потом пропустим, там всё уже забыло, почему 2000. +3616.42 3620.18 "Игорь Лабутин" Короче, к тому моменту можно уже и 2000 называть, все уже не будут знать, что это такое. +3620.18 3622.06 "Игорь Лабутин" Давай дальше, дальше у нас Andrew Locke. +3622.06 3628.14 "Анатолий Кулаков" Да, давай что-нибудь более лёгенькое такое, что-то про новинки, про хардкоры, про оптимизации. +3628.14 3637.34 "Анатолий Кулаков" Andrew Locke решил задаться непростым вопросом, а каким образом вы можете изменить урл, по которому ваш кестрил слушает все входящие запросы? +3637.34 3645.38 "Анатолий Кулаков" Ну, для того, чтобы ISP.NET обрабатывал все запросы и отсылал контроллер, он должен их где-то слушать, на каком-то порту, на каком-то хосту, по какому-то протоколу. +3645.38 3650.02 "Анатолий Кулаков" И вот какие способы есть для того, чтобы изменить этот хост? +3650.02 3657.46 "Игорь Лабутин" Погоди, погоди, погоди, мы такую статью точно обозревали года три назад, давно, короче, где-то благодаря подкасту. +3657.46 3664.82 "Анатолий Кулаков" У Andrew Locke есть такая интересная хобби, он эту статью пишет в каждой новой версии .NET, потому что он находит новые способы запуска. +3664.82 3669.06 "Анатолий Кулаков" И поэтому он не мог себя удержать и выпустил последнюю версию все-таки. +3669.06 3672.66 "Анатолий Кулаков" Как теперь, вот на данный момент это можно и нужно задавать? +3672.66 3673.66 "Анатолий Кулаков" Ну, давай посмотрим. +3673.66 3676.10 "Анатолий Кулаков" Быстренько пробежимся. +3676.10 3685.46 "Анатолий Кулаков" Итак, по дефолту, если вы ничего не настраиваете, просто поставили себе ISP.NET, завели контроллер, нажали F5, то ваше приложение запустится на Localhost 5000. +3685.46 3689.78 "Анатолий Кулаков" Это стандартный порт, который, в принципе, ничем не плох, ничем не хорош. +3689.78 3690.78 "Анатолий Кулаков" Это нормальный дефолт. +3690.78 3697.58 "Анатолий Кулаков" Вы можете поменять это значение, вы можете поменять его, например, изменить порт или указать конкретный IP-адрес. +3697.58 3712.46 "Анатолий Кулаков" Нужно понимать, что если на вашем компьютере установлено несколько сетевых карт или настроено несколько network протоколов, или настроено просто несколько IP-адресов, то вы, может быть, не хотите, чтобы ваш сервис слушал на каждом из них. +3712.46 3717.98 "Анатолий Кулаков" Ну, например, один IP-адрес у вас может уходить в интернет, а другой адрес может уходить в локальную сеть. +3717.98 3722.86 "Анатолий Кулаков" И вы хотите свой веб-сервер настроить только для локальной сети. +3722.86 3727.26 "Анатолий Кулаков" В этом случае вам нужно прибаниться только к IP-адресу локальной сети. +3727.26 3740.42 "Анатолий Кулаков" Ежели вы просто укажете Localhost или там какую-нибудь звездочку, то ISP прибанится ко всем адресам, то есть он будет доступен с любой сети, хоть с интернета, хоть с локальной, хоть с любой другой, к которой к нему можно обратиться. +3740.42 3742.02 "Анатолий Кулаков" И тут немножко поаккуратнее. +3742.02 3745.90 "Анатолий Кулаков" И по дефолту он как раз-таки слушает Localhost 5000. +3745.90 3751.10 "Анатолий Кулаков" Вы можете указать один конкретный адрес, вы можете указать несколько адресов, разделяя их разделителем. +3751.10 3757.78 "Анатолий Кулаков" Опять же, это невозбранно, или можете сказать, что слушай вообще все адреса, которые найдешь на моем локальном хосте. +3757.78 3760.18 "Анатолий Кулаков" Как же теперь их можно поменять? +3760.18 3771.98 "Анатолий Кулаков" Ну, наверное, самое очевидное, хотя, может быть, и не самое очевидное, это использовать специальный метод расширения для веб-аппликейшн-билдера, который называется UseUrls. +3771.98 3786.14 "Анатолий Кулаков" То есть в нашем программ.cs файле мы создаем веб-аппликейшн-билдер, это, наверное, одна из тех строчек, которые все еще не убрали, которые все еще нам доступны, и у этого билдера у нас есть куча свойств для настройки нашего будущего сервиса. +3786.14 3794.26 "Анатолий Кулаков" В частности, есть .webhost.useurls, и туда вы в качестве строки можете передать вот этот URL, по которому вам нужно слушать. +3794.26 3813.18 "Анатолий Кулаков" Другое интересное нововведение, нововведение его ввели в шестом дотнете, почему его раньше не было, никто не знал, и, наверное, все очень сильно хотели, это заключается в том, что вы можете этот URL настроить не только у билдера, но и непосредственно в своем уже конкретном аппликейшне. +3813.18 3822.78 "Анатолий Кулаков" То есть вы билдер позадавали, вызвали метод билд, вам вернулся аппликейшн, и у этого аппликейшна вам все еще есть возможность настроить URL для прослушивания. +3822.78 3829.54 "Анатолий Кулаков" У аппликейшна есть свойство, которое называется .urls, и к нему можно добавить такой же точно URL. +3829.54 3855.90 "Анатолий Кулаков" За сценой этот urls, это свойство, на самом деле ходит к сервер-фичам, то есть это специальный такой классик, который хранит все возможные свойства, которыми обладает текущий сервер, и вытаскивает оттуда специальный сервис, который называется iservice-address-feature, то есть фича, которая поддерживает оповещения, даже не оповещения, поддерживает коллекцию всех сервисных адресов, которые нужно послушать. +3855.90 3861.70 "Анатолий Кулаков" И вот в этот сервис-адрес-фичу оно записывает новый адрес, который вы добавили. +3861.70 3865.34 "Анатолий Кулаков" На самом деле к этой фиче обращается очень много методов. +3865.34 3884.74 "Анатолий Кулаков" В частности, вы, например, можете вызвать app-run, то есть запустить ваш аппликейшн, и в ране есть перегрузка, которая точно так же принимает URL, по которому нужно послушать, по которому нужно запустить кестрил, и этот URL, который принимает в ране, делает абсолютно то же самое. +3884.74 3891.06 "Анатолий Кулаков" Он берет сервис-адрес-фичу и просто-напросто да, этот URL записывает, а эту фичу уже потом потребляет кестрил. +3891.06 3895.08 "Анатолий Кулаков" В общем, поэтому есть несколько endpoint, которые под капотом используют одно и то же. +3895.08 3897.66 "Анатолий Кулаков" В общем, мы их рассматривать не будем, будем считать, что это одно и то же. +3897.66 3898.66 "Анатолий Кулаков" Дальше. +3898.66 3909.58 "Анатолий Кулаков" Для того, чтобы настроить еще этот URL, вы, возможно, захотите воспользоваться стандартным интерфейсом опций, который пришел к нам в ASP.NET и также во весь .NET. +3909.58 3918.78 "Анатолий Кулаков" Опции позволяют вам комбинировать и загружать настройки, конфигурацию из нескольких источников, из нескольких провайдеров опций. +3918.78 3935.38 "Анатолий Кулаков" По умолчанию, Configuration Manager использует в качестве источника для своих настроек Upsettings JSON-файл, а также Upsettings с Environment JSON-файл, то есть, когда вы хотите отдельно для Production, отдельно для Development, отдельно для стейджинга сделать файлики. +3935.38 3938.42 "Анатолий Кулаков" Это тоже в стандартную поставку, в стандартный комплект входит. +3938.42 3947.46 "Анатолий Кулаков" Также он загружает секреты, после этого Environment Variables и в последнюю очередь Command-Line-аргументы, которые перебивают абсолютно все, что было вышесказано. +3947.46 3956.14 "Анатолий Кулаков" В общем, из вот этой всей шарманки, из вот этой всей каши он, соответственно, может вам сгенерить конечные настройки. +3956.14 3961.62 "Анатолий Кулаков" И в любом из этих провайдеров, если он найдет настройку URL, он ее, естественно, затащит. +3961.62 3967.66 "Анатолий Кулаков" Настройка URL может быть с помощью определенного названия, определенного ключа. +3967.66 3972.02 "Анатолий Кулаков" Ключ может называться URLs, может называться ISPnetCoreURLs или .NETURLS. +3972.02 3983.10 "Анатолий Кулаков" А ISPnetCore и .NET по умолчанию отрезаются, как только вы загружаете все ваши конфигурации через Configuration Manager, поэтому они сводятся все все едино к URLs. +3983.10 3996.58 "Анатолий Кулаков" Поэтому очень легко, если вы хотите, допустим, настраивать через переменное окружение, ваш URL, по которому запускается сервачок, вы можете просто выставить переменное средоокружение и после этого запустить приложение. +3996.58 4000.84 "Анатолий Кулаков" И по умолчанию он подхватит переменную, если она названа правильно. +4000.84 4010.40 "Анатолий Кулаков" Дальше, если мы начнем задумываться, что наш сервис принимает в качестве того, что он будет слушать, он принимает URL. +4010.40 4014.42 "Анатолий Кулаков" На самом деле он использует из этого URL не полное подмножество. +4014.42 4023.06 "Анатолий Кулаков" Он может использовать протокол, он может использовать порт, а вот название хоста в этом URL у него довольно ограниченное. +4023.06 4027.18 "Анатолий Кулаков" То есть вы не можете сказать, что я хочу свой сервис запустить на URL Яндекс.Ру, допустим. +4027.18 4031.18 "Анатолий Кулаков" Ну потому что прибавиться к этому интерфейсу вы не сможете. +4031.18 4033.90 "Анатолий Кулаков" Вы сможете прибавиться только то, что у вас есть на локальном хосте. +4033.90 4045.26 "Анатолий Кулаков" И вот чтобы такой диссонанс убрать, недавно было введено новые переменные, новые настройки, которые называются HTTP Port и HTTPS Port. +4045.26 4054.82 "Анатолий Кулаков" То есть вы можете менять, по сути, только порты, но и при изменении этих портов ваш сервер будет слушать на любом IP-адресе. +4054.82 4059.90 "Анатолий Кулаков" То есть он, по сути, прибавится ко всем IP-адресам, и вы будете настраивать только порты. +4059.90 4064.22 "Анатолий Кулаков" Вы можете настроить несколько портиков точно так же, как и с несколькими адресами. +4064.22 4073.58 "Анатолий Кулаков" И начиная с .NET 8, у вас есть переменная SPNet Core HTTP Ports, которую вы можете настраивать. +4073.58 4088.26 "Анатолий Кулаков" Здесь еще нужно сказать, что начиная с .NET 8, по умолчанию во всех официальных .NET Docker images, в Docker images используется эта переменная, и она проставлена в значение 8080. +4088.26 4098.50 "Анатолий Кулаков" Это еще связано с rootless контейнерами, чтобы мы там не бандились на адресах, которые меньше какого-то определенного системного пользователя и так далее. +4098.50 4108.26 "Анатолий Кулаков" В общем, вот эта переменная пригодилась, и каждый из вас, кто использует докер-контейнеры для запуска вашего .NET-приложения, там явно или не явно, эту переменную подкомпотом юзают. +4108.26 4115.54 "Анатолий Кулаков" Еще один способ, как переписать адреса – это, естественно, командная строка. +4115.54 4119.82 "Анатолий Кулаков" Наверное, опять же, тоже, может быть, не для всех очевидный способ. +4119.82 4134.32 "Анатолий Кулаков" Вы можете запустить ваше приложение и в качестве параметра указать --urls, и в этом значении после этого urls-ключа вы можете передать список тех адресов, которые теперь нужно слушать. +4134.32 4136.66 "Анатолий Кулаков" Еще одно место – это upsettings.json. +4136.66 4149.26 "Анатолий Кулаков" В upsettings.json вы прямо в самом ротовом элементе можете указать свойства, которые называются urls, можете указать свойства, которые называются http_ports, которые было выше упомянуто, и оба они потянутся без всяких проблем. +4149.26 4155.50 "Анатолий Кулаков" Дальше у нас есть еще один JSON-файл, который не так очевиден. +4155.50 4156.98 "Анатолий Кулаков" Это launch_settings.json. +4156.98 4161.26 "Анатолий Кулаков" Это специальный файл, который находится в папочке properties. +4161.26 4171.54 "Анатолий Кулаков" И его использует в основном Visual Studio для того, чтобы предоставить вам очень удобный drop-down-лист с профилями запуска. +4171.54 4180.54 "Анатолий Кулаков" Допустим, ваше приложение может быть запущено под IS-экспресса, может быть запущено в виде EXE, может быть запущено под или развернуто под настоящий IS. +4180.54 4184.10 "Анатолий Кулаков" В общем, есть различные профили запуска вашего приложения. +4184.10 4188.26 "Анатолий Кулаков" И вот эти профили запуска, они как раз-таки все и описываются в launch_settings.json, очень полезный файлик. +4188.26 4202.74 "Анатолий Кулаков" И у этого launch_settings.json есть свойство, которое называется application_url, которое вы точно так же можете настроить и которое точно так же скажет, на каком адресе ваше приложение должно слушать входящие запросы. +4202.74 4208.50 "Анатолий Кулаков" Также в launch_settings.json очень удобно настраивать переменное окружение. +4208.50 4230.90 "Анатолий Кулаков" Допустим, если вы хотите, чтобы загружать ваше приложение под какими-нибудь разработческими настройками, с разработческими environment variables или с какими-нибудь тестовыми настройками, переменными среды окружения, вы можете просто запустить два профиля, у каждого из профилей обозначить свои переменные окружения, и в Visual Studio очень удобно переключаться между этими профилями. +4230.90 4233.98 "Анатолий Кулаков" В общем, полезный файлик, про него тоже полезно знать. +4233.98 4246.46 "Анатолий Кулаков" Ну и самый последний, самый хардкорный, самый низкоуровневый, самый оптимизируемый способ – это указать Кестрилу напрямую, откуда ему брать этот адрес. +4246.46 4248.50 "Анатолий Кулаков" То есть вы можете сконфигурировать Кестрил. +4248.50 4252.58 "Анатолий Кулаков" В обычной жизни вам этим, скорее всего, не приходится заниматься, но в этом нет ничего сложного. +4252.58 4260.86 "Анатолий Кулаков" У вышеупомянутого билдера есть свойство webhost и у этого свойства есть метод, который называется ConfigureCastKestril. +4260.86 4280.30 "Анатолий Кулаков" Это свойство принимает Kestril Server Options в качестве аргумента, и у этих опционов есть метод Listen, который принимает кучу аргументов, у него есть куча перегрузок и в частности он может вам получить конкретный адрес, получить конкретный порт и прибандить Кестрил именно туда. +4280.30 4297.62 "Анатолий Кулаков" У этих опций очень много возможностей, там сертификаты туда можно подставлять, какие-нибудь буферы кестриловские, оптимизировать какие-нибудь свои собственные протоколы проставлять вместо TCP/IP, в общем, там черт ногу сломит, но в частности, портики и адреса туда тоже можно записывать. +4297.62 4312.70 "Анатолий Кулаков" Вот такой набор свойств, у каждого из них есть какие-то плюсы и какие-то минусы, у каждого можно захардкодить, каждый можно динамически в рандайме выяснить, какой и какие можно в файлах прописать, наверное, какой ближе к вам, какой ближе к вашей ситуации, такой и стоит использовать. +4312.70 4316.14 "Игорь Лабутин" Мне приятно, что видите такое разнообразие, действительно. +4316.14 4327.34 "Игорь Лабутин" Не уверен, что я наизусть, например, помню все их, но обычно просто это либо через параметр командной строки, либо через переменное окружение недостаточно, но удобно, что только всего есть. +4327.34 4360.42 "Анатолий Кулаков" Ну, вот приятная штука, знаешь, что есть еще специальная опция, когда ты можешь поднять свой сервис и настроить прослушивание на любом рандомном порту, на любом свободном открытом, потому что ты не можешь сто процентов гарантировать, что у тебя порт 8080 абсолютно везде настроен, абсолютно везде открыт, и у тебя есть право вообще к нему бандиться, поэтому можно на любом рандомном, например, открывать, на любом рандомном открытом, опять же, открывать и гарантировать тем, что, допустим, твои интеграционные тесты всегда найдут себе свободный порт. +4360.42 4370.34 "Анатолий Кулаков" Ну, в этом случае у тебя, Павел, получается проблема, что как только ты открываешь, грубо говоря, на рандомном портике, ты не знаешь, а на каком портике запустился твое приложение и куда клиенты должны обращаться. +4370.34 4381.98 "Анатолий Кулаков" И вот там, например, есть, можно, опять же, взять сервер фикчу, у нее спросить, где ты слушаешь, но она не всегда есть, например, когда ты хотишься пдисом, ее у тебя нет. +4381.98 4396.46 "Анатолий Кулаков" И вот там уже другие способы работают, например, динамически самому найти свободный порт, динамически его указать уже через конфигурацию, допустим, того же самого кестрала или аппликейшн билдера, и то есть на момент старта программы его, несмотря на то, что он рандомный, его уже знать. +4396.46 4398.66 "Анатолий Кулаков" И когда ты его знаешь, ты уже можешь его куда-то запаблишить. +4398.66 4405.78 "Анатолий Кулаков" В общем, случаи получаются всякие, и как бы на момент запуска самого экзешника, может быть, тебе порт и неизвестен будет. +4405.78 4422.02 "Игорь Лабутин" Ну, а еще можно, мы, по-моему, один раз такое делали, я не помню, пушится ли он по дефолту, или мы добавляли это сами, запушить его как метрику наружу, сочетать эту метрику и таким образом узнать, ну, типа, метрики есть. +4422.02 4423.02 "Анатолий Кулаков" Ну, это такой очень экзотический способ. +4423.02 4424.02 "Анатолий Кулаков" Как метрика. +4424.02 4425.02 "Анатолий Кулаков" Да, метрика, это сильно. +4425.02 4426.02 "Анатолий Кулаков" Ну, число же число. +4426.02 4427.02 "Анатолий Кулаков" У тебя она всегда будет одинаковая. +4427.02 4428.02 "Анатолий Кулаков" Да? +4428.02 4429.02 "Анатолий Кулаков" Ну, а что такого? +4429.02 4430.02 "Игорь Лабутин" Действительно, действительно. +4430.02 4432.26 "Игорь Лабутин" Почему бы и нет? +4432.26 4434.26 "Игорь Лабутин" Ладно, давай пойдем дальше. +4434.26 4444.10 "Игорь Лабутин" А дальше у нас, ну, как, тема, мне кажется, последних трех, больше выпусков, это «Дональд Эспаир». +4444.10 4451.10 "Анатолий Кулаков" Если еще считать анонсы, мы там про него начали говорить, да, потом в декабре там что-то тоже было, и тут в январе полностью выпуск про него был. +4451.10 4453.50 "Игорь Лабутин" Ну, в общем, да, популярный чувак, знаешь. +4453.50 4454.50 "Игорь Лабутин" Короче, «Эспаир». +4454.50 4455.50 "Игорь Лабутин" «Дональд Эспаир превью-3». +4455.50 4457.38 "Игорь Лабутин" Что в нем поменялось? +4457.38 4459.66 "Игорь Лабутин" В нем поменялось довольно много всего. +4459.66 4462.86 "Игорь Лабутин" Во-первых, напомню, что что такое вообще в принципе «Эспаир». +4462.86 4479.54 "Игорь Лабутин" Да, «Эспаир» - это некоторый такой opinionated stack, библиотека набор компонентов от Microsoft, который позволяет вам удобнее разрабатывать локальное приложение, локально разрабатывать клауд-приложение, да, то есть микросервисы, грубо говоря. +4479.54 4483.54 "Игорь Лабутин" И потом их чуть более удобно деплойть, дальше уже куда вы их там деплойте. +4483.54 4486.86 "Игорь Лабутин" И концептуально он состоит из нескольких частей. +4486.86 4487.86 "Игорь Лабутин" Одна из частей - это дэшборд. +4487.86 4498.14 "Игорь Лабутин" Дэшборд - это, пожалуй, главное, что обновилось в превью-3, потому что они много чего в нем отрефакторили, много чего в нем переделали и в итоге вытащили его в абсолютно отдельный тул. +4498.14 4500.90 "Игорь Лабутин" Что позволяет дэшборд делать? +4500.90 4507.06 "Игорь Лабутин" Дэшборд позволяет вам смотреть, что же у вас запущено, какие там контейнеры, процессы, приложения и так далее. +4507.06 4510.46 "Игорь Лабутин" Позволяет смотреть логи, позволяет смотреть метрики, позволяет смотреть трейсы. +4510.46 4528.38 "Игорь Лабутин" Короче, красиво делать практически полное обзервабилити, если не сказать полной обзервабилити вашего приложения, причем все это локально и в виде одного как бы, по сути одного проектика, одного как бы тула, а не трех-четырех контейнеров, которые должны работать там вместе. +4528.38 4529.82 "Игорь Лабутин" Графана, Прометеус и все остальное. +4529.82 4541.02 "Анатолий Кулаков" А скажи, вот этот дэшборд, он как запускается, отдельный контейнер или я могу его в end-process со своим приложением запустить, если мне не нужны контейнеры, у меня есть один всего-навсего экзешничек и я хочу его тогда встроить? +4541.02 4545.54 "Игорь Лабутин" Пока вроде как в экзешничек я не видел, чтобы встраивали. +4545.54 4564.30 "Игорь Лабутин" Пока вроде как отдельно, но поскольку это первый превью, в котором это вышло, ну в смысле превью третий, но это первый раз, когда они такое сделали, то сейчас начались эксперименты, в комьюнити видно по всяким разным твитам и прочему, что прикольно, работает, так что посмотрим, может и в end-process занесут как-нибудь. +4564.30 4573.94 "Анатолий Кулаков" Ну да, мне кажется, для таких небольших приложений, которые состоят из одного экзешника, которые может быть даже не очень контейнеры используют, тоже был бы последний дэшборд, такой эмбарик, если его сделают. +4573.94 4577.90 "Игорь Лабутин" Да, сейчас пока это просто, как они пишут, это independent executable. +4577.90 4578.90 "Игорь Лабутин" Ну, посмотрим. +4578.90 4603.50 "Игорь Лабутин" Много чего поменяли в дэшборде на тему локализации и аксессибилити, улучшили ресурс детейлс, более красиво, чтобы все показывалось, добавили улучшений в телеметрию, какие-то гистограммы, метрик, спаны, венты, короче, много чего такого, пользуйтесь, посмотрите, будет выглядеть лучше. +4603.50 4604.50 "Игорь Лабутин" По компонентам. +4604.50 4632.10 "Игорь Лабутин" Это вторая большая часть Aspire, это компоненты, которые позволяют легко добавить в ваш продукт некоторую стандартную функциональность, тоже хорошо сконфигурированную, то есть, например, добавить хорошо сконфигурированное что-то по эклиен, со всякими поли, ну короче, ретраями, резилиенсом, вот этим всем, или там добавить стандартные настройки для RADIS, или еще для чего-нибудь. +4632.10 4640.42 "Игорь Лабутин" Добилось несколько новых компонентов, во-первых, ну куда же без Azure AI Open AI Component, никуда не делась. +4640.42 4670.22 "Игорь Лабутин" Второй компонент это Kafka, причем не только, как это сказать, не только подключает возможность коннекта Kafka в ваше приложение, но если вам нужно для локальной отладки, вы теперь можете в Aspire конфигурации в C# написать что-нибудь типа with Kafka, я не помню как там, пишется точно, и у вас будет локально подниматься преконфигурированная Kafka для вашей локальной разработки. +4670.22 4683.54 "Игорь Лабутин" Ну, то есть, понятно, что это просто поднимается контейнер с Kafka, но вот теперь достаточно просто написать в одном месте C# кода with Kafka и все, у вас есть готовый сервер Kafka, когда у вас приложение работает. +4683.54 4712.70 "Игорь Лабутин" Дальше, соответственно, появились интеграции для работы через Entity Framework с Oracle и с MySQL, можно теперь сделать с Cosmos DB то же самое, как я только что говорил, с Kafka, то есть при необходимости, у Cosmos DB есть локальный эмулятор, вы можете поднять, не обязательно ходить в Azure для этого, можно поднять локальную копию Cosmos DB, точнее локальную базу данных, которая эмулирует поведение Cosmos DB, вот теперь есть компонент, который позволяет это легко сделать. +4712.70 4785.18 "Игорь Лабутин" В Redis завезли логирование, точнее не в сам Redis, а в библиотеку доступа от Second Exchange, завезли логирование, и поскольку все это еще в превью, то у нас есть ряд breaking-чинджей, ну например поменяли API, то, что раньше называлось withServiceBinding, теперь называется withEntryPoint, если вы обновляете на третью превью, у вас перестает все собираться, потому что поменялись названия методов, такой нормальный breaking-чиндж, ну превью, что вы хотели, зато для контейнеров теперь можно указывать специальную функцию withEntryPoint и таким образом просто прямо указывать, что запустить внутри контейнера, когда он поднимется, дальше из полезняшек таких добавилось, например у вас была компонента Postgres, она позволяла настроить вам ConnectedPostgres, прокидывала там всякие connection-стринги к базе, вот это все, теперь туда можно еще дописать метод расширения withPgoadmin, после чего у вас поднимется дополнительный контейнер с Pgoadmin рядышком, и такая же штука для Redis Commander, это веб-менеджмент для Redis, короче они делали максимально удобно, максимально односрочно, так скажем, дефолтные конфигурации для самых популярных тулов. +4785.18 4876.98 "Игорь Лабутин" Внезапно в DotNet Espire Preview 3 добавили поддержку орлинсов, вот уж чего-чего, не думал, что так быстро сделают, но видимо кому-то надо было, очень надо, поэтому добавили, и добавили три новых проекта, примеров проектов, прямо в репозитории DotNet Espire лежит, три новых проекта, во-первых, называется Espire with JavaScript, это проект, который показывает как работать с Espire, если у вас есть DotNet Espire Application плюс дополнительно еще Node.js приложение зачем-то, плюс какой-нибудь SPA frontend типа Angular, React или Vue, как это все вместе сдружить и все это работает в Espire, дальше есть проект под названием ClientAppsIntegration, которое показывает как подружить DotNet Espire с WinForm или WPF и собирать с них аналогии, трейдсы и все такое, ну и последний проект это PersistentVolumeMount, это проблематика следующая, Espire вот этот вот дэшборд и сервер, который собирает все менеджеры, логи и так далее, он все это делает в памяти, т.е. как только вы говорите закончить там отладку или еще что-нибудь, хост DotNet Espire, дэшборда опускается и он теряет все, что у него было, т.е. если вам после этого захочется посмотреть логи прошлого запуска, вы уже не сможете, но есть возможность подключить нормальную базу данных либо файловую систему для того, чтобы хранить все по-человечески, вот этот пример показывает как это сделать. +4876.98 4904.14 "Игорь Лабутин" Ну и последнее изменение для превью 3, это добавили два новых шаблончика, т.е. до превью 3, что вы могли сделать, вы могли создать новый проект с поддержкой Espire, а вот если вам нужно было добавить поддержку Espire к существующему проекту, то вам откуда-то нужно было взять вот эти два шаблонных проекта, UpHost и ServiceDefault, в которых собственно и описывается вся инфраструктура и настройки. +4904.14 4919.18 "Игорь Лабутин" Вот теперь есть два шаблончика, которые позволяют в уже готовом солюшене написать DotNet New Espire UpHost или DotNet New Espire ServiceDefault и вам к существующему солюшену добавится два вот этих вот новых нужных для работы Espire проекта, т.е. +4919.18 4922.42 "Игорь Лабутин" ServiceDefault не то чтобы сильно нужен, но по крайней мере обычно есть. +4922.42 4935.66 "Игорь Лабутин" Вот такие дела, Espire живет, развивается, смотрим что будет дальше с Dashboard, насколько комьюнити его полюбит, примет и будет использовать, может быть даже отдельно от DotNet будем посмотреть. +4935.66 4936.66 "Анатолий Кулаков" Пока не видел. +4936.66 4960.82 "Анатолий Кулаков" Слушай, а нету ли примеров с тестами, потому что интересная тема, у нас же есть отдельный контейнер тестов, грубо говоря, а здесь кажется, что эта штука примерно их покрывает, потому что если мы под разработческим окружением можем одной кнопкой запустить все наши кавки, как ты сказал, Orleans, то мы наверняка же захотим это делать и в интеграционных тестах, вот нет ли каких-то примеров, как она дружит с интеграционными тестами? +4960.82 4965.30 "Игорь Лабутин" Пока я не видел, пока это чисто девелоперский тулинг из того, что я видел. +4965.30 4975.46 "Анатолий Кулаков" Ну, то есть, понимаешь, у нас теперь будет как бы мы эту кавку и Orleans будем настраивать в девелоперском тулинге, а потом то же самое будем идти и делать в тест-контейнерах. +4975.46 4976.82 "Анатолий Кулаков" Звучит как довольно странно. +4976.82 4986.34 "Игорь Лабутин" Я согласен, и скорее всего надо внимательно почитать репозитории Espire, может быть там что-то про это есть, я просто настолько внимательно и не изучал их в части. +4986.34 5000.50 "Игорь Лабутин" Можно посмотреть к следующему разу, если что-то нароется, я периодически туда заглядываю, ради того, чтобы понять, есть ли что-то новенькое, а может и превью какую-нибудь выпустят в следующем выпуску, или когда выпустят следующий превью, я постараюсь не забыть посмотреть на эту тему. +5000.50 5001.50 "Анатолий Кулаков" Давай. +5001.50 5003.50 "Анатолий Кулаков" Не дадим вам отдохнуть от Espire ни одного выпуска, +5003.50 5004.50 "Игорь Лабутин" да? +5004.50 5008.02 "Игорь Лабутин" Ну, я надеюсь, что они не успеют за 2 недели выпустить следующий превью. +5008.02 5015.10 "Анатолий Кулаков" Ладно, погнали, времени осталось мало, а тут еще пару интересных статей, которые хотелось бы вбросить. +5015.10 5021.78 "Анатолий Кулаков" Марк Симон, давно мы не обращались к нашему гуру, хотелось бы повысить градус гиковости. +5021.78 5029.38 "Анатолий Кулаков" Давайте посмотрим, у него есть хорошая статья вышла, которая называется «Категории ошибок и ошибки категорий». +5029.38 5041.78 "Анатолий Кулаков" Казалось бы, да, что сейчас мы снова про категории, но нет, здесь все довольно более приземисто, здесь автор рассуждает о том, на какие типы и виды он делает где-то ошибки, каким образом он их обрабатывает и как к этому вопросу подходит. +5041.78 5058.58 "Анатолий Кулаков" Вообще вопрос обработки ошибок, он очень нетривиальный, несмотря на его очевидность и, казалось бы, продуманность уже не одно десятилетие, многие языки все еще перезабретают какие-то подходы к ошибкам, как их обрабатывать, что надо обрабатывать, что не надо обрабатывать и прочие-прочие эти вещи. +5058.58 5065.38 "Анатолий Кулаков" Поэтому тема глобальная, тема большая, ну, так поверхностно немножко про ней пошелся Марк. +5065.38 5071.42 "Анатолий Кулаков" Прежде всего нужно осознать, что в любом программном приложении есть ошибки или будут ошибки. +5071.42 5086.10 "Анатолий Кулаков" Вы никогда не будете застрахованы от всего, начинать можно с обычного user input, если у вас есть user input, то пользователь вам может ввести невалидные данные, которые ваше приложение не способно, не хочет и не будет обрабатывать. +5086.10 5119.10 "Анатолий Кулаков" К вам могут попасть какие-то поврежденные данные, какие-то поврежденные конфиги, которые у вас уже есть, у вас может случиться проблема с сетью, у вас может быть наведенка от рентгеновских лучей, у вас может быть какие-то параллельные вычисления, которые дадут вам risk condition или concurrent exception или еще что-то, ну и в крайнем случае в вашем коде всегда могут быть баги, то есть мы разрабатываем все наши приложения всегда оперируя тем, что вокруг нас есть ошибки того или иного уровня сложности, критичности и так далее. +5119.10 5120.10 "Анатолий Кулаков" Это уже не суть важно. +5120.10 5125.94 "Анатолий Кулаков" Важно то, что наше приложение не всегда работает так, как мы это задумывали в идеальном success path. +5125.94 5132.42 "Анатолий Кулаков" И по версии Марка ошибки можно разделить на начальном этапе на три категории. +5132.42 5145.82 "Анатолий Кулаков" Во-первых, это предсказуемые ошибки, которые мы можем обработать, предсказуемые ошибки, которые мы не можем обработать и, соответственно, непредсказуемые ошибки, которые мы не можем никак предсказать. +5145.82 5147.22 "Анатолий Кулаков" Давайте рассмотрим их поподробнее. +5147.22 5152.58 "Анатолий Кулаков" Ну прежде всего большинство ошибок, которые есть в наших приложениях, мы вполне способны предсказать. +5152.58 5156.54 "Анатолий Кулаков" Например, к ним относится уже вышеупомянутый ввод пользователя. +5156.54 5165.30 "Анатолий Кулаков" Когда пользователь вводит какие-то данные в ваше приложение, вы на сто процентов можете быть уверены, что рано или поздно он в этих данных ошибется. +5165.30 5169.34 "Анатолий Кулаков" Поэтому там существует стандартный процесс валидации пользовательских данных. +5169.34 5171.06 "Анатолий Кулаков" В общем, от этого вы никуда не денетесь. +5171.06 5174.10 "Анатолий Кулаков" И это то, что мы можем предсказать на сто процентов. +5174.10 5177.66 "Анатолий Кулаков" То есть, это тот слой, который обязательно должен присутствовать в вашем приложении. +5177.66 5182.46 "Анатолий Кулаков" Немножко сложнее обстоит дело с получением данных из другой системы. +5182.46 5188.94 "Анатолий Кулаков" То есть, когда не пользователь вам вводит эти данные, а другая система вводит данные, здесь есть тонкости, от которых мы немножко позже посмотрим. +5188.94 5200.02 "Анатолий Кулаков" То есть, для того, чтобы избежать ошибок пользовательского ввода, вам необходимо настроить свой слой валидации и каким-то образом проинформировать пользователя о плохих данных, которые он вам ввел. +5200.02 5206.54 "Анатолий Кулаков" Выдать сообщение об ошибке, написать в лог, написать в консольку или каким-то другим образом. +5206.54 5213.66 "Анатолий Кулаков" Дальше следующая категория – это тоже предсказуемые ошибки, но немножко более сложные. +5213.66 5220.34 "Анатолий Кулаков" Например, ваше приложение, скорее всего, может зависеть от базы данных. +5220.34 5222.30 "Анатолий Кулаков" А эта база данных может быть недоступна. +5222.30 5225.18 "Анатолий Кулаков" Может покарабкаться, может отвалиться винт, может отвалиться сеть. +5225.18 5229.58 "Анатолий Кулаков" И вообще у вас может отвалиться сеть, например, с другими сервисами, которые необходимы вам для работы. +5229.58 5234.54 "Анатолий Кулаков" Например, ваше приложение могли плохо сконфигурировать. +5234.54 5236.82 "Анатолий Кулаков" Например, задать неправильный connection string. +5236.82 5242.74 "Анатолий Кулаков" Отчего оно, естественно, работать не сможет, с базой данной приконектиться не сможет и вообще основные функции выполнять не сможет. +5242.74 5244.98 "Анатолий Кулаков" У вас, может быть, банально кончится место на диске. +5244.98 5250.30 "Анатолий Кулаков" Может быть, не знаю, сервер закрашивался из-за какой-то ошибки. +5250.30 5253.30 "Анатолий Кулаков" Может закрашивалась какая-то из ваших зависимостей, которая вам нужна. +5253.30 5258.70 "Анатолий Кулаков" В общем, очень много существует инфраструктурных, технических проблем, от которых вы абсолютно никак не застрахованы. +5258.70 5265.86 "Анатолий Кулаков" Вы должны понять, что любая сеть падает, любая датабаза сломается, любой диск заполняется. +5265.86 5270.58 "Анатолий Кулаков" Эти штуки можно решить, можно попытаться решить, давайте так. +5270.58 5286.94 "Анатолий Кулаков" Можно сделать ретрай, можно сделать какие-нибудь дополнительные приседания, попробовать через какое-то время уменьшить количество запросов, circle bracket поставить, можно еще что-то сделать. +5286.94 5290.94 "Анатолий Кулаков" Но в общем случае, единственное, что вы сможете сделать, это залогировать проблему. +5290.94 5295.26 "Анатолий Кулаков" Ну и не факт, что вообще ваш лог сможет куда-то записаться, потому что все зависит от проблем. +5295.26 5313.66 "Анатолий Кулаков" И надо понимать, что если, допустим, у вас ваше приложение зависит от базы данных, и база данных почему-то или повреждена, или не отвечает, или мы не можем получить правильный connection string к ней, то ваше приложение, по сути, становится неработоспособным. +5313.66 5317.46 "Анатолий Кулаков" Это значит, что вы не можете обработать эту ошибку. +5317.46 5324.32 "Анатолий Кулаков" То есть, когда мы раньше в эту категорию спускались, мы ее рассматривали как предсказуемые ошибки. +5324.32 5327.98 "Анатолий Кулаков" И вот это те предсказуемые ошибки, которые вы обработать не в состоянии. +5327.98 5339.26 "Анатолий Кулаков" Да, вы можете пытаться хоть целый день ретраить на базу данных, но вы должны понимать, что рано или поздно лимит ретраива у вас закончится, и все равно ваше приложение не способно будет работать полноценно. +5339.26 5348.82 "Анатолий Кулаков" Поэтому у нас появляется вот такая отдельная категория, что ошибки, которые мы теоретически можем предсказать, да, все рано или поздно ломается, но сделать мы с этим ничего не сможем. +5348.82 5354.50 "Анатолий Кулаков" Также нужно понимать, что часто ошибки бывают контекстно зависимыми. +5354.50 5362.14 "Анатолий Кулаков" Ну, например, рассмотрим наш предыдущий сценарий, когда у нас есть пользователь, который вводит невалидные данные. +5362.14 5366.42 "Анатолий Кулаков" Когда он вводит невалидные данные, мы ему выдаем сообщение об ошибке, и здесь все хорошо. +5366.42 5370.62 "Анатолий Кулаков" Теперь возвращаемся к примеру, когда эти невалидные данные к нам присылает какой-то другой сервис. +5370.62 5376.90 "Анатолий Кулаков" И этот другой сервис, допустим, с ним нет какого-то канала связи, вы не можете ему там сказать просто exception и все. +5376.90 5379.90 "Анатолий Кулаков" Он вам просто загружает какой-то файл и говорит «обрабатывай». +5379.90 5380.90 "Анатолий Кулаков" И никого не волнует этот файл. +5380.90 5383.22 "Анатолий Кулаков" Может быть с плохими данными, с плохими, с еще какими-то. +5383.22 5387.54 "Анатолий Кулаков" Что можно сделать в случае, если вдруг у вас там есть в этом файле невалидные данные? +5387.54 5395.90 "Анатолий Кулаков" Ну, во-первых, конечно, можно всегда бросить ошибку, отказаться отрабатывать этот файл, послать bad request, сделать reject. +5395.90 5399.54 "Анатолий Кулаков" То есть, в принципе, как вариант тоже может быть. +5399.54 5404.98 "Анатолий Кулаков" Можно попытаться найти из этого файла только валидные какие-то значения и обработать только их. +5404.98 5415.22 "Анатолий Кулаков" Можно послать какое-то асинхронное сообщение, что типа «я не смог обработать этот файл», приложить файл, объяснить почему, и типа попытайтесь снова через какое-то время или еще что-то с этим файлом сделать. +5415.22 5417.14 "Анатолий Кулаков" В общем, как-то оповестить админов. +5417.14 5433.82 "Анатолий Кулаков" Все это нас приводит к тому выводу, что если у нас есть проверка пользовательского ввода, то есть, допустим, обычная валидация инпута, то то, как мы будем реагировать на эту валидацию инпута, вполне контекстно зависимо. +5433.82 5440.26 "Анатолий Кулаков" И тот сам процессор, который валидирует этот файл, может быть, даже не знает, каким образом это правильно нужно отвалидировать. +5440.26 5445.62 "Анатолий Кулаков" Знает только тот, кто этот файл в этот процессор отдал. +5445.62 5449.06 "Анатолий Кулаков" То есть, некий враппер сверху, который может принять решение. +5449.06 5457.38 "Анатолий Кулаков" Есть у него текущий интерактивный пользователь или у него просто какой-нибудь машин-то машин-коммуникация и он как-то может другой машине сообщить о проблемах. +5457.38 5471.58 "Анатолий Кулаков" Нужно также понимать, что обработка ошибок всегда связана с неким трейдовом, то есть, у вас всегда есть какие-то плюсы, какие-то минусы и вы всегда должны уметь чем-то жертвовать. +5471.58 5484.70 "Анатолий Кулаков" Возвращаясь к примеру с базы данных, когда мы получаем недоступную базу данных, то вы можете сколько угодно ретраиться, но рано или поздно вы придёте к осознанию, что вы не можете ничего с этим сделать. +5484.70 5492.38 "Анатолий Кулаков" И в обычном банальном случае вы можете отказаться от обработки этой операции, от обработки команды. +5492.38 5496.50 "Анатолий Кулаков" Это как бы 100% скорее всего нашей повседневной бизнес-задачи. +5496.50 5508.90 "Анатолий Кулаков" Когда к нам приходит какой-то реквест на создание пользователя, мы идём в базу, она недоступна, ну мы просто падаем и всё с криками, ай-яй-яй, не могу создать пользователя, программа наша выполнила недопустимую ошибку и будет открыта, и будет закрыта. +5508.90 5517.42 "Анатолий Кулаков" Это самый распространённый кейс, но подумайте, что будет, если вдруг вы пишете программу, которая обрабатывает какие-нибудь медицинские данные, от которых зависит жизнь человека. +5517.42 5529.50 "Анатолий Кулаков" Или если вы запускаете какой-нибудь зонд в космос, где у вас нет возможности просто-напросто поднять ручки и сказать "всё, нишмогла", там вам нужно как-то мучиться, что-то делать. +5529.50 5531.22 "Анатолий Кулаков" И мучиться можно на разных уровнях. +5531.22 5539.34 "Анатолий Кулаков" Можно, как я уже говорил, напрячь сисадминов, которые поставят вам какой-нибудь файловер к базе данных, чтобы она была не одна, чтобы она была более отказоустойчивая. +5539.34 5549.46 "Анатолий Кулаков" Можно запаять к вам в ящик несколько сетевых карт, чтобы если одна отвалилась, у нас всегда был резервный канал связи, мы могли пойти на другую карту. +5549.46 5557.26 "Анатолий Кулаков" Но всё это более-менее от нас не зависит, мы можем это бросить как-то на админов, но как разработчики, грубо говоря, этот путь нам не интересен. +5557.26 5565.10 "Анатолий Кулаков" Нам интересен другой путь, мы на это можем повлиять с точки зрения архитектуры программного приложения. +5565.10 5566.10 "Анатолий Кулаков" Каким образом? +5566.10 5580.90 "Анатолий Кулаков" Ну, например, если у нас недоступна база данных, но при этом доступен, допустим, какой-нибудь асинхронный обмен событиями, там Kafka или Rabbit, мы вполне можем послать себе какое-нибудь асинхронное сообщение, допустим, попытаясь сделать ту же операцию через какой-то промежуток времени. +5580.90 5592.14 "Анатолий Кулаков" Если эти сообщения ещё отправляются через какую-нибудь дюрибл очередь, то есть очередь, которая может сохраниться себе на диск и гарантировать нам какую-то доставку, то вообще прекрасно. +5592.14 5597.26 "Анатолий Кулаков" Могут быть какие-то другие ситуации, которые мы можем каким-то образом по-другому обрабатывать. +5597.26 5614.62 "Анатолий Кулаков" Но, например, если недоступна сеть, вам нужно срочно отправить логи, а недоступна сеть, вы можете вполне сделать у себя локально на диске какой-то буфер с этими логами и как только сеть поднимется, вы этот буфер можете, например, запаблишить куда-нибудь в ваше официальное хранилище. +5614.62 5620.34 "Анатолий Кулаков" То есть можно предусматривать на уровне кода, на уровне программистов вот обход вот таких вот ситуаций. +5620.34 5625.34 "Анатолий Кулаков" Но, опять же, нужно понимать, что всему есть предел. +5625.34 5629.22 "Анатолий Кулаков" Вы не можете бесконечно буферировать в диск, потому что диск сломается. +5629.22 5637.58 "Анатолий Кулаков" Если у вас отказала база данных, то, скорее всего, можете отказать и шинка, в которую вы можете забрасывать сообщения. +5637.58 5649.66 "Анатолий Кулаков" Таким образом, у нас все-таки ситуация, когда у нас есть предсказуемые ошибки, которые вы якобы могли бы обработать, мы можем уменьшить вот этот эффект, который мы могли бы обработать. +5649.66 5655.74 "Анатолий Кулаков" Мы можем и на локальный диск писать, и в другие источники записывать, и как-то это все кэшировать, и как-то повторять. +5655.74 5666.06 "Анатолий Кулаков" Но рано или поздно мы понимаем, что все возможные ситуации предусмотреть невозможно, и постепенно эта категория все равно сваливается в категорию ошибок, которая называется предсказуемые ошибки, которые мы не можем отработать. +5666.06 5679.50 "Анатолий Кулаков" Поэтому нужно ли загоняться вот этими всеми оптимизациями, которые мы пытаемся сделать с ошибками, которые мы якобы можем предсказать, но не можем обработать? +5679.50 5686.74 "Анатолий Кулаков" Нужно ли все-таки ресайленты делать, буферы делать, ретраи делать каждый раз на любом вашем приложении? +5686.74 5687.74 "Анатолий Кулаков" Ответ по дефолту нет. +5687.74 5697.86 "Анатолий Кулаков" Это все очень большое усложнение, которое дается очень большими силами разработчиков, а самое главное, оно ввозит в ваше приложение дополнительную сложность. +5697.86 5706.02 "Анатолий Кулаков" Вся эта сложность, это прямое следствие этой сложности будут дополнительные баги, какие-то проблемы по эксплуатации, какие-то проблемы с метриками, еще чего-то. +5706.02 5712.90 "Анатолий Кулаков" В общем, все это очень-очень сложно, поэтому зря, просто так, ради интереса, по дефолту в эту сложность вписываться не надо. +5712.90 5717.14 "Анатолий Кулаков" И опять же, вся эта сложность, она не дает вам никаких гарантий. +5717.14 5724.74 "Анатолий Кулаков" У вас все равно диск закончится, ретраи кончатся, все базы данных и очереди отвалятся, т.е. у вас все равно гарантий никаких нет. +5724.74 5726.66 "Анатолий Кулаков" Поэтому здесь вам нужно взвешивать. +5726.66 5730.30 "Анатолий Кулаков" Опять же, если у вас критикал-система, то да, стараемся изо всех сил. +5730.30 5734.78 "Анатолий Кулаков" Если что-то средненькое, ну, пробуем какие-то базовые ретраи того же самого поля запустить. +5734.78 5741.02 "Анатолий Кулаков" Если пользователь прекрасно переживет bad-request, то просто бросаем им ошибку и не загоняемся ни о чем. +5741.02 5744.66 "Анатолий Кулаков" Это будет просто, красиво, понятно, а самое главное – поддерживаемо. +5744.66 5750.06 "Анатолий Кулаков" Есть еще одна интересная категория ошибок, которая называется баги, они же инциденты. +5750.06 5755.18 "Анатолий Кулаков" Третья категория, к которой относятся категории невозможно предсказать. +5755.18 5762.66 "Анатолий Кулаков" Ну, т.е. мы все можем предсказать, что баги у нас, конечно, есть, но мы абсолютно не понимаем ни в каком месте они выстрелят, ни как программа будет после этого себя вести. +5762.66 5766.22 "Анатолий Кулаков" Поэтому эта категория относится невозможно предсказать. +5766.22 5768.18 "Анатолий Кулаков" Но мы точно знаем, что они будут. +5768.18 5777.34 "Анатолий Кулаков" И если у вас был баг один раз, допустим, он стрельнул и исчез, то это прямое следствие того, что он может стрельнуть и второй раз, поэтому это очень опасная штука. +5777.34 5786.02 "Анатолий Кулаков" И в этот момент мы можем для себя решить, мы будем этот баг искать и фиксить или есть еще другой вариант, можно не искать и не фиксить. +5786.02 5797.50 "Анатолий Кулаков" Если мы не можем это сделать, мы можем вполне себе сами честно ответить, что этот баг, который мы фиксить не будем, он не так уж сильно влияет на наше приложение. +5797.50 5801.06 "Анатолий Кулаков" Мы его можем вполне описать, сказать, что оно происходит раз в год и в принципе забить. +5801.06 5807.26 "Анатолий Кулаков" Когда мы говорим про моделирование ошибок, у нас есть очень много подходов. +5807.26 5816.38 "Анатолий Кулаков" К сожалению, человечество до сих пор не придумало идеальные подходы, которые бы нам позволяли хорошо работать со всеми вот этими ошибками, которые здесь были описаны. +5816.38 5821.18 "Анатолий Кулаков" Но были придуманы некие вспомогательные методы. +5821.18 5826.74 "Анатолий Кулаков" Например, самая прекрасная вещь, которую придумала человечество для того, чтобы бороться с ошибками, это стронг тайпинг. +5826.74 5837.98 "Анатолий Кулаков" Именно поэтому языки с сильной статической типизацией очень сильно выиграют языку с динамической типизацией или без типизации, или со слабой типизацией, в общем, со всем этим шлаком в виде джаваскрипта. +5837.98 5846.92 "Анатолий Кулаков" Потому что то, что джаваскриптеры, питанисты и прочие люди должны выявлять в тестах, у нас делает компилятор на уровне компиляции. +5846.92 5854.86 "Анатолий Кулаков" Большинство из тех проблем, которые случаются в рантайме в этих языках, в строго типизированных языках, мы отлавливаем в компайл тайме. +5854.86 5863.30 "Анатолий Кулаков" У нас также есть на основании строгих типов еще их дополнительные фишки, дополнительные плюшки. +5863.30 5873.06 "Анатолий Кулаков" Прежде всего, это null-reference-types, это просто мега-фича, мега-взрывная штука и ее можно прям сравнить, как будто у вас не было раньше типа, а вы типы добавились. +5873.06 5891.38 "Анатолий Кулаков" Потому что null-reference-types дают вам огромное количество прекрасных возможностей избежания самой популярной в мире проблемы, это null-reference-exception, если вдруг вы почему-то до сих пор уже не пользуетесь все еще null-reference-types, то обязательно изучите вопрос, оно того стоит, оно спасает просто мега-сильно. +5891.38 5912.02 "Анатолий Кулаков" Также, благодаря тому, что у нас есть нормальные строгие типы, у нас полно линтеров и анализаторов, которые не просто там какие-то буквы анализируют, а могут нормально построить семантическое, синтаксическое дерево, пройтись, проанализировать, посмотреть свои типы и в памяти даже проинтерпретировать вам некоторый код для того, чтобы прям найти какие-нибудь определенные, например, векторы атаки. +5912.02 5914.26 "Анатолий Кулаков" Этим часто грешат там security-сканеры уязвимостей. +5914.26 5928.30 "Анатолий Кулаков" В общем, линтеры, анализаторы, NRT, strong-types, эти все инструменты как раз были призваны нам для того, чтобы уменьшить то количество ошибок, которые у нас возможно будут порождаться в рантайме и свести это на самый эффективный уровень – на билд-тайм. +5928.30 5939.86 "Анатолий Кулаков" Другие способы, как работать с ошибками – это введение специальных явных результатов, которые нам говорят о том, что данный метод может вернуть ошибку. +5939.86 5946.46 "Анатолий Кулаков" Это наверняка всем известный вам result-type, он же either в других методах, в других языках или maybe. +5946.46 5950.70 "Анатолий Кулаков" То есть это обычно тип, который может принимать два значения. +5950.70 5956.66 "Анатолий Кулаков" Или он успешно выполнился, и вам успешный результат, или не успешно выполнился, и какое-то описание ошибки возвращает. +5956.66 5960.02 "Анатолий Кулаков" В общем, этот подход тоже очень популярен в различных языках. +5960.02 5969.22 "Анатолий Кулаков" Ну и у нас еще есть методология, то есть у нас есть TDD, который позволяет нам покрывать тестами максимальное количество задач. +5969.22 5971.22 "Анатолий Кулаков" То есть это уже ловля на уровне рантайма. +5971.22 5977.26 "Анатолий Кулаков" У нас есть код-ревью, который тоже помогает уменьшить количество проблем на каких-то ранних этапах. +5977.26 6002.98 "Анатолий Кулаков" В общем, человечество придумало очень много всего, и включая инструментарии, включая методологии, включая подходы и чуть ли не целые концепции в языках программирования, которые отталкивались от ошибок, и как вести себя с ошибками, и как, например, перезапускать проблемы с ошибками, как это сделано, допустим, в АКИ, когда у нее есть целая стратегия, когда мы из ошибок перезапускаем целый кластер акторов. +6002.98 6012.70 "Анатолий Кулаков" В общем, ошибки драйвят очень сильно нашу систему, и пока человечество не выдумало что-то такое хорошее, где можно описать красиво все и решить все эти проблемы. +6012.70 6019.94 "Анатолий Кулаков" Поэтому мы пока остаемся на уровне методологии, на уровне договоренности, на уровне концепции, а также строгих типов и кучи анализаторов, которые нам в этом помогают. +6019.94 6026.90 "Игорь Лабутин" Ну, вообще, с одной стороны, звучит все это масштабно, классификация, все такое. +6026.90 6030.78 "Игорь Лабутин" С другой стороны, это не из разряда нормально делать нормально будет. +6030.78 6038.38 "Игорь Лабутин" Ну, то есть, подходи, так сказать, с умом к тому, насколько критична твоя система, и сообразно планируй. +6038.38 6043.82 "Игорь Лабутин" Это же все не просто разработчик решает, они сделают для меня тут ретрай. +6043.82 6054.94 "Игорь Лабутин" Это же как-то все, не знаю, должно проговариваться на каком-то плюс-минус критикурном уровне, пусть даже с самим разработчиком, но с каким-то более опытным разработчиком. +6054.94 6055.94 "Анатолий Кулаков" Не знаю. +6055.94 6056.94 "Анатолий Кулаков" Проговариваться – это одно. +6056.94 6063.94 "Анатолий Кулаков" Но так как мы в нашем повседневном коде сталкиваемся с миллионом мест, где может случиться ошибка, все это проговорить невозможно. +6063.94 6071.42 "Анатолий Кулаков" Поэтому у тебя должен быть очень высокий уровень сознательности, а уровень сознательности подразумевает под собой какой-то практический опыт. +6071.42 6082.34 "Анатолий Кулаков" Пока ты не натолкнешься на то, что база данных у тебя может отсутствовать, что тебе connection string могут неправильно записать, пока ты на практике вот это не испытаешь, скорее всего, большинство людей об этом даже не задумываются. +6082.34 6090.94 "Игорь Лабутин" Ну, или connection string есть, но у тебя мастер базы данных умерла, а реплика живет в рядомом режиме, и у тебя половина только с программой работает. +6090.94 6094.46 "Игорь Лабутин" Типа, гетпоинты работают, а посты не работают. +6094.46 6099.22 "Анатолий Кулаков" И приложение может быть устроено так, что при первой попытке записи у тебя оно просто рушится. +6099.22 6105.86 "Анатолий Кулаков" Можно было поставить его, чтобы только начание работало, но ты это как-то не предусмотрел, и у тебя на записи оно просто все падает. +6105.86 6107.30 "Анатолий Кулаков" Например, такое тоже может быть. +6107.30 6128.02 "Игорь Лабутин" Ну, в общем, подходите с умом, думайте о том, когда вы пишете код, что здесь может пойти не так, и если вам кажется, что что-то может пойти не так, и либо сами принимаете решение, как бы с этим бороться, либо сначала посоветуйтесь с кем-то еще в проекте, нужно с этим бороться, или пусть падает, потому что по факту вам окей. +6128.02 6135.74 "Игорь Лабутин" Хорошо, давай попробуем на сегодня успеть последнюю темку, наверное, быстренько пробежаться. +6135.74 6136.74 "Анатолий Кулаков" Ну, давай. +6136.74 6140.22 "Анатолий Кулаков" Ну, я думаю, что шансов мало. +6140.22 6141.22 "Анатолий Кулаков" Ладно. +6141.22 6142.22 "Анатолий Кулаков" Погнали. +6142.22 6152.22 "Анатолий Кулаков" Топ 10 визуал студийных фич, которые были выпущены в 2023 году, и которые понравились товарищу Джеймс Монтемангону. +6152.22 6163.02 "Анатолий Кулаков" Этот товарищ довольно знаменит, особенно в средах мобайл-разработчиков, очень много библиотек написал, очень много статей написал, в общем, товарищ просто золото. +6163.02 6176.22 "Анатолий Кулаков" К сожалению, в наших статьях, в наших подкастах он звучит редко, потому что по профилю немножко не подходит, но в основном человек очень крутой, поэтому нет никаких резонов ему не верить. +6176.22 6184.26 "Анатолий Кулаков" Давайте посмотрим, что он для себя открыл в 2023 году, даже не открыл, наверное, посчитал самыми хорошими инструментами, которые появились в визуал студии. +6184.26 6194.06 "Анатолий Кулаков" Прежде всего, это DevTunnels, туннели для разработчиков, которые позволяют вам, ваш локальный хост, выставить голой попой, например, в интернет. +6194.06 6209.62 "Анатолий Кулаков" То есть, данный сервис помогает вам сформировать специальный урл, и если кто-то зайдет по этому урлу, любой человек в интернете зайдет по этому урлу, он будет перенаправлен на ваш локальный сервак, на ваш локальный порт, который, допустим, у нас сейчас под студией запущен. +6209.62 6215.30 "Анатолий Кулаков" И вы, например, можете этот запрос отдебажить или что-то показать, например, вашу презентацию, или еще что-то. +6215.30 6218.30 "Анатолий Кулаков" Это просто мега-фича для мобильных разработчиков. +6218.30 6228.42 "Анатолий Кулаков" Когда у вас есть миллион девайсов, эти все миллионы девайсов никаким образом не подключены к вашей, допустим, корпоративной сети, у них нормально, если есть интернет. +6228.42 6244.70 "Анатолий Кулаков" И вот вы этим девайсам даете ссылочку, и эти девайсы заходят на ваш сервер, который сейчас запущен у вас под отладчиком, и делают там всякое, вызывают запросы, проходит авторизация, вы это все можете видеть, дебажить, смотреть, как бы снимать дампы, в общем, золотая штука. +6244.70 6262.06 "Анатолий Кулаков" А также, если вы просто хотите, например, показать в вашем веб-сайте, который вы недавно разработали какому-то, не корпоративному, а наоборот, внешнему клиенту, вы точно так же можете дать им урлик вот этот и не паблишить этот сайтик никуда, запустить его под Visual Studio, и по этому урлу ваш внешний потребитель все это увидит, все это посмотрит. +6262.06 6265.30 "Анатолий Кулаков" Короче, прекрасная штука, которая для некоторых сфер просто критикал необходима. +6265.30 6276.98 "Анатолий Кулаков" Дальше он отмечает вторую фичу, которая ему понравилась, это HTTP файлы и Endpoint Explorer, вообще не связаны между собой вещи, кроме там слова HTTP, наверное, но обе прекрасны. +6276.98 6285.18 "Анатолий Кулаков" HTTP файл – это возможность в Visual Studio сделать специальный файлик с расширением HTTP и писать там обычным текстом запросы. +6285.18 6292.66 "Анатолий Кулаков" Типа, дай мне такой сервис, и вы нажимаете специальную кнопочку, о, не дай, а вызови мне такой-то HTTP урл, допустим, какой-то Endpoint какой-то. +6292.66 6301.34 "Анатолий Кулаков" Нажимаете специальную кнопочку, и у вас этот урл вызывается, и показывается ответ от удаленного сервиса в виде такого же текстового файлика. +6301.34 6313.38 "Анатолий Кулаков" Казалось бы, идея примитивная, т.е. это обычный курл, грубо говоря, т.е. но более в удобном виде, в удобном файлике, который можно сохранить, передать и т.д., но это действительно на практике безумно удобно. +6313.38 6331.98 "Игорь Лабутин" Ну, и эта штука поддержана не только в Visual Studio, она поддержана многими и IDE, и RIDER такой умеют, в общем, такой плюс-минус стандарт, что ли, VVS-код, всё это пошло, на самом деле, из VVS-кода, где кто-то написал отличный экстенджер, который, собственно, эту идею предложил, насколько я понимаю. +6331.98 6334.46 "Игорь Лабутин" Ну и дальше это потихонечку растянулось во все места. +6334.46 6337.86 "Анатолий Кулаков" Я даже уже не боюсь предположить, откуда это первый раз пошло. +6337.86 6344.86 "Анатолий Кулаков" Ну, я, например, допользуюсь Visual Studio кодом, мне там удобнее такую штуку делать, но надо понимать, что Visual Studio тоже это умеет. +6344.86 6379.82 "Анатолий Кулаков" И второй подпункт – это Endpoint Explorer, тоже прекрасная тулза, которая позволяет вам просканировать весь ваш проект, притом не надо его запускать, сканируется исходный код, и посмотреть все endpoints, которые у вас есть, и посмотреть, где они в одном единственном окошечке, что они вызывают, а самое приятное – это сгенерировать для них реквест, и этот реквест как раз генерируется в подобном http-файле, т.е. вы можете открыть, нажать кнопочку "Generate" и позапускать запросы прямо к вашему endpoint, и увидеть сразу в этом же файле ответы к этому endpoint, вообще прекрасно. +6379.82 6395.30 "Анатолий Кулаков" Третий пункт – это GitHub Copilot, GitHub Copilot Chat, в общем, все, что связано с искусственными интеллектами, которые помогают нам давать подсказки в реальном времени, а также помогают кодить, помогают генерить файлы, тесты, рефакторинг, объяснять код и прочее-прочее. +6395.30 6427.82 "Анатолий Кулаков" Четвертый пункт – это GIT и улучшения в пул реквестах, т.е. вы в Visual Studio можете создать и управлять GIT-репозиториями с помощью интегрированного в Visual Studio UI, вы можете прилинковать коммиты из GitHub-ов, из GitHub-issues для более тщательного общения там и по отслеживанию истории того, что вы делаете, и также в Visual Studio есть встроенный пул реквест-креатор, который умеет создавать пул реквесты прямо из Visual Studio. +6427.82 6432.06 "Анатолий Кулаков" Игорь, ты пользуешься Visual Studio и вообще вот этой интеграцией с GIT-ом? +6432.06 6442.54 "Игорь Лабутин" У меня GIT либо command-line, либо веб, так сказать, вариант, либо сторонник-клиент, из Visual Studio я GIT-ом практически не пользуюсь. +6442.54 6450.94 "Анатолий Кулаков" Да, у меня похожая ситуация, но судя по картинкам это выглядит все прекрасно, в общем-то, гораздо лучше, чем, например, пул реквесты смотреть в вебке. +6450.94 6453.74 "Анатолий Кулаков" Но надо пересилиться и попробовать, наверное. +6453.74 6471.14 "Игорь Лабутин" Нет, я таким пользуюсь в Райдере, когда я смотрю гитлабовские мерч реквесты, там это называется, там есть специальное расширение, которое позволяет прямо нативно, она подтягивает сразу чек-аутик, нужную веточку тебе, все дифы, сразу все навигации тут же работают, все прекрасно работают, шикарно. +6471.14 6474.06 "Игорь Лабутин" Если в студии сделали так же, это прекрасно. +6474.06 6476.14 "Анатолий Кулаков" Ну вот судя по скриншотам, да, там тоже пытались что-то +6476.14 6477.14 "Игорь Лабутин" подобное сделать. +6477.14 6483.90 "Игорь Лабутин" Ну слушай, мы весь прошлый год в превьюхах, каждое превьюху было что-то улучшение в GIT-е, так что я не удивлен. +6483.90 6498.30 "Анатолий Кулаков" Пятый пункт, вообще не поверите, вот рядом с АИ, девтуннелями, гитхабами, копайлотами стоит такая прекрасная штука, как разноцветные скобочки фигурные. +6498.30 6505.38 "Анатолий Кулаков" Заключается смысл в том, что Visual Studio, кстати, с подачи Мэтта Торгессона, не Мэтта Торгессона, а как главный наш писатель? +6505.38 6506.38 "Анатолий Кулаков" Мэтс Кристенсен. +6506.38 6550.74 "Анатолий Кулаков" Мэтс Кристенсен, да, позаводили Мэтсов, с подачи Мэтса Кристенсена эта штука появилась в Visual Studio, естественно, я сначала плагин под ним написал, штука, которая позволяет вам раскрашивать фигурные скобочки, ну открыть-закрыть блок в разные цвета, и дает это два преимущества, во-первых, вы видите фигурные скобочки, они у вас выделяются, и во-вторых, вы вложенность, видите уже вложенные фигурные скобочки, вы уже видите совершенно другим цветом, да, и это визуально помогает вам улучшить читабельность и улучшить идентификацию скобочек друг от друга, то есть пару ей найти очень быстро визуально, и это по мнению Джеймса, в общем, достойная мега фича, которую срочно стадо упомянуть, и он не понимает, как он без этого раньше жил. +6550.74 6553.66 "Игорь Лабутин" Ну, может, код у него такой, с кучей скобочек он пишет. +6553.66 6556.42 "Анатолий Кулаков" Ну, код с кучей скобочек у нас у всех, да. +6556.42 6562.06 "Игорь Лабутин" Слушай, ну следующая ему тоже, spellcheck, ну блин, spellcheck, как бы, что такое? +6562.06 6567.14 "Анатолий Кулаков" Ну, да, он есть у многих, просто в Visual Studio недавно появился, я, например, тоже живу долго с spellcheck. +6567.14 6571.66 "Игорь Лабутин" Сколько у меня ошибок оказывается, да, сказал он, ну какая полезная штука, ну да. +6571.66 6577.78 "Игорь Лабутин" А вот следующая мне, кстати, даже непонятна на самом деле, давай вот я так быстро перебрыгну. +6577.78 6585.10 "Игорь Лабутин" Это accessibility checker, если ты говоришь, что он в основном про мобильную разработку, а тут в основном про ВПФ, насколько я вижу. +6585.10 6589.42 "Анатолий Кулаков" Ну, он про мобильную разработку в терминах Xamarin, а Xamarin это +6589.42 6591.42 "Игорь Лабутин" ВПФ, поэтому что-то удивляешься. +6591.42 6592.42 "Игорь Лабутин" Ладно, хорошо. +6592.42 6609.34 "Анатолий Кулаков" Ну то есть accessibility checker довольно полезная вещь, она умеет сканировать ваши десктопы визуальные там или мобильные, короче, любое приложение, у которого есть разметка визуальная, юайка, которая есть, правильно сказать, да, и подсвечивает вам какие-то ошибки, которые можно устранить и которые можно прооптимизировать для лучшей доступности. +6609.34 6610.34 "Анатолий Кулаков" Прикольно. +6610.34 6617.14 "Анатолий Кулаков" Восьмой пункт, это его вдохновляет, тотнет эспайр и всё, что с ним происходит, в общем, без эспайра ни на одной темы ни одного дня у нас. +6617.14 6618.82 "Анатолий Кулаков" Ну, надо же профушить. +6618.82 6619.82 "Игорь Лабутин" Ну, наверное, да. +6619.82 6620.82 "Игорь Лабутин" Да, все дела, да. +6620.82 6638.66 "Анатолий Кулаков" Несмотря на то, что у них там есть эспайр-темплейт, который позволяет вам создавать новые проекты, вы также можете добавить эспайр в существующие проекты благодаря Visual Studio, и также ему нравится, что там прекрасные дефолты есть, которые подключают сразу и трейсинг, и метрики, и дают красивые дашборды, и всё это красиво без единой там нажатия кнопочки. +6638.66 6641.10 "Игорь Лабутин" Звучит, как типичный рекламный текст. +6641.10 6642.10 "Анатолий Кулаков" Давай дальше. +6642.10 6643.10 "Анатолий Кулаков" Это точно. +6643.10 6663.62 "Анатолий Кулаков" Visual Studio UI Refresh, я долго думал, кто там рефрешит у Visual Studio что-то, оказывается, Visual Studio в прошлом году сильно улучшило свой дизайн, он теперь стал более современным, например, появились скругленные уголочки, табики начали вести себя немножко по-другому, и подтянулись новые темы, и также эти темы прооптимизировались. +6663.62 6664.62 "Анатолий Кулаков" Прекрасно. +6664.62 6665.62 "Анатолий Кулаков" Да. +6665.62 6671.70 "Анатолий Кулаков" И последний, десятый пункт – это C# WebKit for Visual Studio Code. +6671.70 6672.70 "Игорь Лабутин" Давай, DevKit. +6672.70 6674.54 "Игорь Лабутин" Всё-таки не WebKit, а DevKit. +6674.54 6678.34 "Игорь Лабутин" Это, да, набор плагинов для VS Code. +6678.34 6698.46 "Анатолий Кулаков" Для Visual Studio, который над Language Service, настраивает вам нормальный Solution Explorer, даёт хорошие темплейты, тест Discovery, тест Solution, дебаггинг хороший, IntelliSense тот же самый подключает, в общем, делает практически вот из Visual Studio Code полноценную Visual Studio, ну, по крайней мере, пытается на том Language Service, который у неё есть. +6698.46 6712.78 "Игорь Лабутин" Нет, ну там как раз Language Service это неплохой, потому что, я так понимаю, что они туда тянут свой, который закрытый и хороший, а я так понимаю, что эта цель как раз какая-никакая замена в Visual Studio for Mac, потому что таким образом на VS Code вы можете нормально писать. +6712.78 6715.66 "Игорь Лабутин" Ну, кроссплатформенной версии, да, что-то такое. +6715.66 6716.66 "Игорь Лабутин" Да, да. +6716.66 6717.66 "Игорь Лабутин" Давай, у тебя три минуты. +6717.66 6721.82 "Игорь Лабутин" У меня три минуты, так у меня же тема называется «Кратко о разном». +6721.82 6722.82 "Игорь Лабутин" Никаких проблем. +6722.82 6723.82 "Игорь Лабутин" Кратко так кратко. +6723.82 6740.16 "Игорь Лабутин" Во-первых, вышла статья от Джеймса Ньютон Кинга про то, что, напоминаем, что у нас, у Майкрософта есть очень классные дэшбордики для графана, то есть Aspire это, конечно, хорошо, но графану мы не забываем. +6740.16 6748.20 "Игорь Лабутин" Короче, есть репозитории, где лежат полезные дэшборды, которые очень круто показывают состояние вашего Asp.NET приложения. +6748.20 6752.88 "Игорь Лабутин" Так что, если вы пользуетесь графаной и пишете на дот.нете Asp.NET приложение, посмотрите обязательно. +6752.88 6760.56 "Игорь Лабутин" И вторая новость это, если вы не знаете, есть такой, не знаю, продукт, библиотека, Enquire. +6760.56 6761.56 "Игорь Лабутин" Кто он? +6761.56 6762.56 "Игорь Лабутин" Библиотека, мне кажется. +6762.56 6763.56 "Игорь Лабутин" Библиотека или фреймворк. +6763.56 6764.56 "Игорь Лабутин" Фреймворк, да. +6764.56 6765.56 "Игорь Лабутин" Вот такое. +6765.56 6773.24 "Игорь Лабутин" Это все, всякие там про таймеры, запуск, про расписание, вот это все, короче, шедулер, вот все вокруг этого. +6773.24 6779.88 "Игорь Лабутин" Они написали библиотечку, которая называется Kronos, которая позволяет на дот.нете парсить крон-экспрессион. +6779.88 6791.44 "Игорь Лабутин" То есть, если вот эти все ваши стандартные там, один звездочка-звездочка-звездочка-звездочка, вот это все, библиотечка, которая позволяет это все распарсить, причем она поддерживает ряд кастомизаций, там интервалы можно задавать. +6791.44 6817.12 "Игорь Лабутин" Поддерживает нормальный парсинг, поддерживает нормальный удобную API-шку вида, а дай мне, пожалуйста, когда случится следующее событие согласно этому крону от текущего момента, или дай мне, пожалуйста, все события, которые случатся в интервале ближайший год для вот этого крон-выражения, и он вам вернет набор дэйт таймов, когда же случится то, что должно было случиться по вашему запрограммированному крону. +6817.12 6828.92 "Игорь Лабутин" Короче, если пользуетесь вдруг крон-синтаксисом зачем-то, посмотрите на кроны, скажется, что это довольно неплохая библиотека от чуваков, которые знают, что такое шедулеры и явно, скорее всего, парсить крон умеют. +6828.92 6832.40 "Анатолий Кулаков" Да, судя по фичам, очень крутая библиотечка, стоит +6832.40 6833.40 "Игорь Лабутин" попробовать. +6833.40 6874.96 "Игорь Лабутин" Ну, на этом все, мы посмотрели на DotNet 9 Vision, посмотрели на DotNet 9 Preview 1, узнали, как мы собираемся ломать C# 13-й версии, посмотрели на Visual Studio 20.22, 17.9 и 17.10 Preview 1, узнали у Эндрю Лока очередной раз, как же мы можем настраивать урлы и порты для Espanet Core приложения, посмотрели на новинки Aspire Preview 3, поразмышляли об категориях ошибок, об ошибках категорий вместе с Марком Симоном, ну и узнали крутые 10 новых фич в Visual Studio за 2023 год, по мнению Джеймса Монтеманио. +6874.96 6876.88 "Игорь Лабутин" И на этом все. +6876.88 6883.32 "Анатолий Кулаков" Всем до новых встреч, лайки, шарики, репосты, ждём ваших комментариев, присылайте письма, всем пока. +6883.32 6883.96 "Анатолий Кулаков" Всем пока. diff --git a/input/Radio/Transcriptions/RadioDotNet-96.txt b/input/Radio/Transcriptions/RadioDotNet-96.txt index 76b4aac..a5530a0 100644 --- a/input/Radio/Transcriptions/RadioDotNet-96.txt +++ b/input/Radio/Transcriptions/RadioDotNet-96.txt @@ -1,694 +1,692 @@ -0.00 16.42 SPEAKER_01 Здравствуйте, уважаемые слушатели, в эфире Радио.нет и выпуск номер 96, и в студии постоянный ведущий Анатолий Кулаков. -16.42 17.42 SPEAKER_00 И Игорь Лобутин. -17.42 18.42 SPEAKER_00 Всем привет. -18.42 37.10 SPEAKER_01 А за нашей студией наши помогаторы, а именно Александр Сергей, Владислав Шевченко, Антон Гурий-Самарин, Лазарев Илья, Виктор, Руслан Артамонов, Александр Ярыгин, Сергей Бизенко, Александр Лаперлин, Ольга Бондаренко, Дмитрий Сорокин, Сергей Краснов, Константин Ушаков, Андреев Азлеев и Бальсима Альджавахири. -37.10 42.18 SPEAKER_01 Спасибо всем, кто нас поддерживает, а также шарит, репостает и комментирует. -42.18 50.02 SPEAKER_01 Поэтому, если вдруг вы никогда не заходили к нам на YouTube, приходите, там у нас разворачиваются интересные дискуссии, некоторые даже полезные. -50.02 59.54 SPEAKER_01 В общем, часто повторяю, поправляют нас и доносят какую-то дополнительную информацию, поэтому как дополнение к выпуску вполне хороший источник. -59.54 62.38 SPEAKER_00 Ну, давай на самом деле начинать потихонечку. -62.38 68.82 SPEAKER_00 Новостей от Майкрософта у нас особо нету, ничего такого не вышло, превью пока не вышло. -68.82 74.74 SPEAKER_00 Скорее всего оно, конечно же, выйдет на следующий день после записи подкаста, но тут уж ничего не поделаешь, придётся ждать следующего выпуска. -74.74 76.78 SPEAKER_00 А пока давай пойдём в статьи. -76.78 78.94 SPEAKER_01 Зато мы можем посвятить выпуск статейчикам. -78.94 79.94 SPEAKER_01 Да. -79.94 92.98 SPEAKER_01 Не каждый раз, когда у нас много новостей, мы доходим до каких-то полезных статей, а тут вот вытащили пачку того, что вам может быть полезно в повседневной жизни, и что как раз-таки не зависит от времени, поэтому этот выпуск можно будет прислушивать вечно, и пойдём по статейчикам. -92.98 97.74 SPEAKER_00 Ну, может быть, не совсем вечно, но действительно полезные статьи у нас попались. -97.74 101.86 SPEAKER_00 И первая статья про EF Core и про миграции. -101.86 121.26 SPEAKER_00 Мы довольно много говорим про EF Core, точнее, не то чтобы много на самом деле, потому что в релиз ноутсов дотнета обычно EF Core уделяется довольно мало времени, там довольно куции какие-то, одна-две-три фичи описывается, остальное говорите, идите смотрите changelog, и поэтому довольно подробно мы про него практически никогда и не говорим. -121.26 123.18 SPEAKER_01 Мы же не пойдём смотреть changelog? -123.18 134.54 SPEAKER_00 Нет, мы не пойдём смотреть changelog, мы пойдём смотреть статью, которая довольно неплохо, обзорно описывает то, что можно и как можно работать с миграциями в EF Core. -134.54 139.42 SPEAKER_00 И давайте для начала просто сообразим и вспомним вообще, что это такое миграция и зачем нам оно надо. -139.42 182.86 SPEAKER_00 То есть понятно, что EF Core, там ORM составляет запросы, всё такое прочее, значит, облегчает маппинг ваших результатов запросов обратно в объекты, это всё здорово и полезно, но только в тот момент, когда у вас уже есть база данных, или даже когда она у вас уже есть, вам её иногда нужно менять, и можно это, конечно, делать как-то отдельно, можно руками, можно даже отдельно прям без каких-либо скриптов менять прям впроди на живую схему базы данных, в принципе, такое делали раньше, когда-то давным-давно, наверное, но это всё очень понятно ведёт к ошибкам, ведёт к тому, что у вас будут разные схемы баз данных там-сям, требует времени, в общем, дико неудобно, поэтому нужно автоматизировать. -182.86 187.98 SPEAKER_00 Автоматизируется это всё обычно с помощью концепции, которая называется миграцией. -187.98 204.26 SPEAKER_00 Это довольно общая концепция, не то чтобы она связана как-то с EF Core конкретно, то есть это просто некоторый способ записать то, как вам нужно изменить базу данных в виде некоторых скриптов, тем или иным способом. -204.26 252.94 SPEAKER_00 Есть способы, когда вы описываете то, что вы хотите получить конечный результат, дальше некоторый тул волшебным образом пытается подумать, как же привести вашу базу данных именно в такое состояние, но, к сожалению, в большинстве случаев миграции так просто без некоторого программистского раздумья автоматически изгенерить не очень получится, потому что данные, которые хранятся в базе, как правило, довольно ценные и случайно, неправильно собранные, неправильно автоматически изгенеренные миграции всё испортить не очень здорово, поэтому, как правило, всё-таки они пишутся плюс-минус руками, ну так, полуавтогенерация, сейчас про это немножко расскажу, но обязательно требуют какого-то ревью и после этого можно их уже коммитить и использовать в плюс-минус автоматизированных скриптах во время раскатки вашего приложения. -252.94 271.26 SPEAKER_00 Причём здесь Евкор, Евкор здесь при том, что Евкор предоставляет свою собственную, так сказать, модель миграции, то, как вы можете описать то, что вы хотите изменить в вашей базе данных, при том, что большинство вещей можно писать на плюс-минус понятном и знакомом C#. -271.26 327.44 SPEAKER_00 Понятно, что могут быть случаи, когда вам C# не хватит и придётся возвращаться уже к SQL, но в целом большинство вещей, не требующих каких-то суперхитрых тюнингов базы данных, справятся с обычным C#, что даёт дополнительное преимущество, что эта миграция может быть применима вообще к любой базе данных, которая поддерживается, понятное дело, Евкором, что, наверное, не то чтобы сильно полезно для продуктов, которые вы ставите куда-то на сервера, но может быть полезно, если вы это делаете в каком-нибудь коробочном продукте, который ставится в какую-нибудь организацию, например, просто так и который в таком случае в качестве полезной фичи может иметь свойство работать на, не знаю, Oracle, SQL Server, PostgreSQL, MySQL, в общем, подставьте сюда любую более-менее плюс-минус поддерживаемую базу данных, которая, например, уже есть в компании, гораздо приятнее. -327.44 348.56 SPEAKER_00 В целом, по Евкору есть довольно неплохая документация от самих Microsoft, она вся очень хорошая и понятная, но в статье дается, так скажем, необходимый минимум для понимания того, что со всем этим делать, как с этим обращаться, и поэтому мы по ней пробежимся. -348.56 351.20 SPEAKER_00 Для начала надо понять, как эти миграции создавать. -351.20 367.42 SPEAKER_00 Значит, если вы работаете с Евкором, у вас уже наверняка есть db.context, у вас есть наверняка какие-то entities, через которые вы общаетесь с базой данных, и для того, чтобы создать вашу первую миграцию, можно сделать одну простую штуку. -367.42 372.98 SPEAKER_00 Нужно позвать некоторую command line тулзу, которая вам создает эту самую миграцию. -372.98 383.88 SPEAKER_00 Способов позвать эту тулзу, на самом деле, несколько, можно использовать .NET Global Tool, там, соответственно, .NET EF и дальше, все, что связано с миграциями, либо есть PowerShell. -383.88 391.00 SPEAKER_00 Статья использует PowerShell, команды в PowerShell, это, соответственно, это addMigration, и дальше название вашей миграции. -391.00 410.92 SPEAKER_00 Как правило, первая миграция называется createDb, потому что первое, что она сделает, она, имея на руках ваше определение entities, то есть всех, по сути, табличек, колонок и там, связи между ними, с которыми работает именно ваше приложение, она создаст некоторый кусочек кода. -410.92 414.16 SPEAKER_00 На самом деле, она создает класс, который наследуется от класса migration. -414.16 417.24 SPEAKER_00 В этом классе есть два метода, up и down. -417.24 427.80 SPEAKER_00 Up — это, соответственно, когда вы будете применять эту миграцию для того, чтобы смигрировать базу данных из старой версии в новую, down, соответственно, наоборот, если вам нужно домигрейтить базу обратно. -427.80 445.36 SPEAKER_00 И в этих методах, up и down, она сгенерит некоторое тело методов, которые будут, по сути, создавать базу данных необходимую и достаточную для того, чтобы ваше entity, ваше приложение, которое работает с теми entities, обязательно в DB-контексте, могло работать. -445.36 454.84 SPEAKER_00 Понятное дело, что, возможно, там нужны какие-то дополнительные индексы, возможно, вам нужны какие-то дополнительные хранимые процедуры, view, функции, ну, все, что угодно нестандартное. -454.84 462.84 SPEAKER_00 Такие штуки придется добавлять руками, но базовый набор там таблицы и колонок она создаст и связи между ними. -462.84 488.76 SPEAKER_00 Дальше это все, конечно, хорошо и здорово, таким образом, вы можете создать первую миграцию, как правило, первая миграция более-менее адекватна, вот, исключением всяких специальных SQL вещей, либо каких-то кастомизаций, которые вы знаете, что вы будете запускаться только на Postgres, и вы хотите сразу кастомизировать создание базы именно под Postgres, дополнив его какими-то специфическими позгоревыми штуками. -488.76 492.68 SPEAKER_00 Но дальше нужно эту миграцию кастомизить, как правило. -492.68 512.32 SPEAKER_00 Вы точно так же можете говорить add migration, даже когда у вас уже есть другие миграции, и в этот момент, на самом деле, EF Core будет поднимать некоторый временный контекст базы данных, смотреть, что у вас есть сейчас в вашей базе данных, которую вы укажете connection строкой, и сравнивать это с тем, что есть в модели данных, которую вы написали в коде. -512.32 534.52 SPEAKER_00 То есть вы в коде дописываете, допустим, новое поле в какой-нибудь entity, говорите EF, там, migration, add, и имя новой миграции, и после чего EF Core сравнит базу данных с новым набором классов entity и добавит или что-то изменит в вашей схеме базы данных, добавит код, который будет изменять схему базы данных. -534.52 535.52 SPEAKER_00 В чем проблема? -535.52 538.84 SPEAKER_00 Проблема в том, что этот код может быть довольно наивен. -538.84 548.28 SPEAKER_00 То есть одно время, я не помню, сейчас поменялся это или нет, по-моему, это все-таки пофиксили, но одно время, если, например, вы переименовываете колонку в базе данных, EF Core генерил довольно простую штуку. -548.28 550.92 SPEAKER_00 Он сначала дробил колонку, потом добавлял колонку с новым именем. -550.92 563.52 SPEAKER_00 Формально миграция верная, фактически миграция ведет к потере данных, поэтому понятно, что, как правило, вы это меняли на явный вызов функции renameColumn, которая делает это без потери данных. -563.52 581.28 SPEAKER_00 Особенно, когда мы говорим про down-миграцию, т.е. когда мы говорим, что нам нужно что-нибудь откатить обратно, если вы в миграции drop-аете колонку, которая по какой-то причине вам стала не нужна, то понятно, что в down-миграции вы уже никакую колонку ниоткуда не восстановите. -581.28 594.72 SPEAKER_00 И некоторые миграции однонаправленные, либо некоторые миграции нужно смотреть, как делать, если вам действительно нужно уметь откатиться, колонку, не знаю, переименовывать во что. -594.72 607.68 SPEAKER_00 Я даже не знаю, я обычно исповедую подход, что down-миграции никогда не надо, всегда движемся только в сторону up, потому что на моей практике как-то редко были случаи, когда нужны были именно down-миграции. -607.68 610.20 SPEAKER_01 Ну действительно, они пригождаются практически никогда. -610.20 621.04 SPEAKER_00 И мне кажется, что как только они потребуются, это будет как раз тот случай, где типа drop-колонка был, и down-миграция тебе ничего не даст, всё равно восстановить колонку не получится. -621.04 622.04 SPEAKER_00 Да-да. -622.04 642.00 SPEAKER_00 Для того, чтобы кастомизировать, там есть довольно шикарный набор fluent API, т.е. вы пишете NaVi, Sharpie, но если вам нужен прям кастомный SQL, то там есть метод под названием SQL, незамысловато названый, куда передаётесь просто строчку с SQL, куда можно записать любой кастомный SQL, который вы хотите. -642.00 649.64 SPEAKER_00 Ну допустим, вы создали миграцию, вы написали набор миграции, теперь в вашем приложении есть пачка миграций. -649.64 665.20 SPEAKER_00 Это некоторый набор C# файликов или возможно рядом лежащих там SQL скриптов, которых вы заполняете внутри вот этого SQL метода, и надо, собственно, понять, а как применять-то, что со всем этим делать, как же это применять. -665.20 675.64 SPEAKER_00 Ну, первый способ, он такой довольно прямой, в лоб, я его практически не видел, чтобы он когда-либо использовался, но он есть. -675.64 684.76 SPEAKER_00 Можно сделать это, давайте не так, давайте прежде чем говорить, как это можно сделать, поговорим, когда это нужно делать, потому что может быть это более важно. -684.76 701.80 SPEAKER_00 Вот у нас есть наше приложение, вы как-то поменяли код, чтобы оно работало с, требовало каких-то новых фич от базы данных, у вас даже в коде есть миграция, которая говорит о том, как же это нужно сделать, чтобы привести базу в новое состояние, но вопрос, когда же это делать. -701.80 717.72 SPEAKER_00 Есть несколько вариантов, вариант, точнее как, вариант такой, что ваш код, скорее всего, в любом случае ждет так или иначе каких-то новых фич от базы данных, иначе зачем миграция, если код работает все еще со старой версией. -717.72 720.64 SPEAKER_00 Могут быть случаи, когда это нужно, но это большая редкость. -720.64 730.88 SPEAKER_00 Например, добавление индекса, в принципе его можно делать как угодно, от этого работа кода с точки зрения корректности не пострадает, возможно скорость где-то улучшится или ухудшится. -730.88 743.96 SPEAKER_00 Но предположим, что у нас есть изменения, которые требуют такое, так что нам нужно, чтобы новый код работал с новой схемой базы данных, желательно тогда миграцию провести перед тем, как приложение стартует. -743.96 770.96 SPEAKER_00 Это все понятно, но у нас в нашем современном мире кубернетес и прочих горизонтально масштабируемых сервисов есть проблема с тем, что довольно многие используют так называемый rolling upgrade, то есть когда вы кубернетесу говорите вот новая версия нашего контейнера, давай мы его раскатим аккуратненько, и кубернетес по очереди накатывает один код, выключает один из старых, накатывает еще один новый, выключает один из старых. -770.96 780.72 SPEAKER_00 То есть у нас есть некоторое время, когда у вас с одной стороны работает старый код, с другой стороны работает новый код, и при всем при этом миграция уже должна быть как бы проведена. -780.72 782.96 SPEAKER_00 Отсюда следует несколько важных выводов. -782.96 787.28 SPEAKER_00 Во-первых, которые не совсем связаны прямо с EFCore, они применимы к любым миграциям. -787.28 798.44 SPEAKER_00 Когда вы пишете ваши миграции, делайте так, чтобы эти миграции не нарушали работу старого кода, то есть желательно старый код, чтобы продолжала работа, добавляйте новую колонку обязательно с каким-нибудь там дефолтным значением. -798.44 808.96 SPEAKER_00 Добавляйте и там, и nullable она должна быть, добавляйте, или там убирайте колонку, нельзя убирать колонку до тех пор, пока старый код ее хоть как-то использует. -808.96 819.52 SPEAKER_00 Даже если вам очень хочется и вы знаете, что в новом коде она вам больше не нужна, придется потерпеть, сначала раскатить новый элис, который не использует колонку и уже в следующей миграции, в следующем апгрейде удалить колонку. -819.52 822.84 SPEAKER_00 Ну вот такие случаи, в общем, надо понимать и надо отслеживать. -822.84 839.32 SPEAKER_00 Тот факт, что обе версии кода могут работать, но фактически это означает, что миграция будет выполняться по сути параллельно с работающим кодом, то есть у нас работают старые коды, например, если мы в кубере, нам нужно накатить миграцию, пока они работают, а потом раскатывать нужную версию. -839.32 850.80 SPEAKER_01 Это очень похоже, например, если мы задумывались, когда мы обсуждали версионирование в API, мы тоже там советовали не делать breaking changes, не убирать те поля, которые могут юзаться каким-то внешним системами. -850.80 854.36 SPEAKER_01 А здесь вы 100% знаете, что ваше поле юзается какой-то системой. -854.36 860.60 SPEAKER_01 И в принципе вот все те же правила по постепенной миграции, про избегание breaking changes и так далее, они сюда очень хорошо ложатся. -860.60 876.68 SPEAKER_00 Все так, все так, но на самом деле при апгрейдах баз данных очень рекомендую иногда поспрашивать о ваших DBA, не настроили ли они какую-нибудь там репликацию в какое-нибудь DWH-хранилище вашей схемы, потому что выяснится, что вы проапгрейдите схему, у них сломается репликация. -876.68 915.12 SPEAKER_00 Я встречал такое как-то в одном из проектов, что как-то нужно было замутить какие-то отчетики, но те, кому нужно было, они сказали, ну есть BD, давайте админ, и вы нам это, реплицируйте просто в наше хранилище, все нормально, мы по ним сами сколько будем строить, не нагружая основную базу, ну хорошо же, хорошо, репликация ресурсов особо не жрет, ну как бы, по крайней мере не тормозит основную BD, она может запаздывать, если ресурсов не хватает, но в целом как бы основную работу приложения не тормозит, все хорошо, но мы поменяли схему и сломали отчеты, такое бывает, знайте кто вами пользуется, это тоже в каком-то смысле API может быть, хоть и не очень удобный. -915.12 938.28 SPEAKER_00 Ну вот, возвращаясь к тому, когда же запускать, есть простой способ, который вы увидите, наверное, во всех примерчиках простых на EFCore, можно в самом начале вашего приложения, до того как-то вы там начали слушать ваши контроллеры, сказать, дорогой, значит, EFCore, сделай так, чтобы мы убедились, что база данных на месте. -938.28 1031.32 SPEAKER_00 Мигрейт, что-то там, migrate_db_async, по-моему, называется, не помню, я особо не пользуюсь этим методом, поэтому точное название не помню, но в общем есть там такой метод, функция, который просто приведет в состояние, что точная база данных на месте, но вспоминаем наш предыдущий пойнт про то, что, во-первых, у вас может быть несколько инстансов приложения, и если вы в Кубере такое запустите, то каждый из подов, допустим, у вас довольно большие лимиты на тему масштабирования, и тогда в момент роллинга апгрейдов, Кубернет сможет, на самом деле, по нескольку подов за раз новые версии закидывать в запускаемые, и в таком случае все они побегут обновлять базу данных, конечно же, все эти миграции, ну, как бы, там есть вариант, как сделать такую глобальную блокировку на уровне всех миграций, чтобы только один под смог что-то обновить, но дальше возникнет вопрос, что пока он обновляет, все остальные тупо ждут, у позгрессов, у Кубернетеса есть некоторые лимиты на тайм-аут, на поднятие подов, ну, в общем, там могут возникнуть всякие разные проблемы, а миграции бывают долгие, надо сказать, очень долгие, особенно если вы там перелопачиваете всю табличку, то не знаю, индексы какие-нибудь навешиваете, это может быть очень долго, поэтому не очень хороший способ, кроме того, миграция может упасть, и тогда у вас как-то вроде это, приложение непонятно, то ли стартовать, то ли не стартовать, если не стартовать, то у вас под свалится, Кубернетес его снова попробует поднять, он снова попробует смигревать, что он там натворил в бд, ну, не очень понятно, вот. -1031.32 1050.16 SPEAKER_00 При этом такая опция очень удобна для локальной разработки, то есть вот поставить эту штуку под условия их окружения, их environment, development, в принципе, удобно, тогда вы сразу получаете каждый раз обновленную бдшку, если вы миграциями свою локальную бдшку обновляете, ну, что, в принципе, тоже рекомендуется. -1050.16 1051.16 SPEAKER_00 Вот, это один вариант. -1051.16 1071.00 SPEAKER_00 Второй вариант — это некоторый deployment script, ну, то есть у вас наверняка есть некоторая автоматическая CD-система, которая так или иначе разворачивает ваше приложение, это может быть просто какой-нибудь bash скриптик или не баш, на чем-нибудь написано, парашейль скриптик, там, это может быть Octopus, это может быть кто угодно другой, который разворачивает ваше приложение. -1071.00 1079.60 SPEAKER_00 Можно туда, до того, как вы попросили, не знаю, кубер или еще что-то, развернуть ваше приложение, впилить, соответственно, запуск некоторого deployment скрипта. -1079.60 1093.64 SPEAKER_00 Это, в принципе, неплохой вариант, мы им пользовались довольно долго в случае, когда вы живете не в Кубернетесе, а именно просто разворачиваете ваше, не знаю, приложение в одном единственном экземпляре ваш большой монолит. -1093.64 1103.20 SPEAKER_00 Вполне нормальный вариант, если что-то в базе данных не смогло прогрейдиться, ну, ваш deployment упадет, дальше приложение не пойдет разворачиваться, все нормально, пойдете фиксить. -1103.20 1109.28 SPEAKER_00 Риск в том, что если апгрейд упал в базе данных, то база данных может быть в каком-нибудь странном состоянии, так он и всегда есть. -1109.28 1120.32 SPEAKER_00 От этого риска, к сожалению, мне кажется, никак особо не избавится, кроме как предварительного тестирования на каком-нибудь хорошем бэкапе, который у вас есть, для рисковых и длинных апгрейдов. -1120.32 1139.00 SPEAKER_00 И последний вариант, если вы живете в Кубернетесе, то тогда есть, точнее, предпоследний вариант, если вы живете в Кубернетесе, то тогда у вас есть вариант сделать отдельный так называемый init-контейнер и применить еще некоторые штуки под названием jobs. -1139.00 1155.52 SPEAKER_00 Я сейчас проверю, нет, у меня нет ссылки, я потом повешу ссылочку еще, добавлю в шоу-ноуты, ссылочку на статьи Koindrelog, мы ее не рассматривали подробно, потому что она все-таки не совсем по профилю нашего подкаста, она там продолжает немножко, но в основном про диплоймент. -1155.52 1199.60 SPEAKER_00 Там есть хорошая статья, как как раз-таки диплоить Asp.core-приложение с миграциями в Кумбер с использованием jobs и init-контейнеров, то есть jobs — это некоторая сущность, коллекция подов, которая просто исполняется от начала и до конца, но, возможно, с ретраями, и дальше нужно просто сделать так, чтобы ваша миграция выполнялась как java, а каждый контейнер с помощью концепции называемой init-контейнера ждал, пока эта java закончится, и тогда у вас приложение будет спокойно ждать, это не входит во всякие вот эти вот стартовые пробы Кумбера, соответственно, оно спокойно дождется, пока java-миграция закончится, в единственном экземпляре она одна будет, и все контейнеры, которые ее ждут, спокойно запустятся. -1199.60 1204.24 SPEAKER_00 Вот, прекрасная штука, хорошо работает в окружении, когда у вас Кумбер. -1204.24 1226.12 SPEAKER_00 Вот, и есть еще один способ, он, в принципе, немножко пересекается с дипломинскриптом, потому что в дипломинскрипте вам как-то что-то надо сделать все-таки, вот, то давайте теперь поймем, а как вот нам в дипломинскрипте надо что-то запустить, давайте теперь мы плюс-минус выяснили, когда нужно запускать, точнее, какие у нас есть варианты, теперь давайте поймем как. -1226.12 1234.20 SPEAKER_00 Ну, в случае со стартапом, я уже сказал, там все просто, вызываем код и db.context.database.migrate, и все нормально, это работает. -1234.20 1237.76 SPEAKER_00 В остальных же случаях надо понять, что можно делать. -1237.76 1263.96 SPEAKER_00 Первый случай можно сделать через sql script, у вас есть некоторая либо PowerShell, либо опять же через .NET EF Tool команда, называется, если в PowerShell варианте, script.migrate, script.migration, в которой указывается, от какой миграции и до какой нужно сгенерить скрипт, можно не указывать миграции, а, главное, сгенерить скрипт вообще на все, такое с нуля до последнего состояния, ну, в общем, интервал указывайте. -1263.96 1269.28 SPEAKER_00 И он генерирует sql script, который соответствует ровно тем миграциям, которые вы выбрали. -1269.28 1282.00 SPEAKER_00 Проблема в том, что по дефолту он генерирует не идемпотентный скрипт, то есть если в скрипте написано create table, в смысле, что он понимает, что нужно создать табличку, в скрипте так и будет написано create table, без всяких условий, без всего. -1282.00 1304.44 SPEAKER_00 Это не очень здорово, потому что могут быть ситуации, когда этот скрипт будет накатываться, пытаться накатываться несколько раз из-за каких-то переповторов, лучше всегда передавать ключик idempotent, тогда он каждую миграцию будет оборачивать в некоторые условия, проверить, то есть он понимает, что если нужно создать табличку, то он делает, если табличка не создана, если добавить колонку, он будет проверять, что колонка не добавлена. -1304.44 1316.56 SPEAKER_00 Я, кстати, не знаю, какие условия он вставляет, если там вставки просто .sql, вот этого я что-то не помню, по-моему, он ничего не делает и тупо их выполняет, это ответственность разработчика, сделать так, чтобы эти вставки были идемпотентными. -1316.56 1329.60 SPEAKER_00 То есть вы того, вы можете просто генерить .sql скрипт, например, в билдтайме, положить его вместе с артефактами вашего приложения и в диплоймент скрипте его выполнить, это один вариант. -1329.60 1357.92 SPEAKER_00 Второй вариант можно, если у вас есть исходники вашего приложения, можно просто сказать dotnet.ef.update_database, по-моему, либо PowerShell.update_database вызвать, указать туда, до какой миграции нужно докатить, указать connection string и .net.ef.tool поднимет кусочек вашего приложения, поднимет db.context, поднимет connection string и накатит все эти миграции как нужно. -1357.92 1362.12 SPEAKER_00 Это способ, если у вас исходнички рядом. -1362.12 1371.68 SPEAKER_00 Ну и последний вариант, который как раз таки максимально подходит для варианта с кубером, ну впрочем для диплоймента скрипта он тоже подходит, это называется migration_bundles. -1371.68 1396.96 SPEAKER_00 Это, по сути, некоторое исполнимое приложение, которое вы создаете с помощью команды bundle_migration или dotnet.ef.bundle, оно полностью self-contained, то есть оно не требует никаких исходников, ничего-ничего-ничего, то есть это просто полностью готовое приложение, которое единственное, что нужно передать connection string и оно накатит тот набор миграций, который вы выбрали, на заданную bd с заданным connection string. -1396.96 1406.32 SPEAKER_00 Вот такой бандл уже можно упаковать в контейнер, можно упаковать тоже как артефакт вашего сборки, чтобы отдать его диплоймент скрипту и он уже накатит. -1406.32 1415.40 SPEAKER_00 Вроде как Microsoft считает, что это чуть ли не самый лучший вариант сейчас, не знаю из каких соображений, но вот я из того, что видел, они довольно активно его именно продвигали. -1415.40 1428.72 SPEAKER_00 Ну понятно, что как бы от простого command line отличается тем, что не нужно тащить исходники все, от SQL скрипта не знаю чем отличается, возможно каким-то более расширенным логированием или еще чем-то, вот. -1428.72 1438.68 SPEAKER_00 Ну а из кода db.context.db.is_migrate я подозреваю, что бандл делает ровно то же самое, но просто в более контролируемом и self-contained окружении. -1438.68 1444.48 SPEAKER_00 Вот примерно такая штука с миграциями EF Cora. -1444.48 1450.80 SPEAKER_00 Признаться, мы только на одном проекте использовали миграции EF Cora, в основном я пользовался другими тулами для миграций. -1450.80 1455.76 SPEAKER_00 Я не знаю, Только есть что добавить именно про EF миграции? -1455.76 1458.88 SPEAKER_01 Наверное нет, кроме того, что мы везде используем EF миграции. -1458.88 1462.44 SPEAKER_01 Почему-то на другие тулзы и не осмотрели, наверняка пока хватало. -1462.44 1464.00 SPEAKER_01 Что тебя на них натолкнуло? -1464.00 1473.48 SPEAKER_00 Я не помню, что нас натолкнуло, вот EF миграции мы использовали в проекте, в котором мы с нуля все это делали, в остальных, видимо, оно уже просто было и поэтому просто не переделывали. -1473.48 1475.48 SPEAKER_00 Значит, что есть из других тулов? -1475.48 1484.56 SPEAKER_00 С двумя тулами я встречался, один это Fluent Migrator, это даже не тул, они это гордо называют Migration Framework. -1484.56 1500.88 SPEAKER_00 По сути, там подход похожий на Entity Framework, то есть там тоже для миграции задаются классы, они наследуются от некоторого специального базового класса, там их несколько вариантов есть, для двухсторонних миграций как раз таки, ну с Up и Down есть односторонние, какие-то вариантики есть. -1500.88 1506.80 SPEAKER_00 И есть еще отдельный раннер, то есть это некоторый тоже класс, который позволяет эти все миграции заранить. -1506.80 1516.84 SPEAKER_00 Вы можете этот класс использовать внутри вашего приложения, либо классический подход это написать отдельную маленькую консольную тулзу, которая возьмет этот раннер и, соответственно, применит все миграции. -1516.84 1522.88 SPEAKER_00 То есть это просто набор некоторых Nuget пакетов, которые вы используете для того, чтобы накатить изменения на вашу базу. -1522.88 1533.28 SPEAKER_00 Максимально похожий на EFCore, просто другой, написан полностью на C#, в общем, если надо, можно смотреть, как он устроен внутри, он сушит на GitHub вот это все. -1533.28 1537.76 SPEAKER_00 Его мы использовали, никаких, в общем, нареканий к нему не было вообще, все прекрасно работало. -1537.76 1542.88 SPEAKER_00 Так же, собственно, и к EFCore у меня тоже особых нареканий в общем-то не было, тоже работало. -1542.88 1565.64 SPEAKER_00 Есть еще небольшая библиотечка на дотнете, это dbUp, она, по сути, предназначена просто для применения SQL скриптов, то есть если вы не хотите писать SQL скрипты или по какой-то причине не пишете апгрейд скрипты миграции на C#, а хотите их писать на SQL, то, может быть, вам и не нужна вся вот эта вот мощь и умения EFCore либо Fluent Migrator. -1565.64 1576.00 SPEAKER_00 Возможно, вам будет достаточно dbUp, это просто некая библиотечка, которая отдается набор из SQL скриптов и говорится, вот мне, пожалуйста, от C# до C# примени, ну и она их применяет. -1576.00 1586.68 SPEAKER_00 С треками, что там применено, что не применено, ну, понятно, все как положено для нормального мигратора, но вот тоже на GitHub, тоже open-source, тоже на дотнете, можно посмотреть. -1586.68 1603.92 SPEAKER_00 Дальше есть тул, которым я не пользовался, называется Grate, Grate как решетка, в смысле, G-R-A-T-E, он тупо выполняет SQL скрипты из папочки, грубо говоря, как я понял по описанию, возможно, тоже кому-то пригодится. -1603.92 1606.92 SPEAKER_00 В общем, похож на dbUp, но dbUp — это библиотечка, это тул. -1606.92 1607.92 SPEAKER_00 Вот. -1607.92 1638.52 SPEAKER_00 Ну и еще в одном проекте, несмотря на то, что он был дотнет, но и у нас использовался Liquibase, Liquibase и Flyway — это тулы, наверное, более известные в мире Java, потому что они написаны на Java, Liquibase точно, Flyway, по-моему, тоже, вот, но они в этом смысле максимально агностик для языка, в смысле, вы не можете написать на C#, конечно, миграции для них, но они там пишутся либо в SQL, либо условно в XML, и поэтому абсолютно все равно, просто, ну, вам нужна Java, да, для того, чтобы запускать эти самые миграции. -1638.52 1645.44 SPEAKER_00 Был у нас проект, где вот они тоже почему-то, видимо, исторически использовались, ну, в принципе, тоже работали прекрасно. -1645.44 1646.44 SPEAKER_00 Вот. -1646.44 1669.16 SPEAKER_00 Вот такой вот у нас сейчас обзор получился разных всяких миграций, то есть если вам хватает EF-корных миграций, просто берете и пользуйтесь, если не хватает, посмотрите в сторону Fluent Migrator, возможно, там что-то будет чуть поудобнее сделано, или вам будет чуть по, не знаю, там можно получше покастомизировать, какие миграции накатывать, какие нет. -1669.16 1681.56 SPEAKER_00 Во Fluent Migrator там была, вот я помню, мы даже пользовались одно время, развесистая система тегов, то есть можно миграции тегать, и типа, не знаю, там разным заказчикам, например, в разных окружениях накатывать разные кусочки. -1681.56 1691.76 SPEAKER_00 У нас таким образом не были миграции, которые были помечали, типа, такие сид данные для автотестов, и вот они накатывались только при указании спецтега, при накатке схемы. -1691.76 1697.40 SPEAKER_01 Ну удобно, да, действительно, когда у тебя такие какие-то сложные процессы, сложные миграции. -1697.40 1710.64 SPEAKER_00 То есть вот он этим, мне кажется, наиболее мощный в каком-то смысле, то есть EF, по-моему, такого, наверняка на EF тоже можно такое написать, понятное дело, да, никто не мешает функции up писать все, что вы хотите, но это все-таки сложнее. -1710.64 1711.64 SPEAKER_00 Такая альтернативная поддержка. -1711.64 1721.04 SPEAKER_00 Ну и остальные они такие попроще, тулы, ну, dbup и graded чисто для SQL скриптов, но, может быть, вам этого тоже будет достаточно. -1721.04 1722.04 SPEAKER_01 Такие дела. -1722.04 1730.76 SPEAKER_01 Ну в Quantity Framework раньше миграции были довольно убогие, то есть мне кажется, вот с тех пор, когда они перелезли там на core и более или менее стабилизировались, то там миграции стали довольно хорошие. -1730.76 1743.04 SPEAKER_01 Ну и опять же, вспоминая, не знаю, мои старые проекты, где мы все миграции писали чисто на SQL скриптах, которые по порядочку складывали в папочки, я до сих пор такого, ну, такого удовольствия от написания миграции не получаю. -1743.04 1748.96 SPEAKER_01 То есть надо признаться, что миграции EF, это все равно там на 80% какая-то дикая магия. -1748.96 1761.04 SPEAKER_01 Если ты раньше мог бы зайти в эти SQL скрипты и посмотреть их и проанализировать каким-то образом или даже сделать им downgrade, если ты захотел бы назад что-то вернуть, вот там все это как-то было возможно. -1761.04 1774.60 SPEAKER_01 В общем-то сейчас EF скрипты, если вы захотите посмотреть, что он там генерирует, какие там вещи делает, иногда волосы там становятся, что, как он эти миграции прокручивает. -1774.60 1780.76 SPEAKER_01 Они все, конечно, работают, все, конечно, хорошо, но это не для того, чтобы пользователь на них смотрел, не для того, чтобы им как-то ручками управлять. -1780.76 1785.04 SPEAKER_01 И это мне, конечно, всегда не очень нравится в EF миграциях. -1785.04 1798.12 SPEAKER_00 Да, именно для этого, я так понимаю, была создана в том числе вот эта вот команда script-migrate, чтобы можно было заскриптовать то, что он будет делать в нормальной понятной SQL, например, отдать DBA им, чтобы они посмотрели и хоть, ну, так сказать, одобрили. -1798.12 1803.48 SPEAKER_01 Там тоже ее нельзя назвать, что она прям хорошая, читабельная. -1803.48 1810.00 SPEAKER_01 Точно так же, как и C#-код, который у тебя генерирует стандартный генератор, они не для того, чтобы их люди читали. -1810.00 1815.08 SPEAKER_00 Ну, он хотя бы на SQL, где уже точно понятно, что будет исполняться. -1815.08 1817.12 SPEAKER_00 То есть тут как бы уже хоть что-то. -1817.12 1822.48 SPEAKER_01 Опять же, все равно такое удовольствие, как написание мануальных скриптов, вы не получите ни в одного из этих лоз. -1822.48 1827.62 SPEAKER_01 Опять же, не будете писать, как в DBA, например, просто скриптики. -1827.62 1828.62 SPEAKER_00 Ну да, да. -1828.62 1830.56 SPEAKER_00 Ну, в общем, такие дела. -1830.56 1831.56 SPEAKER_00 Давай дальше. -1831.56 1834.16 SPEAKER_01 Ну, отлично, в принципе, хорошая темка. -1834.16 1837.34 SPEAKER_01 Миграции, я думаю, нужны и всем важны. -1837.34 1838.34 SPEAKER_01 Пойдем дальше. -1838.34 1843.68 SPEAKER_01 Что еще, интересно, всем нужно и всем важно, но никто это не осознает, это шифровать ваши урлы. -1843.68 1847.64 SPEAKER_01 Вот, мы, конечно же, о таком не задумывались, а вот давайте теперь задумаемся. -1847.96 1853.72 SPEAKER_01 Все началось с того, что один из авторов начитался Энди Рахина. -1853.72 1868.00 SPEAKER_01 Это такой опасный человек, кто не знает, это автор RavenDB, наверное, самая популярная и самая единственная база данных, которая написана на C#, и у него очень много интересных концептуальных мыслей в голове рождается. -1868.00 1872.48 SPEAKER_01 Не все он их применяет именно к RavenDB, но блок у него довольно познавательный. -1872.48 1891.32 SPEAKER_01 Там много мусора, конечно, но если появляются самородки, они там многие годы живут, и вот там, не знаю, статья четырехлетней, наверное, давности, когда Энди задался вопросом, а почему мы вообще выставляем наши, допустим, идентификаторы сущностей наружу, в общем, этот вопрос все еще открыт. -1891.32 1905.00 SPEAKER_01 И вот Халид Абдухамед, он тоже знаменитый автор блогов, вот, прочитал эту статью, вдохновился и решил разобраться, а как же сделать хорошо на уровне Айспенета. -1905.00 1908.24 SPEAKER_01 И вот мы сейчас с вами все эти темки и пройдем. -1908.24 1917.04 SPEAKER_01 Почему плохо выставлять голые попоидентификаторы наружу, ну, в частности, в Урлы, например, их отдавать, и что же с этим мы можем сделать в Айспенеткой. -1917.04 1922.36 SPEAKER_01 Прежде всего, давайте разберемся, что же в этом плохого, обычно все идентификаторы выставляют, и все нормально. -1922.36 1935.52 SPEAKER_01 Ну, здесь нужно понимать, что речь в основном идет об идентификаторах, интовых, то есть многие спрашивают, зачем там использовать буйды, зачем использовать строки в виде идентификаторов, и давайте использовать наши красивые инты. -1935.52 1943.36 SPEAKER_01 Ну вот, статья, она в основном рассчитана на то, чем инты плохо выставлять наружу, но некоторые моменты, конечно, можно и гуйдам тоже натянуть. -1943.36 1947.92 SPEAKER_01 Давайте по порядочку, чем же плохо, например, интовые идентификаторы выставлять наружу. -1947.92 1955.44 SPEAKER_01 Прежде всего, есть такая атака, которая называется "Url Tempering", это, по сути, подделка Урла. -1955.44 1957.80 SPEAKER_01 И в чем она выражается? -1957.80 1980.04 SPEAKER_01 Когда вы, например, пишете типичный код, вот сервер мой, вот у меня есть ресурс users, и у этого ресурса я хочу вернуть юзера под идентификатором 1, то абсолютно всем ожидаемое поведение, что если мы идентификатор 1 поменяем на идентификатор 2, то нам вернется уже другой юзер, не с идентификатором 1, а тот, который с идентификатором 2. -1980.04 1990.24 SPEAKER_01 И, в принципе, это очень плохая ситуация, потому что здесь мы можем открыть те данные, которые не подразумевались, что нам будут доступны. -1990.24 2004.40 SPEAKER_01 Эта проблема решается в основном тем, что мы заводим некий security слой, мы заводим аутентификацию, авторизацию, и тому пользователю, которому не нужно доставать юзера 2, а только доставать юзера 1, мы ему эти данные просто напросто не вернем. -2004.40 2019.60 SPEAKER_01 Но здесь, опять же, очень большая сложность влетает в виде security, и очень часто бывает, что разработчики забывают разметить специальный контроллер или специальные методы вот такими параметрами security, или еще где-то что-то пропустить. -2019.60 2041.60 SPEAKER_01 В общем, такая ошибка, когда мы подставляем вместо идентификатора какой-то другой идентификатор, следующий идентификатор, или перебираем пачку из миллиона идентификаторов и пытаемся запросить этот ресурс, она очень частая, и, в принципе, наверное, это самая легкая атака, которую вы можете провернуть, если вдруг общаетесь с какими-то другими сервисами и видите какой-нибудь интовый идентификатор, попробуйте так поделать. -2041.60 2066.00 SPEAKER_01 В общем, я очень много открывал таких видеофайлов и всяких, даже на платных курсах, много платных курсов есть, которые вот так вот идентифицируют свои ресурсы и дают вам ссылку только к тому, что вы купили, но при этом проставляя другие идентификаторы, интовые, по порядку вы можете найти еще очень много открытых курсов, которые никаким security не спрятаны, а спрятаны только тем, что вы якобы не знаете идентификатор ресурса. -2066.00 2073.68 SPEAKER_01 В общем, на самом деле, какая бы эта атака смешная и глупая ни казалась, в сети огромное количество ресурсов, которые ей подвержены. -2073.68 2079.00 SPEAKER_01 И это один из принципов, почему плохо интовые идентификаторы выставлять наружу. -2079.00 2091.08 SPEAKER_01 Потому что вы не знаете, каким образом они попадут наружу и кто их будет использовать, и закроются ли они во всех нужных местах с помощью всяких ваших security авторизаций. -2091.08 2094.88 SPEAKER_01 Могут они закрыться, при этом хакеры могут утянуть ваши данные с помощью такого способа. -2094.88 2104.08 SPEAKER_01 И если мы вдруг идентификатор каким-то образом прячем, то это уже становится невозможным. -2104.08 2121.52 SPEAKER_01 Вторая причина, почему плохо интовые идентификаторы выставлять наружу, это потому что данные идентификаторы они могут вам раскрыть, даже не вам, а внешнему наблюдателю, могут раскрыть тонкости реализации вашей системы. -2121.52 2128.12 SPEAKER_01 Ну, например, известно, что интовые идентификаторы очень любят программисты из реалиционных баз данных. -2128.12 2135.08 SPEAKER_01 Вот именно там у них есть такое поверье, что инты - это всегда красиво, это всегда коротко, и вот давайте делать интовые идентификаторы. -2135.08 2140.48 SPEAKER_01 Если же мы возьмем документные базы данных, то там сразу были введены строки. -2140.48 2141.88 SPEAKER_01 И более популярные строки. -2141.88 2158.76 SPEAKER_01 И именно анализируя вот эти данные, можно раскрыть строение вашей внутренней системы, и также можно выяснить некие архитектурные решения, которые у вас есть, и таким образом тоже спланировать каким-то образом вектор атаки на вашу систему. -2158.76 2166.68 SPEAKER_01 Ну, вплоть до того, что даже если мы берем ГУИДы, то дефолтный алгоритм генерации ГУИДов у большинства вас разный. -2166.68 2173.04 SPEAKER_01 То есть мы легко можем отличить какой-нибудь ГУИД от mongdb, от ГУИДа, который там генерирует mssql. -2173.04 2187.08 SPEAKER_01 Также точно вспоминаем, что у нас есть sequential ГУИДы или ГУИДы, которые ни разу не sequential, у нас у ГУИДов есть разные версии, и вот в зависимости от каких-то определенных параметров мы более или менее можем уже узнать, а что там за база данных стоит. -2187.08 2201.00 SPEAKER_01 Более того, некоторые базы данных со временем переходят на новые генерации ГУИДов, но новой версией, то есть мы можем определить не только базу данных, но и даже ту версию, которая база данных там работает. -2201.00 2213.56 SPEAKER_01 Ну, например, тот же самый ravendb менял способ генерации дефолтных идентификаторов с одного формата на другой, и видя этот формат, вы точно можете сказать, что там raven и даже можете сказать от какой до какой версии. -2213.56 2230.40 SPEAKER_01 В общем, это тоже кажется, что ситуация мало, ну как бы мало опасности она в себе внесёт, но на самом деле, зная то, какая база данных там установлена, злоумышленник уже получает какой-то набор о том, о какие эксплойты можно посмотреть для того, чтобы попытаться её проатаковать. -2230.40 2235.04 SPEAKER_01 То есть это какой-то первичный анализ архитектуры очень хорошо раскрывает. -2235.04 2237.56 SPEAKER_01 Поэтому тоже опасная штука. -2237.56 2248.48 SPEAKER_01 Ну и третий аргумент, который здесь можно привести, то есть почему интовые идентификаторы опасно отдавать наружу, то это может раскрыть некие ваши бизнес-показатели, довольно критичные бизнес-показатели. -2248.48 2266.20 SPEAKER_01 Например, если мы посмотрим на идентификаторы, то их очень любят часто без дырок инкрементировать, это один из плюсов интовых идентификаторов, которые вам приводят, что там не бывает никаких дырочек, ну там кроме удалений, этим мы сейчас можем пренебречь, ну не бывает так, что у тебя там появился идентификатор 200, а потом стал идентификатор 5000. -2266.20 2277.04 SPEAKER_01 В общем, всё-таки их стараются инкрементировать по порядку, ну и базы данных нас на это подвигают, если мы сделаем автоинкрементную колоночку, то она тоже всё будет делать по порядку. -2277.04 2278.04 SPEAKER_01 Чем это плохо? -2278.04 2290.84 SPEAKER_01 Ну естественно, тем, что этот инкремент, его можно анализировать, и благодаря вот этому анализу вы легко можете отследить, какие данные у вас были, например, в начале месяца и какие данные, какой идентификатор у вас был в конце месяца. -2290.84 2308.12 SPEAKER_01 И таким образом вы вполне можете вычислить, а какое количество, например, ордеров у вас было, если это идентификатор ордера, какое количество там заказов поступило в вашу систему, какое количество продуктов может быть ваша система оформила или отослала, или какие пользователи там, сколько пользователей сделал покупок. -2308.12 2311.80 SPEAKER_01 Опираясь на эти идентификаторы, вот такие данные очень легко из системы получить. -2311.80 2320.52 SPEAKER_01 Это в большинстве случаев бизнес не хочет делиться такими показаниями, опять же, всем-всем подряд наружу, и даже об этом никто не задумывается. -2320.52 2329.44 SPEAKER_01 Но анализируя расход идентификаторов через API, злоумышленник, опять же, очень легко вот такие показатели считывает и получает. -2329.44 2330.44 SPEAKER_01 Это неплохо. -2330.44 2335.64 SPEAKER_01 Поэтому вот примерно от вот этих трех векторов мы сами и пытаемся защититься. -2335.64 2345.84 SPEAKER_01 Ну, хорошо, мы выяснили, что интовые идентификаторы - это плохо, но если они у вас уже в системе есть, то, естественно, никто их менять и переводить не будет. -2345.84 2346.84 SPEAKER_01 Что же в этом случае делать? -2346.84 2352.52 SPEAKER_01 Очень просто, прежде чем отдать интовые идентификаторы наружу, их очень полезно можно зашифровать. -2352.52 2356.88 SPEAKER_01 А когда принимаем их обратно, их полезно расшифровать и работать с ними дальше. -2356.88 2367.48 SPEAKER_01 Естественно, руками в каждом запросе шифровать и расшифровывать, это никто делать не будет, поэтому у нас есть неявные методы, в которых нам помогает ISP.NET Core. -2367.48 2370.96 SPEAKER_01 Прежде всего, давайте посмотрим, каким образом мы можем зашифровать значения. -2370.96 2373.56 SPEAKER_01 Это делается довольно просто. -2373.56 2387.12 SPEAKER_01 Для этого нам понадобится свой собственный классик, который мы пронаследуем от специального интерфейса, который называется iOutboundParameterTransformer, как несложно догадаться по названию. -2387.12 2398.40 SPEAKER_01 Интерфейс требует от нас, чтобы мы каким-то образом заэнкодили параметры, которые выдаются наружу, а энкодить мы их будем с помощью такого механизма, как Data Protection. -2398.40 2409.96 SPEAKER_01 Data Protection - это прекрасный слой, который скрывает от нас весь ужас шифрования и все знания о ключах, где они хранятся, как они ротетятся, кому принадлежат и прочее. -2409.96 2418.12 SPEAKER_01 Он выдает прекрасный API, у которого есть два метода - protect и unprotect, и все счастливы при этом. -2418.12 2419.76 SPEAKER_01 Но опять же, это пример. -2419.76 2429.32 SPEAKER_01 В данном примере используется Data Protection, который делает все операции памяти, все ключи, генерирует на лету и так далее. -2429.32 2441.52 SPEAKER_01 Если вы будете это в продакшене использовать, то, естественно, вам нужен более сложный подход, как-то ваши ключи хранятся где-то в пересистительном сторе, у них настроен понятный роллинг и так далее. -2441.52 2450.32 SPEAKER_01 Для примера нам достаточно и какой-нибудь In-Memory криптовальщика, в коем как раз и выступает данная имплементация Data Protection. -2450.32 2456.36 SPEAKER_01 Так, после того, как мы написали наш прекрасный классик с интерфейсиком, его достаточно зарегистрировать в сервисах. -2456.36 2471.16 SPEAKER_01 У нас есть прекрасный RouteOptions, у которого есть ConstraintMap, к которому мы добавляем наш класс и все, после этого все руты, которые проходят через нашу систему, подвергаются нашему шифрованию. -2471.16 2475.48 SPEAKER_01 Поэтому все, что вы выдадите наружу, все ID-шники будут зашифрованы. -2475.48 2482.40 SPEAKER_01 Естественно, это касается не того, когда вы урлы ручками форматируете, это касается каких-то системных утилит. -2482.40 2491.16 SPEAKER_01 Например, есть LinkGenerator, который позволяет вам сгенерить урлы для определенного контроллера, экшена, параметров и так далее. -2491.16 2499.44 SPEAKER_01 Если вы будете пользоваться как положено с помощью LinkGenerator, то у вас все вот эти параметры будут зашифрованы, как мы и рассчитывали. -2499.44 2513.16 SPEAKER_01 Также, если вы там используете какие-то RazorPages, и в этих RazorPages у нас там есть RouteTemplates, эти RouteTemplates, естественно, тоже подхватят наш трансформер, и все RazorPages-ссылочки тоже у вас будут за encryption, и пользователь там, естественно, ничего не увидит. -2513.16 2522.36 SPEAKER_01 Если мы используем DataProtection, то внутри у него используется серьезная, как я уже сказал, шифровальная система, там, по-моему, IS какой-то даже стоит. -2522.36 2532.96 SPEAKER_01 Минусы этого IS составляют в том, что после того, как мы маленький int зашифровали, тот же самый единичку, двоечку, из него получается огромная-огромная стакища из месива буковок. -2532.96 2539.64 SPEAKER_01 В общем, минус данного подхода в том, что урлы у вас начинают выглядеть как полная каша, полное месиво. -2539.64 2542.84 SPEAKER_01 Но посмотрим, что с этим можно сделать чуть попозже. -2542.84 2548.48 SPEAKER_01 Давайте теперь вернемся к другой части, да, то есть мы данные-то зашифровали, а как нам их обратно получать? -2548.48 2555.32 SPEAKER_01 А, ладно, обратно там нам хочется тоже int-овые единички получить вместо всего вот этого месива, которое у нас в результате IS вышло. -2555.32 2558.56 SPEAKER_01 И в этом нам поможет ISP NetCoreModelBinder. -2558.56 2563.48 SPEAKER_01 У байндера есть точно такая же система, но только на оборот. -2563.48 2570.24 SPEAKER_01 Есть специальный интерфейс, который называется IModelModelBinder, от которого мы должны пронаследовать наш вышеупомянутый классик. -2570.24 2582.40 SPEAKER_01 И у него всего лишь там навсего перекрыть один метод, который как раз-таки вычленяет нужные данные из контекста, который приходит, из HTTP-контекста, и вызывает у нашего протектора метод unprotect. -2582.40 2586.52 SPEAKER_01 То есть с помощью того же DataProtection API мы эти данные расшифровываем. -2586.52 2601.92 SPEAKER_01 После того, как мы такой интерфейс экземпляризировали, нам нужно вот этот протектор рассказать, то есть рассказать ISP Net, когда применять этот протектор, каким свойствам. -2601.92 2614.88 SPEAKER_01 Самый примитивный способ это сделать, это прямо над свойством навесить атрибут, bind property, и в этом bind property указать того байндера, через который ISP NetCore будет пропускать все реквесты. -2614.88 2627.80 SPEAKER_01 Таким образом мы можем навесить bind property на наши айдишники все, и в эти айдишники после всех наших преобразований будет записываться тот чистый красивый int, который вы и ожидали увидеть. -2627.80 2631.56 SPEAKER_01 В общем так, довольно прозрачно можно сделать и шифрование, и дешифрование. -2631.56 2641.00 SPEAKER_01 И это все сделается, естественно, на уровне ISP Net, и ваш бизнес-логика от этого никак не страдает, она продолжает работать с интами и ничего не знает о всех этих ужасах. -2641.00 2642.00 SPEAKER_01 Криптографии и секьюрити. -2642.00 2647.08 SPEAKER_01 Так, теперь давайте посмотрим, а что же у нас получилось и какие минусы, в принципе, у этого подхода есть. -2647.08 2671.28 SPEAKER_01 Ну, прежде всего, шифрование и дешифрование в данном случае, это настоящее криптографическое шифрование IS, как я уже сказал, оно требует очень много ресурсов, ресурсов процессора прежде всего, поэтому если у вас вдруг какие-то запросы очень частые, и высоконагруженный сервис, и железа мало, то тут уже стоит думать, нужно оно вам или не нужно, потому что encrypt и decrypt идет на каждый реквест. -2671.28 2675.52 SPEAKER_01 Дальше у нас получаются слишком длинные строки. -2675.52 2676.52 SPEAKER_01 Ну как слишком? -2676.52 2683.16 SPEAKER_01 С точки зрения шифрования эти строки нормальны, но если мы будем читать их глазками, то это очень некрасиво выглядит. -2683.16 2690.80 SPEAKER_01 Если у вас с этим нет проблем, вы используете какой-нибудь Razor Pages, никто ваши урлы глазками не читает, то, в принципе, наверное, можно и забить. -2690.80 2699.44 SPEAKER_01 Если же вы все-таки хотите, чтобы ваши урлы были красивыми, более-менее помещались хотя бы в строку браузера, то можно пойти на небольшой компромисс. -2699.44 2704.56 SPEAKER_01 В принципе, в то, что мы делаем, здесь security нам не так сильно важна. -2704.56 2709.72 SPEAKER_01 Нам здесь не нужно полное шифрование, здесь хватило бы какой-то базовой офускации. -2709.72 2726.08 SPEAKER_01 Даже если мы получим, сделаем какую-то базовую офускацию, то есть просто-напросто каким-нибудь шифром Цезаря сдвинем все буквки слева на все байтики или битики слева направо и так далее, не зная алгоритм офускации, довольно сложно подобрать. -2726.08 2729.08 SPEAKER_01 Опять же, довольно сложно подобрать вот этот ключ. -2729.08 2751.32 SPEAKER_01 Поэтому если у вас там не какая-то банковская тайна или финансовая информация или какие-нибудь данные о здоровье, то есть где вам реально не нужна настоящая криптография, а вы просто храните котиков и просто хотите повыпендриваться, то там можете отказаться от криптографии и взять какую-нибудь любую библиотечку по офускации коротких адресов, по офускации интов, айдишников. -2751.32 2755.72 SPEAKER_01 Их в интернете миллион, ну и у нас в выпусках тоже были хорошие обзоры таких библиотечек. -2755.72 2766.40 SPEAKER_01 Можете взять их, но только в этот момент помните, что никакой криптографии там на самом деле нет, а есть просто security by obscurity, то есть пока ваш алгоритм неизвестен, то мало шансов, что его кто-то откроет. -2766.40 2775.80 SPEAKER_01 Также мы получаем небольшой шум из-за вот этих атрибутов, как я уже сказал, что нужно на айдишник навесить специальный атрибут bind property и так далее. -2775.80 2801.48 SPEAKER_01 Но на самом деле вот навешивать атрибуты над каждое свойство не нужно, есть более элегантные хуки, которые позволяют вам там проанализировать всю модель и независимо от, то есть в зависимости от каких-то там параметров, например, если поле называется id или заканчивается на id и его тип int, то применить вот этот bind property атрибут. -2801.48 2817.32 SPEAKER_01 В общем, такие условия тоже можно написать и гораздо лучше их написать и не вымазывать модельки во все эти bind атрибуты, потому что, опять же, последняя проблема это в том, что вы можете забыть навесить такой bind атрибут, то есть навесить такие constraint и получите утечку данных, что очень-очень плохо. -2817.32 2819.08 SPEAKER_01 Лучше таких вещей еще не допускать. -2819.08 2822.68 SPEAKER_01 Если возможно что-то забыть, значит нужно это делать на другом уровне. -2822.68 2826.78 SPEAKER_01 Вот на уровне как раз hook reflection это сделать намного приятнее. -2826.78 2829.08 SPEAKER_01 Там вот 100% ничего не забудете. -2829.08 2839.12 SPEAKER_01 Если property заканчивается на id и имеет тип int, допустим, ее можно автоматически считать, что это property, которое нужно шифровать или аффуцировать и отдавать наружу. -2839.12 2842.40 SPEAKER_01 В общем, и тогда никаких вот этих проблем не будет. -2842.40 2856.92 SPEAKER_01 В общем, вот такой интересный вброс, смотрите, то есть я думаю, что очень важно каждому разработчику понимать, почему int-ы отдавать наружу это плохо, это прежде всего, это главное, что хотелось бы вынести из статьи. -2856.92 2862.92 SPEAKER_01 А то, будете ли вы там шифровать, аффуцировать или дальше как-то этим загоняться, уже зависит от вашего бизнес-кейса. -2862.92 2870.72 SPEAKER_01 Иногда бывает, на большинстве случаев, ситуации, когда бизнесу все равно показывают котиков и никому не интересно сколько котиков мы загрузили в базу. -2870.72 2880.06 SPEAKER_01 В общем, но если это не так, то смотрите, как с антами можно защититься, как их можно аффуцировать и как можно избежать хотя бы базовых проблем. -2880.06 2906.84 SPEAKER_00 Ну да, и надо еще помнить, что если как ты говоришь, как-то автоматически это делать, если у нас поле типа int, то автоматически его шифровать или еще как-то заменять на string, то дальше возникает вопрос, если вы автогенерите при этом OpenAPI-спеку из вашей модели, то надо чтобы ваш OpenAPI-генератор дружил с этой логикой и понимал, что там на самом деле надо показать string, а не int. -2906.84 2913.16 SPEAKER_00 Потому что многие просто посмотрят на модель и скажут, что вот это там int, и у вас в модельке, ну в спеке будет int. -2913.16 2944.32 SPEAKER_01 Ну опять же, скорее всего, когда ты описываешь вот эти наружные DTOшки, по которым будет генериться OpenAPI-спецификация, то наверное там лучше всего сразу сказать одичнику, что это string, и таким образом вы себя тоже немножко обезопасите, как мы уже обсуждали, как одичники выставляют наружу тему недавнешнюю, что чем меньше внешняя система знает и предполагает о вашей системе, тем лучше, поэтому string – это универсальный идентификатор, самый безопасный тип, который вы можете отдать наружу, и чтобы потребляющая страна ничего об этом не подозревала. -2944.32 2948.92 SPEAKER_00 Все так, но ModelBinder и прочее как раз к этим самым DTOшкам-то и применяются. -2948.92 2952.60 SPEAKER_00 Поэтому если делать это на автомате, то там должен быть int. -2952.60 2957.80 SPEAKER_00 Если применять логику вида int и начинается или заканчивается на id. -2957.80 2960.48 SPEAKER_01 Да, я бы только на одичнике заложился, мне кажется. -2960.48 2962.48 SPEAKER_01 На keep закладываться не стоит. -2962.48 2969.68 SPEAKER_00 Я бы явно, на самом деле, писал бы string id, и я бы руками расставлял нужные атрибуты. -2969.68 2994.16 SPEAKER_00 То есть мы такое делали, мы, правда, использовали не шифрование, мы использовали когда-то библиотечку hashids.net, сейчас там ее автор переписал, и теперь она называется sqids.net, там я немножко изменил алгоритм, но в принципе это не шифрование никаким образом, это штука, которая генерирует такие, как она называется, ютуб-подобные айдишники. -2994.16 2996.52 SPEAKER_01 Ну да, это как раз вот эти обфускаторы, про которые -2996.52 2997.52 SPEAKER_00 я говорил. -2997.52 2998.52 SPEAKER_00 Да-да-да. -2998.52 2999.52 SPEAKER_00 Это просто, наверное, пожалуй, одна. -2999.52 3005.04 SPEAKER_00 Вот hashids на момент, ну, несколько лет назад была чуть ли не одной из самых популярных, мне кажется, которая в среднем гуглилась. -3005.04 3011.84 SPEAKER_00 Сейчас автор, она уже давно не обновляется, последний комитет, там четыре года три, по-моему, назад были в нее. -3011.84 3016.60 SPEAKER_00 Вот сейчас автор сосредоточился на новой, которая sqids, которая под новый .net уже работает нормально и так далее. -3016.60 3018.76 SPEAKER_01 Я тоже боюсь представить, а что-то можно обновлять. -3018.76 3031.92 SPEAKER_00 Ну я не знаю, вот он прямо одну забросил, потом написал, что типа вот, мол, ребрендит и придумал новый алгоритм, который называется sqids, и потом пошел писать отдельную библиотечку для нее. -3031.92 3033.76 SPEAKER_01 Надо же ради интереса посмотреть. -3033.76 3034.76 SPEAKER_01 Вот да. -3034.76 3035.76 SPEAKER_01 Реализация обычная. -3035.76 3063.76 SPEAKER_00 Не, я точно знаю, что в старой версии можно было задать seed, то есть ты задавал, мог задать свой кастомный алфавит, но если ты хочешь, например, там по дефолту типа, ну понятно, английские буквы, uppercase, lowercase и цифры, причем там хитро подобрано, чтобы там не было связи, ну в смысле в алфавите не встречалось одновременно там a из-за главной и какая-нибудь там единичка и l прописная, да, чтобы у тебя в идентификатор он был человекочитаемым и легко диктуемым, грубо говоря, в смысле. -3063.76 3066.64 SPEAKER_01 Ну это тоже такое требование есть, но не всегда нужно. -3066.64 3077.52 SPEAKER_00 Ну оно не всегда нужно, да, но вот типа по дефолту, ну там были такие настройки, там можно было еще указать seed, чтобы, понятно, он был чуть более уникален, а не так, что это ты написал такое же приложение, куда и перебором все подобрал. -3077.52 3078.52 SPEAKER_00 Вот. -3078.52 3084.92 SPEAKER_00 А у этого seed указать нельзя, но зато можно указать свой shuffled алфавит типа. -3084.92 3085.92 SPEAKER_00 Вот. -3085.92 3094.40 SPEAKER_00 Короче, видимо, какая-то, наверное, мелочь, я не знаю почему, ну в общем, решил почему-то переписать, может быть это был повод переписать на новый dotnet и забить на поддержку старого, например. -3094.40 3095.40 SPEAKER_00 Тоже вариант. -3095.40 3096.40 SPEAKER_00 Ну можно, возможно. -3096.40 3100.20 SPEAKER_00 Я не смотрел, с чем он там совместим с точки зрения фреймворков. -3100.20 3113.36 SPEAKER_00 Вот, поэтому не знаю, но в общем, да, мы, в принципе, пользовались, приятно, да, когда нужно не показывать чиселки, обычно этого достаточно, в большинстве случаев, вряд ли вам нужно прямо именно шифрование-шифрование. -3113.36 3115.32 SPEAKER_01 Ну если надо, почему нет. -3115.32 3118.00 SPEAKER_01 Да, да, да, обычно так есть. -3118.00 3150.48 SPEAKER_00 Ну давай пойдем дальше, дальше у нас блок статей, в смысле, что-то несколько статей, объединенных общей темой, но именно все это от компании, которая поддерживает и развивает фреймворк, тул, не знаю, библиотеку под названием PostSharp, это штука, которая долгое время, я же не знаю, сколько лет живет и, наверное, является чуть ли не одним из основных, источников неправильное слово, из основных библиотек, которые реализуют подход аспектно-ориентированного программирования в дотнете, вот так скажем. -3150.48 3153.04 SPEAKER_01 Из источников проблем ты хотел сказать, да? -3153.04 3158.88 SPEAKER_01 Потому что все, что я знаю про PostSharp, это то, что его надо срочно выпиливать, если вы в каком-то проекте -3158.88 3159.88 SPEAKER_00 его нашли. -3159.88 3164.92 SPEAKER_00 Ну типа того, давай немножко сначала кратенько скажем, что это вообще такое, в чем была идея. -3164.92 3183.48 SPEAKER_00 Идея PostSharp была в следующем, когда-то давно, когда все это начиналось, вы не могли во время компиляции ничего делать со сходным кодом, не было еще никаких сорс-генераторов для рослин, ничего, максимум что было, это всякие T4-шаблоны или самописные кусочки MSBuild скриптов, которые вам что-то там генерили. -3183.48 3185.52 SPEAKER_00 А иногда хочется изменять код. -3185.52 3195.16 SPEAKER_00 Например, не знаю, там классический пример, который всегда приводит почему-то для аспектно-ориентированного программирования, это что мы хотим залогировать вход и выход каждой функции. -3195.16 3200.08 SPEAKER_00 И ни разу не встретил, что бы такое хотелось, но вот это такой классический пример. -3200.08 3227.24 SPEAKER_00 Значит для этого можно встроить специальный плагин по сути в MSBuild pipeline, который после того, как у вас изгенерена сборка, уже DLL собрана MSBuild, возьмет эту сборку, декомпилирует ее, разберет IL-код, найдет везде, где есть ваши методы, и в нужные места пропатчит IL-код и соберет обратно сборку согласно тому, как вы ему описали. -3227.24 3231.16 SPEAKER_00 То есть там атрибутами поверх функции, либо еще как-то. -3231.16 3239.04 SPEAKER_00 То есть некоторый патчинг вашей DLL, вашего кода, уже после его сборки на уровне IL-кода. -3239.04 3247.44 SPEAKER_00 С одной стороны это позволяет сделать огромное количество вещей, потому что в IL-коде можно сделать практически все. -3247.44 3284.84 SPEAKER_00 С другой стороны эта штука довольно сложна, она очень хрупкая, потому что она по сути, если вы хоть как-то изучали, во что превращается ваш async метод, когда это стоит машина, и большой метод с кучей свитч кейсов, это все нужно аккуратно поддерживать на уровне IL-кода, это у вас все просто, в C#, а на IL-коде это может развернуться в довольно большие простыни, разные методы, еще что-нибудь, какие-то промежуточные объекты, это все надо как-то понимать, куда все это внести, как это распознать и понять, куда что встраивать. -3284.84 3296.98 SPEAKER_00 Поэтому эта штука действительно источник проблем, потому что на уровне IL-кода можно было это все сломать, причем можно было это сломать на уровне, чтобы получалась сборка, которая при попытке загрузки говорила, что у тебя вообще-то невалидная сборка. -3296.98 3299.48 SPEAKER_00 Что-то такое мне встречалось как-то пару раз. -3299.48 3305.00 SPEAKER_00 То есть IL-код был приведен в состояние, что он, ну короче, некорректный. -3305.00 3316.64 SPEAKER_00 Компания, ну PathShark при этом довольно популярный, ну видимо потому что плюс-минус единственный, вот, наверное какие-то вещи с ним действительно делать удобно или других способов может быть нет. -3316.64 3324.72 SPEAKER_00 Если вы, например, использовали какую-нибудь там кодогенерилку или какую-нибудь стороннюю библиотеку, с которой вы ничего не можете сделать, то PathShark можно было ее хоть как-то подходить. -3324.72 3354.56 SPEAKER_00 Но жизнь не стоит на месте, Roslin двигается, дотнет меняется, и компания поняла в какой-то момент, на самом деле это было несколько лет назад, судя по статейочке, одно из, что становится все это поддерживать сложнее и сложнее, а Roslin развивается, появились сурс-генераторы, появилась возможность генерить код нормально в каком-то разумном виде в момент компиляции, причем генерить сразу C#, чтобы дальше компилятор уже сам все компилировал. -3354.56 3361.56 SPEAKER_00 Но есть одна проблема, все еще нельзя менять код. -3361.56 3367.08 SPEAKER_00 То есть вы пока Roslin с сурс-генераторами не можете изменять существующий код. -3367.08 3374.36 SPEAKER_00 То есть если у вас есть, например, задача добавить то самое логирование для всех вызываемых методов, то Roslin вы это сейчас делать не сможете. -3374.36 3378.18 SPEAKER_00 По C# можно, но по C# это все делать хрупко и ненадежно. -3378.18 3401.48 SPEAKER_00 Поэтому компания подумала, поняла, что по C# что-то как-то сложно становится поддерживать, и все свои силы кинула на новый продукт, который теперь называется Metalama, он вышел чуть больше полгода назад, но тут сейчас прошел ряд статей по поводу опенсурсности некоторых кусочков, поэтому он снова появился у нас в наших источниках новостей и мы про него рассказываем. -3401.48 3404.48 SPEAKER_00 Что же такое Metalama? -3404.48 3417.20 SPEAKER_00 Это, как они называют, очень простой и очень мощный инструмент для генерации кода и для валидации кода для C#, для метапрограммирования. -3417.20 3432.80 SPEAKER_00 У него фокус на простоту и безопасность, то есть это в отличие от PostSharp они стараются сделать так, чтобы ничего не ломалось в ваших приложениях, и они сказали, что они reimagined, то есть они перепридумали аспектно-ориентированное программирование для современного дотонета. -3432.80 3435.40 SPEAKER_00 Значит, что же такое и как это теперь выглядит? -3435.40 3462.64 SPEAKER_00 Значит, аспекты, у них есть два понятия, аспект и, ну они это называют fabrics, это не фабрики, в смысле фабрики были бы factories, это скорее fabrics, в смысле нити, ткани, ну то есть что-то такое вот связующее, видимо, эта мысль была при назывании, это все C#-классы, которые исполняются внутри компилятора или внутри IDE, пока вы редактируете код. -3462.64 3482.68 SPEAKER_00 То есть позволяют делать следующее, позволяют генерить код в compile-time, либо менять код в compile-time, позволяют, если все это работает во время IDE, верифицировать ваши исходники по всяким паттернам и правилам, ну и дальше даже позволяются какие-то фиксы и рефакторинги. -3482.68 3484.48 SPEAKER_00 Как этим всем пользоваться? -3484.48 3490.08 SPEAKER_00 Давайте сначала с простого поймем, потом попаковаемся внутри, как же это устроено и работает. -3490.08 3506.48 SPEAKER_00 Значит, есть NuGet пакет, называется metalama.framework, который вы добавляете в ваш продукт, можно добавить некоторые экстенджеры для Visual Studio и поставить, тогда там будут некоторые полезные тулзы доступны, и дальше вы создаете аспект. -3506.48 3539.16 SPEAKER_00 Ну, например, возвращаясь к нашему простому примеру с логированием, вы создаете аспект, это, по сути, класс, который будет применяться, как правило, атрибутом, в данном случае тогда вы его назовете LogAttribute по конвенции C#, который наследуется от класса OverrideMethodAspect, после чего в нем нужно заверрадить единственный метод, который называется OverrideMethod, который возвращает, вот тут я прям удивился, он возвращает nullableDynamic, прикинь, вот. -3539.16 3540.16 SPEAKER_00 Да. -3540.16 3548.76 SPEAKER_00 То есть динамик с вопросиком, прям такой, туда подойдет все что угодно, вообще, не знаю, зачем динамик с вопросиком. -3548.76 3551.60 SPEAKER_00 Типа теперь точно вообще все что угодно. -3551.60 3563.64 SPEAKER_00 Вот, и внутри у вас есть, соответственно, некоторый базовый protected property под названием meta, у которого есть пачка properties и методов, с помощью которых вы можете общаться с тем методом, который вы заверраете. -3563.64 3575.64 SPEAKER_00 То есть метод.target.method даст вам название этого метода, метод.proceed, собственно, вызовет этот метод, и если он возвращает какой-то результат, вы присваиваете его в переменную result и его возвращаете. -3575.64 3578.64 SPEAKER_00 Благодаря динамику вы можете вернуть вообще все что угодно. -3578.64 3585.68 SPEAKER_00 Я не знаю, ничего не сказано, как это будет работать с ассинк методами, вот этим всем, но как бы надо изучать. -3585.68 3587.88 SPEAKER_00 Настолько детально я туда не копался. -3587.88 3594.92 SPEAKER_00 Дальше вы этот атрибют, который, LogAttribute вы объявили, вы его применяете к нужным методам, либо вы можете сделать по-другому. -3594.92 3603.24 SPEAKER_00 Вы можете объявить новый класс, который тот самый Fabric, и внутри с помощью linkStyle сделать такую штуку. -3603.24 3640.68 SPEAKER_00 То есть вы, например, можете написать, там появляется пропертиа под названием amender, от английского amend, ну типа изменять, да, и дальше вы там делаете select, в скобочках пишите условия там на все типы, where, там где эти типы объявлены как public, из них делаете select many, там методы where, там допустим, хочу все public и при этом чтобы они были не toString, да, ну типа toString не будем блокировать, и потом добавляем, типа addAspect, и указываете ваш атрибутчик, который вы создали, и оно автоматически в compile-time все добавится, вот. -3640.68 3656.68 SPEAKER_00 Когда происходит compile-time, эта лама меняет C# код перед тем, как отдавать его собственно к компилятору на компиляцию, она меняет C# код и физически вставляет туда кусочки C#, ну вот того, что вы написали с точки зрения Console.WriteLine и так далее. -3656.68 3691.12 SPEAKER_00 То есть на самом деле, вот эти вот override метод, который динамик с вопросиком, я так понимаю, выполняться не будет именно как выполнение, то есть это по сути просто шаблон аспекта, и нужен там этот динамик просто чтобы компилятор был доволен, ну потому что это тоже же код, который он как бы пытается скомпилить, возможно, вот, а фактически получается, что ваш код меняется так, что вот эти вот кусочки, которые вы добавили там до, например, вызова .prosheet и после, они будут аккуратно вставлены в те места, которые размечены правильными атрибутами. -3691.12 3699.96 SPEAKER_00 Вот, такая вот магия, выглядит действительно немножко магически, но прикольно. -3699.96 3721.08 SPEAKER_00 Дальше вы можете сказать, что на самом деле, на самом деле, это металлама, я так все, постшарп, постшарп, постшарп не единственная штука, которая позволяет, ну делать что-то подобное, то есть во-первых, есть постшарп действительно, во-вторых, есть сам рослинг, который что-то там позволяет, и в-третьих, есть еще такая штука, тоже, может быть, слышал или даже, наверное, какой-то, или выпиливал из проектов, это Фоди. -3721.08 3725.88 SPEAKER_01 Ну да, да, Фоди, мне кажется, самый популярный, потому что он бесплатен, в отличие от этого монстра. -3725.88 3764.80 SPEAKER_00 Ну да, вот, наверное, кстати, да, ты прав, мне вот Фоди, ну Фоди, кстати, я нигде не встречал в живых проектах, даже постшарп встречал почему-то, ну да ладно, значит, и там в этой статичке есть сравнение, что можно сделать с помощью постшарпа, розлина и Фоди, значит, и несколькими киллер-фичами, собственно, этой самой металламы, это как раз-таки отладка и экспорт трансформированного кода, то есть можно скомпилировать его со специальным ключиком, когда вы увидите весь код именно C#, да, он выплюнет его в какой-нибудь OPJ output, так, чтобы вы видели, как ваш код выглядит после того, как к нему применены все ваши аспекты. -3764.80 3769.32 SPEAKER_00 Ну и там всякие разные варианты, что ещё можно с ним делать. -3769.32 3775.08 SPEAKER_00 Значит, как ты правильно сказал, Фоди бесплатный постшарп. -3775.08 3778.56 SPEAKER_00 Я не помню, что там было с лицензиями, но по-моему, там какая-то версия была платная, там была какая-то -3778.56 3783.32 SPEAKER_01 бесплатная версия, но… Не знаю, я помню, что всегда постшарп был довольно дорогой штукой. -3783.32 3785.48 SPEAKER_00 Ну может быть, может быть, не помню. -3785.48 3791.72 SPEAKER_00 С Pentalama тоже история такая, что она частично платная, частично бесплатная. -3791.72 3798.40 SPEAKER_00 Ну точнее как, у неё есть несколько эдишенов, один из них это бесплатный эдишен, полный себе, берите, пользуйтесь. -3798.40 3802.92 SPEAKER_00 У него есть ограничения, то есть вот этих вот аспектов можно сделать три штуки максимум на проект. -3802.92 3820.92 SPEAKER_00 Ну и там другие есть, самые… Не будет никакого отладки, то есть вы не сможете делать степ-ин в Generated Code, то есть вы не сможете при отладке заходить в ваши аспекты внутрь, и у вас не будет там тестинг-фреймворка для ваших аспектов. -3820.92 3823.56 SPEAKER_00 Так, у них есть аж специальный тестинг-фреймворк для аспектов. -3823.56 3830.48 SPEAKER_00 Вот, и еще есть некоторое количество ограничений, но мне кажется, самое важное – это все самые три аспекта на проект. -3830.48 3833.28 SPEAKER_00 Если уж вы хотите в аспекты ориентирования и программирования, ну наверное, трех будет мало. -3833.28 3841.00 SPEAKER_00 Ну и даже там какие-то цены, понятно, я особо сейчас не буду распространяться, потому что всё это может меняться и так далее. -3841.00 3847.16 SPEAKER_00 Давай к интересной части, как это всё построено, как это всё устроено и на основе чего это всё сделано. -3847.16 3856.76 SPEAKER_00 Сам по себе metalama-компилятор, он open-source, его можно посмотреть, его можно взять, его можно использовать, и это просто форк рослина. -3856.76 3857.76 SPEAKER_00 Форк? -3857.76 3858.76 SPEAKER_01 Да. -3858.76 3859.76 SPEAKER_01 Прямо форк? -3859.76 3860.76 SPEAKER_01 Прямо форк. -3860.76 3861.76 SPEAKER_01 И как его поддерживают-то? -3861.76 3876.60 SPEAKER_00 То есть это прямо форк, если зайти в github-репозиторий metalama-компайлер, там прямо написано forked from.net/roslin, то есть это прямо не просто копия, знаешь, как иногда делают, типа ну клонируют и коммитируют к новой репозитории, это честный прямо форк в уровне гитхаба. -3876.60 3878.64 SPEAKER_01 Ну то есть они забираются как-то поддерживать. -3878.64 3902.12 SPEAKER_00 Да-да-да, они сделали следующую штуку, значит вот этот framework, который metalama-framework, она является по сути плагином для компиляторов в compile-time, или плагином для самого основного рослина, если у нас в design-time, в design-time ты же не можешь подменить рослин, который внутри студии живет, но можно к нему заплагиниться. -3902.12 3917.16 SPEAKER_00 Внутри рослина у нас есть аналайзеры и генераторы, то есть на основе аналайзеров можно делать любые аналайзеры, на основе генераторов можно генерировать новый код, тут все хорошо, и не хватало только трансформеров, вот они добавили концепцию трансформеров. -3917.16 3941.28 SPEAKER_00 Можно посмотреть, как это сделано, вероятно они собираются это дело поддерживать в том смысле, что когда будет меняться рослин под новые версии компилятора, они будут себе обновлять из AppStream, грубо говоря, основной рослин и допиливать свою поддержку вот этих source-трансформеров под какие-то новые фичи языка, например, и так далее. -3941.28 3944.56 SPEAKER_00 То есть но базовый рослин, базовый компилятор остается базовым. -3944.56 3947.08 SPEAKER_00 Прямо вот нативный, который берется из дотнета. -3947.08 3953.40 SPEAKER_01 Ну смотри, кажется, если вот думать, а как, можно было бы по-другому сделать, но это, скорее всего, один из самых лучших вариантов. -3953.40 3998.60 SPEAKER_00 Ну, кажется, что да, то есть они сказали, что они сначала пытались сделать это, там у них есть такие небольшие размышления какие-то, ну, историю, что они сначала делали это в private форке, не зная, насколько они смогут сделать прям вот такой форк, который можно будет именно обновлять из AppStream, но, видимо, все получилось, поэтому оно в open-source, его можно, если вам нужен рослин с source-трансформерами, можно взять Metalama Compiler, у него, по-моему, нормальная лицензия, если я правильно помню, а вот Metalama Framework, собственно, статья, из-за которой мы это все добавили сюда, снова всплыло оно в новостях, его тоже за open-sourcely, то есть вот этот Metalama Framework, который, как я сказал, он там платный, вот это все, он open-sourced. -3998.60 4004.92 SPEAKER_01 А как же там ограничение в три штучки, если любой дурак может пойти себе собственный фреймворк собрать? -4004.92 4010.04 SPEAKER_00 Вот, собрать ты его не можешь, по двум причинам. -4010.04 4011.60 SPEAKER_00 Причина первая, лицензия не позволяет. -4011.60 4014.20 SPEAKER_01 Погоди, у нас параллельный импорт, как лицензия. -4014.20 4015.20 SPEAKER_01 Давай по существу. -4015.20 4017.64 SPEAKER_00 Второе, там нет ничего для сборки. -4017.64 4018.64 SPEAKER_00 Исходники C#? -4018.64 4026.84 SPEAKER_00 Ну, как они сказали, мы выложили 99%, одного процента не хватает и без него вы не соберете это в нормальный работающий -4026.84 4027.84 SPEAKER_01 вид. -4027.84 4030.12 SPEAKER_01 Ну интересно, конечно, посмотреть, а что именно там не хватает. -4030.12 4035.50 SPEAKER_01 Мне кажется, что айтузоазисты, по сравнению с ценой на настоящую металламу, этот 1% должны дописать за один -4035.50 4036.50 SPEAKER_00 вечер. -4036.50 4037.50 SPEAKER_00 Ну, возможно, возможно. -4037.50 4040.80 SPEAKER_00 Я с интересом посмотрю, во что это превратится. -4040.80 4046.32 SPEAKER_00 Пока никаких следов я поискал, ничего не видно, никаких энтузиастов не появилось. -4046.32 4067.92 SPEAKER_00 И сделали они это для двух целей, соответственно, это упрощение отладки, потому что если у вас вдруг, видимо, они научены опытом постшарпа, который там портил лейкод и вот это все, короче, упрощает отладку, то есть вам нужно посмотреть, как оно там, черт возьми, трансформирует что-то куда-то, ну вот, пожалуйста, вот исходники. -4067.92 4080.08 SPEAKER_00 Ну и какая-то общая фраза про increase trust and transparency, вот это все, но 1% мы вам не дадим, но можно купить металлама source code subscription, и тогда вам дадут остатки исходников. -4080.08 4083.56 SPEAKER_01 Ну вот кто-то один, может, купит и выложит всего старым. -4083.56 4099.16 SPEAKER_00 Ну, короче, понятно, что способы есть наверняка, да, можно и по шармам было, наверное, бесплатно пользоваться, но как бы такой вот забавный, забавная, так скажем, забавный подход к open-source, посмотрим, человек. -4099.16 4118.76 SPEAKER_01 Нужно признать, что постшарп это один из просто старейших инструментов в дотнете, которые есть, если вспоминать какие-нибудь старые фреймворки, которые выжили, ну и выкинуть оттуда все юайные компоненты, то старее постшарпа, я не знаю, фреймворка коммерческого именно, который выжил, и парадокс в том, что я реально встречал его в многих компаниях. -4118.76 4129.36 SPEAKER_01 Ну, то есть, у него, наверное, была какая-то хорошая пиар-акция когда-то на заре времен, что его затащили и купили, главное, что смешно как бы, в очень большом количестве компаний. -4129.36 4134.08 SPEAKER_01 В общем, но я не встречал ни одной компании, которая об этом не пожалела и не хотела бы его выпилить. -4134.08 4145.32 SPEAKER_00 Ну, вот посмотрим металлам, может быть, кстати, они тоже этот тренд увидели, что там, не знаю, выпиливают, и юзедж сокращается, и продавать стало сложнее, и решили переписать это все на более безопасный вариант. -4145.32 4146.32 SPEAKER_01 Ну, да. -4146.32 4152.08 SPEAKER_00 И в принципе, если даже постшарп продавался с опасным вариантом, то этот тоже, наверное, будет продаваться. -4152.08 4158.12 SPEAKER_01 Ну, наверняка, опять же, потому что аспектно-ориентированное программирование дает нам очень много интересных возможностей. -4158.12 4160.76 SPEAKER_01 Особенно если мы говорим про сложные интерпрайзы, ну а где у нас еще деньги? -4160.76 4161.96 SPEAKER_01 Ну, естественно, в сложных интерпрайзах. -4161.96 4195.84 SPEAKER_01 В общем-то, там действительно есть случаи, когда таких инструментов не хватает, и если те инструменты не будут как бы пилить иль код, который ломается с новой версии компилятора, а все делается на честных генераторах, а честные генераторы, нужно понимать, их плюс, что теперь команда постшарпа металлама не отвечает за то, чтобы их поддерживать, теперь команда Рослина отвечает, что все, что было сгенерировано, компилировалось с любой версией компилятора, то у них там просто 80% всей работы с них спадает, и поэтому они могут больше сосредоточиться на каких-нибудь интересных фичах или тех же самых маркетинговых статьях. -4195.84 4207.20 SPEAKER_00 Не, ну те самые трансформеры все-таки Рослин никак не поддерживает, поэтому с ними-то как раз все еще мучиться надо, разбирать все новинки языка, чтобы понимать, как их трансформировать. -4207.20 4215.40 SPEAKER_01 Скорее всего тебе там нужно было просто сунуться в нужную точку и всё, а все новинки языка – это тебе просто-напросто существующая Рослин-дерево приходит и разбирает как хочешь. -4215.40 4226.68 SPEAKER_00 Не, ну Рослин-дерево – это большой бонус, понятно, и понятно, почему они взяли Рослин, это просто очевидно, что еще в тот ней-то брать, учитывая, что он тебе доступен, плюс-минус. -4226.68 4232.84 SPEAKER_00 Но все равно какая-то логика понятная, с самой металламой там есть, то есть как-то все эти нужно. -4232.84 4237.60 SPEAKER_01 Ну наверняка, мне просто кажется, что здесь в миллиард раз меньше усилий, чем поддерживать постшарп. -4237.60 4238.60 SPEAKER_01 Конечно, конечно. -4238.60 4240.40 SPEAKER_01 Постшарп вот с именем их, это вообще ужас. -4240.40 4241.40 SPEAKER_01 Да. -4241.40 4246.72 SPEAKER_01 И то работал, и то люди платили, и то были в принципе счастливы, поэтому да, наверное, свои вендоры найдутся. -4246.72 4256.60 SPEAKER_01 Ну если вы вдруг использовали или до сих пор самое интересное, почему-то используете постшарп, и при этом не хотите его выпиливать, прийдите в комменты, расскажите, что у вас за юзкейсы такие-то интересные. -4256.60 4260.36 SPEAKER_00 Ну или может быть проапгрейдитесь на металламу и посмотрите, что там как. -4260.36 4261.36 SPEAKER_01 Или так, да-да. -4261.36 4282.24 SPEAKER_01 Ну и чтобы далеко не отпускать металламу, надо признаться, что у металламы главный ментейнер и главный фаундер и лид-девелопер – это товарищ Гаэль, фамилию Фрайтер. -4282.24 4286.32 SPEAKER_01 Ты помнишь, как у него фамилия произносится? -4286.32 4296.52 SPEAKER_00 Я её обычно произношу Фрэтер, но он то ли француз, то ли бельгиец, я не помню, кто он. -4296.52 4305.16 SPEAKER_00 И у них как-то фамилия не всегда правильно, в смысле легко произносится, букв много, а иногда, как скажешь, так там это. -4305.16 4308.64 SPEAKER_01 Короче, в узком круге, да, он знаменит как Гаэль. -4308.64 4315.04 SPEAKER_01 В общем, Гаэль является фаундер и лид постшарпа, и естественно металламы той же самой. -4315.04 4324.84 SPEAKER_01 И вот Гаэль тут недавно пришёл и рассказал в статьечке, а каким образом они обеспечивают качество своих продуктов, даже качество кода. -4324.84 4331.16 SPEAKER_01 Так как они много выкладывают в open-source, все себе красивые, все такие, в общем в open-source код должен быть красивым. -4331.16 4333.88 SPEAKER_01 Работать не работай, там за лицензией или что-то это дело десятое. -4333.88 4335.16 SPEAKER_01 Главное, чтобы было красиво. -4335.16 4346.64 SPEAKER_01 И вот он пришёл и рассказал, а как же они собственно обеспечивают красоту своего кода, чтобы он был весь отлаженный, проанализированный, отформатированный, что у них там, собственно, в команде происходит. -4346.64 4347.64 SPEAKER_01 Давайте же нырнём. -4347.64 4350.52 SPEAKER_01 Раз продукт мы посмотрели, давайте посмотрим теперь, как они работают. -4350.52 4359.92 SPEAKER_01 И обсудим его статичку, которая называется Codestyle for Better Productivity, т.е. что же они там такого для улучшенной производительности делают со своим стилем кода. -4359.92 4389.84 SPEAKER_01 Ну, прежде всего, когда вы начинаете новый проект, то первые шаги, на которые вы должны сделать, это сделать так, чтобы в вашей команде удобно было работать вместе, и чтобы, например, тот код, который вы пишете, он был согласованным и все в команде его хорошо понимали, все хорошо представляли, в каком виде этот код надо писать, все хорошо понимали тот Codestyle, которому он должен соответствовать. -4389.84 4395.36 SPEAKER_01 Ну и даже если они плохо это понимают, что какие-то инструменты, били их по рукам и рассказывали, как надо понимать хорошо. -4395.36 4405.52 SPEAKER_01 Это означает, что вы должны на берегу ещё договориться, желательно до первой строчки кода, пока вы напишете, договориться о кодформатинге и нейминге. -4405.52 4415.40 SPEAKER_01 Ну, кодформатинг — это пресловутые вещи, там, табы против спейсов, сколько там пустых линий, пустых строчек оставлять, где расставлять скобочки, вот это вот все. -4415.40 4422.80 SPEAKER_01 И нейминги, то есть какие суффиксы давать, какие префиксы давать, что как называть, это все относится к неймингу. -4422.80 4436.56 SPEAKER_01 А также есть банальные какие-то вещи, там, использовать var, использовать this, ну, то есть самые священные страшные коровы, из-за которых только бывают войны, вот это все относится как раз к форматингу, неймингу и то, что мы сегодня будем с вами обсуждать. -4436.56 4462.14 SPEAKER_01 Поэтому желательно эти войны сделать до того, как вы пойдете писать код, потому что если эти войны будут начинаться постепенно, когда кто-то уже что-то написал, потом кто-то несогласен, взял переформатировал, сделал pull request, тот не одобрил, в общем, эти вот распри, они могут длиться еще дольше, чем то время, которое вы потеряете перед тем, как сесть вот на берегу и это все написать. -4462.14 4469.16 SPEAKER_01 И вот команда Metalama как раз хочет поделиться с нами своим опытом, как это происходило у них и что они делали. -4469.16 4471.80 SPEAKER_01 Прежде всего, зачем все это нужно? -4471.80 4473.44 SPEAKER_01 Ну, это консистентность. -4473.44 4485.04 SPEAKER_01 Консистентность прежде всего для чтения, когда вы читаете код и знаете, что он отформатирован одинаково во всех файлах, которые бы вы не открыли, вам его удобней читать, удобней по нему навигироваться, удобней по нему понимать. -4485.04 4503.08 SPEAKER_01 И так как по выдуманной статистике разработчик проводит 80% именно читая код, а не написывая его, то мы как раз увеличиваем вот эту вот самую главную точку, на которую он тратит свое время, мы как раз увеличиваем читабельность кода. -4503.08 4513.72 SPEAKER_01 Также единообразность кода дает вам возможность проще разбираться в коде и дает вам меньше конфликтов на мерш-реквестах. -4513.72 4527.36 SPEAKER_01 Или на pull-request, когда вы заливаете свой код, то если он отформатирован и украшен правильно, то в этот момент у вас будет меньше проблем с конфликтами, которые могли внести другие разработчики. -4527.36 4541.72 SPEAKER_01 Особенно если другие разработчики взяли и нажали там кнопочку какой-нибудь отформатировать, и все, весь файл, который вы там так радостно редактировали, вот эта функция форматирования она вам выдала сразу 100-500 конфликтов. -4541.72 4545.88 SPEAKER_01 В общем, весь файл поехал, и все, и формат превратился в какую-то для вас кашу. -4545.88 4551.08 SPEAKER_01 В общем, если вы вдруг используете единый код-стайл, то такой ситуации у вас уже технически даже быть не может. -4551.08 4561.60 SPEAKER_01 Так, теперь давайте посмотрим все-таки, откуда нам брать стили и как нам дойти к этому общему соглашению. -4561.60 4578.56 SPEAKER_01 Мы все знаем прекрасно, что у каждого, каждый человек это гребаная снежинка, и у этой снежинки есть какое-то свое мнение о том, каким образом должны расставляться табы и где быть скобочки, и если мы начнем об этом спорить, то такие священные войны, они могут продолжаться до бесконечности. -4578.56 4584.28 SPEAKER_01 Но, опять же, как советует автор, лучше все-таки договориться до начала написания кода. -4584.28 4586.52 SPEAKER_01 Как нам к этим можно договориться? -4586.52 4604.16 SPEAKER_01 Ну, прежде всего, с основу автор рекомендует взять стандарт Микрософта, у Микрософта есть такая прекрасная страничка, которая называется Common Coding Conventions for C#, то есть как ни трудно догадаться, там есть какие-то базовые основы, что в C# нормальном коде в современном должно быть. -4604.16 4612.24 SPEAKER_01 И там куча, кстати, интересных рекомендаций, если вы вдруг давно не обновляли или не знали, то можно просто пройти посмотреть, статичка не очень большая. -4612.24 4627.84 SPEAKER_01 Ну, кстати, оттуда же можно подчеркнуть такий интересный факт, что конфигура wait нужно использовать всегда, что нужно использовать space вместо табов, что ширина строчки должна быть 65 символов, не больше, и так далее. -4627.84 4635.64 SPEAKER_01 Такие базовые вещи, за которых многие спорят, их можно честно ссылаться на Микрософт и эти халевары такие заканчивать. -4635.64 4640.64 SPEAKER_01 Документ хороший, но, к сожалению, он не покрывает абсолютно всего. -4640.64 4645.48 SPEAKER_01 И мне кажется, это большая недоработка Микрософта до сих пор. -4645.48 4654.48 SPEAKER_01 Если бы она выпустила какой-нибудь документ, который, не знаю, как у Python, допустим, который строго говорит, как надо форматировать, и всё, ни шагу влево, ни шагу вправо. -4654.48 4656.68 SPEAKER_01 Мне кажется, было бы намного меньше у нас проблем. -4656.68 4667.12 SPEAKER_01 В общем, но опять же, оставим какое-то место, чтобы люди могли поспорить, поэтому Микрософт какие-то основные вещи обозначила, но обозначила не всё. -4667.12 4670.96 SPEAKER_01 И вот это не всё, вот этим уже нужно договариваться. -4670.96 4684.20 SPEAKER_01 Вот конкретно для каждого проекта вырабатывать какие-то договорённости, спрашивать опыт разработчиков на тех или иных проектах, в общем, каким-то образом пытаться это свести к какому-то общему договорённости. -4684.20 4692.68 SPEAKER_01 И как только мы все договорились, пусть даже кто-то из разработчиков не согласен в итоге с этой договорённостью, каждый разработчик обязан эти договорённости соблюдать. -4692.68 4694.60 SPEAKER_01 Без всяких обсуждений и так далее. -4694.60 4700.52 SPEAKER_01 Если эта договорённость зафиксирована в команде, то всё, дальше обратного хода уже никакого нет. -4700.52 4711.52 SPEAKER_01 Также ещё нужно помнить, что в принципе вырабатывание стандартов – это интеративный процесс, если вы до всего сразу не смогли договориться или все сразу скобочки не вспомнили, то естественно вы не обязаны это делать. -4711.52 4722.64 SPEAKER_01 Как только вы начнёте разрабатывать, и у вас станет такой вопрос, в будущем, а почему эта скобочка забыта здесь, и мы её не перенесли, вот в этот момент можно опять же этот вопрос поднять и снова вернуться к нашим скобочкам. -4722.64 4727.52 SPEAKER_01 Поэтому процесс итеративный, главное договориться о каких-то базовых вещах, и всё остальное потом можно дорабатывать. -4727.52 4730.96 SPEAKER_01 Так, теперь, предположим, вы договорились, что же дальше мы будем делать? -4730.96 4736.16 SPEAKER_01 То есть каким же образом нам теперь нужно сконфигурить наши инструменты для того, чтобы они нам помогали работать? -4736.16 4749.76 SPEAKER_01 Ну, прежде всего любая уважающая себя IDE должна поддерживать файлы Editor-Config, Visual Studio, Visual Studio Code, ReSharper, ReRider, и тому, и, в общем, мне кажется, всё, что возможно поддерживать сейчас Editor-Config и хотя бы в каком-то там минимальном его наборе. -4749.76 4755.68 SPEAKER_01 Поэтому рекомендуется добавить файл Editor-Config и обязательно залить его в репозиторий. -4755.68 4761.40 SPEAKER_01 То есть это не должен быть файл, который у каждого разработчика свой, куда-то он его там положил, где-то там заинклудил, нет. -4761.40 4771.32 SPEAKER_01 Это штука, которая лежит в репозитории, и он один у всех разработчиков, и более того, он один даже на Continuous Integration систему, она его в том числе обязана учитывать. -4771.32 4781.56 SPEAKER_01 В идеале вот этот файл, он не должен оставлять какого-то места для самовольности, да, то есть чтобы вот таких нелепых снежинок у нас не появлялось. -4781.56 4789.44 SPEAKER_01 Если у нас есть какое-то правило, как должен использоваться код, то он обязан прописываться в этом файле. -4789.44 4799.68 SPEAKER_01 В частности, рекомендуется выставить warning, где только возможно, на всех возможных там форматированиях, скобочках и так далее. -4799.68 4806.84 SPEAKER_01 В Editor-Config это можно прописать как warning, да, то, что если скобочка находится не на своем месте, он вам выдает warning. -4806.84 4815.76 SPEAKER_01 И при этом рекомендуется поддерживать zero warning код, да, то есть у вас там не должно быть warning в вашем коде, естественно, за этим надо следить. -4815.76 4821.84 SPEAKER_01 Вот, еще существует такой инструмент, как ReSharper Code Formatting. -4821.84 4830.80 SPEAKER_01 Наверняка каждый из вас сталкивался с непонятными файликами, которые появляются в вашем репозитории и имеют окончание .sln.dotsettings. -4830.80 4837.12 SPEAKER_01 Вот dotsettings, это и есть те файлики, которые создает ReSharper для того, чтобы доставить какие-то там свои настройки. -4837.12 4841.68 SPEAKER_01 И это гораздо более гибкий и мощный механизм, чем Editor-Config. -4841.68 4852.44 SPEAKER_01 Но в Editor-Config есть преимущество в том, что он cross-EDE-шный, а dotsettings - это штуки чисто JetBrains, поэтому никто, кроме JetBrains их не понимает, но зато они более мощные. -4852.44 4869.92 SPEAKER_01 У JetBrains'ких tools есть такая прекрасная штука, как слоеные настройки, когда вы можете этих dotsettings наделать сколько угодно, разложить их по папочкам, заинклюдить там друг друга и, соответственно, сделать какой-то dotsettings, который шарится между всей командой. -4869.92 4877.36 SPEAKER_01 И сохранить его в отдельный файлик, и вот этот dotsettings, который шарится между всей командой, естественно, тоже должен быть в репозитории. -4877.36 4878.36 SPEAKER_01 Там ему самое место. -4878.36 4880.36 SPEAKER_01 Так, переходим дальше. -4880.36 4889.52 SPEAKER_01 Теперь мы договорились о каких-то настройках, законфигурировали, чтобы они у нас где-то хранились, как мы, собственно, будем применять форматирование. -4889.52 4899.52 SPEAKER_01 Есть такой процесс, который называется CodeCleanup, и подразумевает, что код каким-то образом чистится в соответствии с теми настройками, которые находит этот инструмент. -4899.52 4903.24 SPEAKER_01 Что здесь стоит сказать? -4903.24 4917.28 SPEAKER_01 Так как CodeCleanup обычно выполняется автоматически, то есть не хочется, чтобы человек смотрел и сравнивал, а что там, собственно, нужно закленапить, как там что-то нужно выровнять, обычно так не делается. -4917.28 4922.68 SPEAKER_01 Обычно просто запускается автоматический Cleanup, он проходится по всем файлам, и все файлы выравниваются, чтобы были все равны. -4922.68 4929.44 SPEAKER_01 Поэтому, тут встает хороший вопрос, а что включать в CodeCleanup, а что включать не стоит? -4929.44 4933.12 SPEAKER_01 То есть какие форматоры, какие фиксеры нужно включать? -4933.12 4935.52 SPEAKER_01 В общем, критерий довольно простой. -4935.52 4939.20 SPEAKER_01 Стоит включать те фиксеры, которые 100% не дадут вам ошибок. -4939.20 4945.68 SPEAKER_01 Ну, например, есть фиксер, который говорит, на каких строчках должны расставляться скобочки фигурные. -4945.68 4955.24 SPEAKER_01 Договорились вы в компании, что фигурные скобочки расставляются там каждая на своей отдельной строке, и они обязательны для любого стейтмена, ну и все, и это можно применить автоматически, никаких проблем с этим не будет. -4955.24 4960.12 SPEAKER_01 А есть код-фиксер, который, например, проставляет ReadOnly в вашем приватном поле. -4960.12 4965.80 SPEAKER_01 И этот код-фиксер может быть очень опасным, особенно если вы случайно проставите ReadOnly к какой-нибудь структурке. -4965.80 4975.64 SPEAKER_01 И это может привести к очень большим багам, и притом багам неочевидным, которые можно поймать только по утечке ресурсов, профайлером и так далее. -4975.64 4983.96 SPEAKER_01 В общем, такие фиксеры в Cleanup включать нельзя, потому что вы можете поймать очень много проблем с ними. -4983.96 4991.06 SPEAKER_01 Вот на вот эти два набора вам и стоит разделить код-Cleanup, который можно применять автоматически, и который автоматически примерять не стоит. -4991.06 4997.96 SPEAKER_01 Также, когда вы запускаете код-Cleanup, у вас должна быть 100% гарантия, что там будет все хорошо. -4997.96 5000.36 SPEAKER_01 Вот почему мы должны выбирать именно правильные фиксеры. -5000.36 5010.72 SPEAKER_01 Поэтому любой член команды должен запускать код-Cleanup без всяких там ручных галочек, без каких-нибудь там хаков, и при этом он не должен бояться, что что-то сломается. -5010.72 5015.12 SPEAKER_01 Он должен уверенно, всегда, без всяких проблем запускать свой код-Cleanup. -5015.12 5020.68 SPEAKER_01 Поэтому к настройке вот этого нужно подойти довольно таки хорошо и тщательно. -5020.68 5021.68 SPEAKER_01 Инструменты. -5021.68 5035.28 SPEAKER_01 Visual Studio, прежде всего, она поддерживает код-Cleanup, но, к сожалению, у нее нет возможности сохранить тот профиль, который вы наконфигурировали, сохранить его в виде какого-то отдельного файлика для того, чтобы закинуть Source Control. -5035.28 5038.56 SPEAKER_01 В общем, почему-то они это не сделали. -5038.56 5049.92 SPEAKER_01 А это ключевой момент, потому что те фиксеры, тот Cleanup, тот вид кода, который должен быть у вашего приложения, его должны использовать абсолютно все члены команды. -5049.92 5052.28 SPEAKER_01 Они должны использовать один и тот же профиль. -5052.28 5056.96 SPEAKER_01 Не бывает такого, что каждый настраивает, как хочет, и потом все вместе пытаются дело смешать. -5056.96 5072.80 SPEAKER_01 У JetBrains, у райдера в частности, дела намного лучше, потому что он позволяет сохранить все настройки код-Cleanup в тот самый settings-слоеный файлик, который, естественно, можно расшарить между командой и залить в репозиторий. -5072.80 5081.56 SPEAKER_01 Также райдер позволяет автоматически запускать код-Cleanup, например, перед каждым коммитом, что тоже бывает довольно удобно. -5081.56 5088.72 SPEAKER_01 Но UGL все-таки настаивает, что решение должно быть не привязано к конкретному вендору. -5088.72 5096.40 SPEAKER_01 Они пользуются и тем, и тем, но желательно, конечно, найти какое-то решение, которое бы не зависело от конкретного вендора. -5096.40 5099.44 SPEAKER_01 Тут мы, к сожалению, сейчас ничего не можем предложить. -5099.44 5106.56 SPEAKER_01 У нас есть или решение от Microsoft, или решение от JetBrains, и у каждого есть свои плюсы и минусы. -5106.56 5110.92 SPEAKER_01 Так, давайте теперь посмотрим на сам процесс, на как же собственно команде с этим совсем работать. -5110.92 5131.32 SPEAKER_01 Ну, прежде всего нужно понимать, что если вы слишком сильно затянете гайки, например, ограничите количество пробельщиков, которые у вас может в коде быть, то это приведет к тому, что при каждой проверке, при каждом комите, у вас будет очень много ошибок. -5131.32 5139.48 SPEAKER_01 То есть вам будет какой-нибудь анализатор, какой-нибудь форматор сообщать, что вот смотри, ты тут не тот пробельщик поставил, подсмотри, ты тут форматирование не так красиво сделал, как могло бы быть. -5139.48 5144.20 SPEAKER_01 И, в общем, это все вернет, ведет к деградации производительности именно разработчиков самих. -5144.20 5153.96 SPEAKER_01 А тут нужно понимать, что, в принципе, кодстайл и форматинг, они не призваны к тому, чтобы ухудшить продуктивность разработчиков. -5153.96 5155.76 SPEAKER_01 Наоборот, они хотят ее улучшить. -5155.76 5168.16 SPEAKER_01 В общем, здесь вам как раз нужно соблюсти баланс, потому что если вы сделаете слишком строгие правила, вот этого будут страдать разработчики, а если сделаете слишком слабые правила, то от этого будет страдать код. -5168.16 5169.76 SPEAKER_01 То есть у вас код уже не будет таким консистентным. -5169.76 5173.24 SPEAKER_01 И вот выбор этого баланса – это задача каждой конкретной команды. -5173.24 5178.62 SPEAKER_01 Гаэль со стороны команды может бросить несколько советов. -5178.62 5187.62 SPEAKER_01 Прежде всего, выставляйте уровень анализов, кодстайл анализов в ворнинг. -5187.62 5195.18 SPEAKER_01 Это тоже можно регламентировать, какой анализ, какой уровень вам предупреждения выдаст. -5195.18 5199.66 SPEAKER_01 Он говорит, что ворнинг – это то, что команда обязана соблюдать. -5199.66 5201.22 SPEAKER_01 То, через что переступить нельзя. -5201.22 5211.86 SPEAKER_01 Далее, убедитесь, что вы проверяете код анализ при каждом билде. -5211.86 5214.54 SPEAKER_01 То есть вы проводите код анализ при каждом билде. -5214.54 5228.34 SPEAKER_01 Для этого достаточно выставить свойство, которое называется «Enforced code style in build» в директоре buildprops, то есть это стандартная мс-билдовская настроечка, которая вам как раз будет этот анализ проводить. -5228.34 5239.82 SPEAKER_01 Еще один интересный момент, что в команде металлама позволяется допускать ворнинги на машине разработчика. -5239.82 5250.68 SPEAKER_01 На машине разработчика, пока разработчик не дописал код, и он хочет просто-напросто запустить тест или еще что-то, нет никакого смысла обламывать ему компиляцию. -5250.68 5253.30 SPEAKER_01 Поэтому ворнинги на машине разработчика вполне допустимы. -5253.30 5255.16 SPEAKER_01 С этим проблем нет никаких. -5255.16 5264.20 SPEAKER_01 Но вот на CI-системе у них выставлен флаг «Thread warnings as errors», то есть на CI-системе любой ворнинг приводит к ошибкам. -5264.20 5274.52 SPEAKER_01 Чтобы задетектировать ситуацию, когда ваш мс-билд скрипт запускается на CI-системе, есть прекрасное свойство, которое называется «Continuous integration build». -5274.52 5276.96 SPEAKER_01 Оно может иметь значение true или false. -5276.96 5288.00 SPEAKER_01 Интересное значение, то есть интересное свойство, я почему-то раньше на него внимания не обращал, я знал, что каждая система выставляет, каждая CI-система выставляет какие-то свои настройки окружения, в общем. -5288.00 5294.00 SPEAKER_01 А тут появилось такое универсальное, которое само я так понимаю анализирует все эти настройки и выводит вам в каком-то одном предсказуемой свойстве. -5294.00 5295.52 SPEAKER_01 В общем, тоже полезная штука. -5295.52 5302.24 SPEAKER_01 Далее, из советов, включите различные код-анализы. -5302.24 5307.84 SPEAKER_01 Для этого есть специальная статейка от Microsoft, которая называется «Обзор.NET Source код-анализов». -5307.84 5315.02 SPEAKER_01 Там рассказывается, какие код-анализы есть, как их включить, что они там красиво ищут, ну в общем, это стандартные вот эти розлиновские подсказы-возвращенники. -5315.02 5318.44 SPEAKER_01 Такие умные, хорошие, прям некоторые из них просто must-have. -5318.44 5321.00 SPEAKER_01 Поэтому можно не пренебрегать чистой совестью. -5321.00 5329.94 SPEAKER_01 Также Metalama Team использует StyleCop, который сейчас интегрирован прям в розлин-компайлер и является частью C#-компилятора. -5329.94 5338.88 SPEAKER_01 Так, теперь насчет того, а когда же нужно все-таки применять Clion App и как с этим поступать. -5338.88 5347.00 SPEAKER_01 В общем, Гаэль говорит, что, в принципе, погоня за тем, чтобы каждый pull-request был идеально отформатирован, она бессмысленна. -5347.00 5352.04 SPEAKER_01 И поэтому в каждом pull-request они такую проверку не вставляют. -5352.04 5358.68 SPEAKER_01 И при этом со временем у них набирается, соответственно, вот этот, грубо говоря, технический долг по форматированию. -5358.68 5362.20 SPEAKER_01 То есть у них код не всегда идеально отформатирован. -5362.20 5380.24 SPEAKER_01 И они раз в какой-то промежуток времени, то есть в их случае перед фризом майлстоуна, это происходит где-то в 6-12 недель, они запускают полный код Clion App и преобразуют всю их кодовую базу к красивому, понятному виду. -5380.24 5382.48 SPEAKER_01 Не знаю, я этого аргумента, если честно, не понял. -5382.48 5391.80 SPEAKER_01 То есть намного легче, кажется, и соответствует всем признакам того, что Гаэль говорил вначале, намного легче перед каждым pull-request заставлять форматировать код правильно. -5391.80 5399.88 SPEAKER_01 И тогда у вас в репозитории будет вливаться красивый код, в pull-requests и в merge-requests будет красивый код, и другие разработчики будут ревьюить красивый код. -5399.88 5403.04 SPEAKER_01 Никакого смысла допускать это раз в 12 недель, вообще никакого нет. -5403.04 5404.04 SPEAKER_01 Поэтому не знаю. -5404.04 5412.80 SPEAKER_01 На своей практике мы перед, то есть у нас проверка на соответствие эдитер-конфигу, она запускается на каждый билд, на каждый merge-request. -5412.80 5416.76 SPEAKER_01 То есть вы не можете в мастер залить код, который плохо отформатирован. -5416.76 5419.04 SPEAKER_01 И минусов этого подхода я не вижу. -5419.04 5434.00 SPEAKER_01 Так, следующий момент, он повторяется, что запуск клеонап-тулза должен быть полностью предсказуемый, не должен доставлять каких-то неудобств неразработчикам, не должен вводить в ступор ревьюеров, ничего. -5434.00 5438.48 SPEAKER_01 Он должен строго красиво отрабатывать и делать предсказуемые вещи. -5438.48 5444.28 SPEAKER_01 Для того, чтобы так можно было делать, нам нужен клеонап на основании каких-то настроек. -5444.28 5456.32 SPEAKER_01 У нас из инструментов, из инструментов для того, чтобы это делать, например, на Continuous Integration Server, нам нужен какой-то инструмент, который не зависит от локального и локального энвариомента разработчика. -5456.32 5465.56 SPEAKER_01 Прежде всего, это .NET-формат, это консольная утилитка, которая форматирует ваш код в зависимости от того, что написано в Editor Config. -5465.56 5479.16 SPEAKER_01 Это сейчас самая стандартная, самая полная, самая красивая из всех .NET-утилиток, которые есть, поддерживается она непосредственно Microsoft, и поэтому, как минимум, вы должны поддерживать ее. -5479.16 5485.60 SPEAKER_01 То есть как минимум она прекрасна, она хороша, и она понимает хотя бы базовые вещи Editor Config. -5485.60 5490.04 SPEAKER_01 Огромным ее минусом является то, что понимает она не все. -5490.04 5494.24 SPEAKER_01 Понимает она даже, честно сказать, мало, поэтому все с помощью нее отформатировать невозможно. -5494.24 5508.68 SPEAKER_01 На помощь приходит JetBrains, ну кроме того, что у JetBrains есть интерактивный клеонап, который может воспользоваться каждый разработчик, опять же, нас больше интересует автоматизированность системы, и есть такой прекрасный инструмент, который называется ReSharper Kleonap Command Line Tool. -5508.68 5518.36 SPEAKER_01 Это тоже консольная утилита, которая понимает .settings файлы, в которых можно сохранить намного больше настроек, и с помощью которых вы можете автоматически тоже все форматировать. -5518.36 5540.16 SPEAKER_01 И теперь, чтобы этот формат тоже был более-менее предсказуемый на каждой машине, потому что что ReSharper-овская утилита, что .NET-формат, они имеют кучу настроек, и в зависимости от того, какие настройки вы туда передадите, по каким путям найдутся файлы конфигурации, опять же, формат может отличаться. -5540.16 5549.44 SPEAKER_01 Поэтому рекомендуется сделать какой-то предсказуемый скрипт, и в этом скрипте заполнить, записать все точные параметры, с помощью которых должны запускаться эти утилиты. -5549.44 5552.32 SPEAKER_01 Может быть, даже не одна утилита, а несколько утилит. -5552.32 5561.48 SPEAKER_01 Чтобы, несмотря на то, где этот скрипт запущен, у локального разработчика или на CI-системе, он всегда стабильно выдавал один и тот же результат. -5561.48 5563.96 SPEAKER_01 Поэтому все это нужно сделать именно так. -5563.96 5584.96 SPEAKER_01 Это базовые вещи, которые просто обязаны быть в любом проекте, но если вы их вдруг здесь сделали, то если они у вас есть, то вы большой молодец, но если вы хотите пойти дальше, то можно вернуться, то есть можно уже углубиться в какие-то более интересные аспекты, которые также можно отнести к качеству кода. -5584.96 5603.80 SPEAKER_01 Ну, например, можно проверять, что если у вас есть интерфейс iFactory, то все классы, пронаследованные от этого интерфейса iFactory обязаны заканчиваться на слово "factory", или более ближе, наверное, к каждому разработчику, это все, что пронаследовано от атрибута, от системы атрибут, должно заканчиваться на слово "атрибут". -5603.80 5606.76 SPEAKER_01 То есть вот такие вещи, если вы хотите поддерживать в своем проекте. -5606.76 5625.56 SPEAKER_01 Ну или что-то более сложное, например, если у вас есть неймспейс биллинга, то в этом неймспейсе никогда не должны использоваться даблы, потому что любые там деньги мы подразумеваем, что в биллинге должны обрабатываться с помощью интов или с помощью децималов. -5625.56 5634.08 SPEAKER_01 Такие условия тоже можно писать, их можно проверять, но это уже не обойтись нам какими-то простыми средствами, которые чисто для кодформатирования придуманы. -5634.08 5636.64 SPEAKER_01 Есть более интересные, более глубокие средства. -5636.64 5639.04 SPEAKER_01 Во-первых, это архитектурные тесты. -5639.04 5648.88 SPEAKER_01 Кстати, если вам интересно поговорить про архитектурные тесты, обязательно напишите нам в комментариях, у нас лежит статьечка про них, мы давно ждем какого-нибудь хорошего повода. -5648.88 5656.20 SPEAKER_01 Ну и второй инструмент, который Каэль не мог не предложить, это металлама, который мы как раз-таки сами обсуждали. -5656.20 5664.80 SPEAKER_01 То есть с помощью аспектно-ориентированных вот этих навешанных атрибутов мы можем сделать все вот эти проверки, ну и даже больше, как Игорь упоминал в предыдущей статье. -5664.80 5681.16 SPEAKER_01 В общем, вот такое развитие, вот такие базовые инструменты, поэтому если вдруг вы нашли что-то интересное, какие-то интересные анализаторы техники, которые у вас еще не применяются, рассмотрите возможность, потому что никогда не бывает мало красивого кода, красивый код должен быть всегда много и стандартный между всей командой. -5681.16 5697.40 SPEAKER_00 Да, прикольно, ну иметь такой максимально автоматизированный способ поддерживать кодовую базу в нормальном состоянии, это самое, да, наверное, довольно сложно, чтобы его внедрить, ну потому что надо всем договориться, но зато потом жить проще. -5697.40 5698.40 SPEAKER_00 Проверено. -5698.40 5709.08 SPEAKER_01 Ну да, особенно прекрасно, когда вы начинаете его внедрять прямо в новом проекте, когда ни о чем договариваться, там ничего переписывать не надо, договариваться все равно придется, переписывать ничего не надо, это самый большой бич. -5709.08 5731.08 SPEAKER_00 С этим старым проектом, как правило, в общем, включаете анализаторы, фиксите какое-то ограниченное время, максимальное количество самых явных проблем, так скажем, и дальше потихонечку включаете, все больше и больше, потихонечку дофикшивая, инкрементно, не спеша, ну или наоборот поспешает, в зависимости от того, сколько у вас времени и команды есть. -5731.08 5732.08 SPEAKER_00 Ну чё, давай дальше. -5732.08 5733.08 SPEAKER_00 Еще, да? -5733.08 5734.08 SPEAKER_00 Еще хотите? -5734.08 5735.08 SPEAKER_00 Мало? -5735.08 5741.28 SPEAKER_00 Давай, давай, да, мы же это до 2 часов должны добить, мы же собирались писать выпуск на 1 час. -5741.28 5747.92 SPEAKER_01 Да, мы собирались записать коротенький выпуск, что получится, ну уже понятно, что получится, поэтому давай во все чашки, что что. -5747.92 5788.20 SPEAKER_01 Ладно, небольшие вбросы от Фил Хака, как бы не мог пропустить, потому что Фил Хак пишет довольно редко, не знаю, год назад у него последний раз в блокпост выходил, и в принципе, хорошую тему он поднял, он написал в своем твите следующую штуку, что это в принципе не самая великолепная аналогия, но все-таки попробуйте поразмыслить, что Aspire, ну как вы могли выпуск без Aspire сделать, правда же, Aspire, Aspire это как Nuget, только для облачных сервисов, то есть когда мы делали Nuget, наша задача была, это как можно проще затаскивать к себе различные библиотеки, различные зависимости в наших проектах. -5788.60 5838.76 SPEAKER_01 Ну и до того, как появился Nuget, слишком много это нам приносило неудобств и боли, потому что нам нужно было их как-то найти, определить, какой версии мы хотим, как-то затащить свой проект, как-то их где-то прописать, что делает сейчас Nuget автоматически, мы даже об этом не задумываемся, мы не понимаем, на какой огромный пласт сложности он нас убирает, и в наше время как раз мы сталкиваемся почти с такой же точной проблемой, у нас есть Postgres, у нас есть RabbitMQ, у нас есть всякие Kafka, всякие memcache, и все это точно такие же сервисы, которые нужны нашему приложению в качестве зависимости, и мы точно так же должны понять, откуда мы их возьмем, о какой версии, а как мы их к себе притащим, а как сконфигурируем, и в принципе те же самые задачи, но просто немножко на другом уровне перед нами стоят. -5838.76 5841.56 SPEAKER_01 Разберемся с этой мыслью. -5841.56 5842.72 SPEAKER_01 Зачем придумался Nuget? -5842.72 5858.12 SPEAKER_01 В общем, если мы почитаем там первые постулаты, зачем был нужен Nuget, то, как я уже упоминал, у нас была большой комьюнити, в котором было много библиотек, и среди этих библиотек ориентироваться было довольно-таки сложно. -5858.12 5881.56 SPEAKER_01 Неизвестно, кто был в каком состоянии, через как он распространялся, как его в конце концов было заподключить в свой проект, и где его найти, и как с этим проектом его потом таскать, эти библиотеки, в общем, все те проблемы, которые очень хорошо будут вам видны, если вы сходите в какой-нибудь язык, в котором до сих пор проблемы с такими системами контроля версий. -5881.56 5889.00 SPEAKER_01 Допустим, у C до последних времен были очень большие проблемы, а сейчас средние проблемы с этим. -5889.00 5899.48 SPEAKER_01 Ну, то есть, представляете, самый, наверное, древний из мейнстримовых языков до сих пор не обзавелся системой наподобие Nuget, системой, которая управляет его пакетами. -5899.48 5909.48 SPEAKER_01 И там люди довольно страдают, вплоть до того, что передают друг другу DLL в виде zip архивчиков и каким-то образом версионируют их по-старинке. -5909.48 5927.72 SPEAKER_01 В общем, Nuget сделал для нас огромный шаг вперед, то есть он уменьшил количество тех операций, которые нам необходимы для того, чтобы было найти пакет, установить его и вместе с проектом каким-то образом сопровождать, обновлять и так далее. -5927.72 5963.00 SPEAKER_01 И что немаловажно, Nuget все это сделал абсолютно бесшовно, то есть мы получили очень хороший опыт нового разработчика, когда он может склонировать просто репозиторий из нашего центрального хранилища, нажать F5 и у себя локально этот проект запустить, не загоняясь о том, что под капотом там происходит .NET restore, который лезет где-то, достает актуальные версии библиотек, который их куда-то подключает, как-то складывает, где-то копирует, разрешает конфликты, в общем, под капотом там творится очень много сложной магии, сложной операции. -5963.00 5969.96 SPEAKER_01 Для обычного разработчика ты склонировал, нажал F5, проект у тебя запустился и этот опыт очень дорогого стоит. -5969.96 5979.32 SPEAKER_01 И теперь если мы взглянем на наши облачные сервисы, которыми нас со всех сторон пытаются окутать, то там же происходит такая же точная ситуация. -5979.32 5986.80 SPEAKER_01 У нас есть зависимости у нашего проекта и эти зависимости обычно от каких-то других сервисов, которые есть. -5986.80 6002.56 SPEAKER_01 Уже просто так нельзя, мы не можем уже просто так взять и запустить наш проект с помощью F5, мы обязательно требуем какую-то базу данных, может быть какой-то кэш, может быть какую-то очередь, без этого наш сервис может быть не стартануть, а если в хорошем случае он и стартанет, то работать он точно не будет. -6002.56 6017.64 SPEAKER_01 И .NET expire здесь очень похож на Nuget, вот в .NET expire как раз и входит задача уменьшить количество тех шагов, которые нам нужны для того, чтобы добавить, для того, чтобы внедрить вот эти клауд сервисы, облачные сервисы в наше приложение. -6017.64 6026.40 SPEAKER_01 Но в отличие от обычных библиотек, с которыми работает Nuget, у облачных сервисов гораздо больше различных требований. -6026.40 6034.56 SPEAKER_01 Их нужно каким-то образом настроить, их нужно каким-то образом задеплойить, их нужно каким-то образом мониторить. -6034.56 6038.92 SPEAKER_01 В общем, там стоит намного больше задач, чем стояло перед Nuget. -6038.92 6047.92 SPEAKER_01 Или, допустим, если мы берем connection string, то их нужно каким-то образом пробросить между сервисами, и желательно все это сделать безопасно, чтобы никакие лишние пароли никуда не утекли. -6047.92 6054.92 SPEAKER_01 И expire как раз и позволяет это все делать, он как раз и призван нам для того, чтобы упростить все эти точки. -6054.92 6063.44 SPEAKER_01 Он знает, откуда затянуть, он знает, как настроить, он знает, как отмониторить, как вам даже это показать в красивом дашборде, и даже пытается как-то дружить с секьюрити. -6064.04 6070.68 SPEAKER_01 Поэтому он примерно эти вещи и решает, но только для веб-сервисов. -6070.68 6082.04 SPEAKER_01 В комментариях тут же набежала куча народу и сказали, что в принципе есть какое-то сходство, но вам не кажется, дорогой сударь, что это больше не про expire, а про докер? -6082.04 6114.12 SPEAKER_01 Ведь это именно докер позволяет нам хорошо упаковать сервисы, как упакуются Nuget пакеты, и именно докер позволяет вам локально это все запустить, как делается локальный дотнет рестор, и в принципе докер - это ключевая технология, которая должна ассоциироваться с Nuget, но ни разу не expire, на что в принципе Фил Хак резонно заявляет, что докер - это всего лишь навсего формат хранения, как для Nuget формат хранения - это zip. -6114.12 6115.12 SPEAKER_01 Хороши ли zip архивы? -6115.12 6116.12 SPEAKER_01 Да, хороши. -6116.12 6120.76 SPEAKER_01 Позволили ли нам в виде одного красивого файлика доставлять любые данные на клиента? -6120.76 6121.76 SPEAKER_01 Да, позволили. -6121.76 6122.76 SPEAKER_01 А упаковать локально? -6122.76 6123.76 SPEAKER_01 Да, тоже позволили. -6123.76 6125.88 SPEAKER_01 Но все-таки Nuget - это нечто большее. -6125.88 6129.36 SPEAKER_01 Так же точно и expire - это нечто большее над обычным докером. -6129.36 6141.08 SPEAKER_01 Это то, что вам как раз делает провиженинг, конфигурацию, диплоймент, какой-нибудь security management, сервис-дискавери, вот это вам все делает именно expire, и докер этого из коробки сделать не может. -6141.08 6151.52 SPEAKER_01 Поэтому у expire намного больше преимуществ для того, чтобы вот этот workflow заклонировал и запустил, сделать реальным на локальном компьютере. -6151.52 6154.08 SPEAKER_01 Больший преимуществ, чем у простого докера. -6154.08 6163.72 SPEAKER_01 У простого докера с этим будет намного больше проблем, а у expire все-таки мы можем получить тот долгожданный экспириенс, когда мы заклонировали репозиторий, нажали в пять и у нас все работает. -6163.72 6172.52 SPEAKER_01 Но теперь оно работает не просто так, не просто потому что есть какие-то зависимости, а еще он и эти зависимости к себе подтаскивает. -6172.52 6177.56 SPEAKER_01 Подтаскивает, обновляет, мигрирует, связывает друг с другом и показывает в удобном дэшбарде. -6177.56 6184.68 SPEAKER_01 И вот этот экспириенс, когда заклонировал и запустил, вот этот наброс возвращается даже в наших самых сложных приложениях, которые только можно было придумать. -6184.68 6197.36 SPEAKER_01 Вот такой интересный наброс, в общем, поэтому, может, когда вы в следующий раз будете смотреть на expire или объяснять кому-то, что такое expire, аналогия, что это nuget для облачных сервисов, будет для вас близка. -6197.36 6218.88 SPEAKER_00 Ну да, и посмотрим, куда подвинется expire, потому что у нас был в каком-то из чатиков ссылочка на отдельный сайт под названием expire-dashboard.com, где прям вообще такой супер модный сайт, супер рекламирующий этот самый expire, ну для программистов рекламирующий, понятное дело. -6218.88 6226.24 SPEAKER_00 Со всякими трейсами, там open telemetry, примеры кода на питончике, на джаве, на джава скрипте, на c-шарпе, в общем, прям это очень классно выглядит. -6226.24 6236.48 SPEAKER_01 Ну да, знатный сайт, прям, который видно, что продает отдельный продукт expire-dashboard, ну как продает, он, естественно, фришный, но заставляет задуматься, не хотите ли вы его завязать. -6236.48 6243.96 SPEAKER_00 Поэтому, да, хорошо, что… Да, то есть именно прям вот видно, что дешборд они как-то отдельно продвигают и показывают. -6243.96 6259.00 SPEAKER_00 А вторая половинка, это вот тот самый provisioning, который уже делается, если вы полноценно тащите expire в важный проект, он тогда, да, позволяет вам всё это дело запровиженить и удобно использовать. -6259.00 6264.04 SPEAKER_00 Ну и хорошо, давай мы будем потихонечку загругляться. -6264.04 6271.76 SPEAKER_00 В этот раз есть только одна новость из кратко о разном, это про .NET Eventing Framework. -6271.76 6383.80 SPEAKER_00 Если вы помните, наверное, месяца два назад, может быть три, я упоминал про то, что в гитхабе Майкрософта появилась ишью, по-моему, в рантайм, нет, наверное, не в рантайм, там, где, короче, библиотечки живут, репозитории, появилась ишью, которая называлась .NET Eventing Framework, туда набежала куча народу, про то, что ой, всё, вы сейчас убьёте, всё, значит, так сказать, стороннее open-source ПО вокруг ивентинга, то есть все какие-то мастранзиты и сервисбас больше будут не нужны, и Майкрософт напишет свой ивентинг фреймворк, причём, ну, были те, кто вот так вот с этой стороны жаловался, были те, кто говорили, наконец-то, нормальный ивентинг фреймворк от .NET, выкинем нафиг мастранзиты, сервисбасы, всё, ну, в общем, как обычно, все разделились на несколько лагерей, при том, что Майкрософт это всё говорил, да ладно вам, что вы это, мы только делаем там для Azure Functions и вебджобов, как бы узкая нишевая штука, ну, назвали, как бы, ивентинг фреймворк, ну, на самом деле это, типа, только для конкретного юзкейса, вот, но в результате там ишьи, по-моему, обсуждения идут до сих пор, не помню, сколько там, сотен комментариев уже, но смысл в том, что вот буквально недавно Майкрософт таки сказали, Фаулер, Дэвид Фаулер написал в этой ишьи, что мол, не, значит, мы комьюнити услышали, никаких, по крайней мере, в девятом .NET ивентинг фреймворка не будет и что мы будем использовать, так сказать, open design process for future version, то есть они не отказываются от идеи сделать какой-то ивентинг фреймворк, но судя по тому, что они будут использовать, так сказать, engage-ить весь open source комьюнити в то, чтобы с правильной фреймворкой дизайнить, таки, видимо, там всё-таки должен был получиться какой-то чуть более глобальный ивентинг фреймворк, чем просто для Ажура, но вот посмотрим, будет ли нас с заменой масс-транзита и энд-сервис баса, но, видимо, уже в тот на десять дней раньше. -6383.80 6402.20 SPEAKER_01 Слушай, ну обидно, обидно, я как раз из тех, кто хотел бы всё-таки получить какой-то стандарт ивентинга, потому что сейчас задолбали как бы изобретать какие-то убогие колечные консюмеры, очень не хватает, не хватает такого же вот, как мы сделали для контроллеров, какой-то стандарта, вот такого же нужно для ивентинга. -6402.20 6409.40 SPEAKER_00 Ну посмотрим, может, что и сотворят, и неплохое, и в сообществе с open-source будет даже как-то совместимо. -6409.40 6419.80 SPEAKER_00 По большому счёту же им нужно сделать что-то а-ля iLogger, то есть какой-то как бы интерфейс, им не обязательно делать реализацию в целом, а дальше все остальные подстроятся. -6419.80 6424.08 SPEAKER_00 Ты же используешь Serilog в качестве как бы подкладки под iLogger реализации? -6424.08 6434.20 SPEAKER_01 Да, да, но это, наверное, единственное, что выжило после всех контейнеров, после всех логеров, после всех тех же самых minimal API, Serilog единственный, кто выжил. -6434.20 6435.20 SPEAKER_01 Ну вот посмотрим. -6435.20 6436.20 SPEAKER_01 Поэтому не зарекайся. -6436.20 6438.08 SPEAKER_01 Ну глянем, что будет. -6438.08 6444.00 SPEAKER_01 Ну ладно, давай закругляться, вроде уложились, пусть не в 1 часик, но в 2. -6444.00 6474.16 SPEAKER_00 Ну в 2, я надеюсь, мы уложились, судя по таймеру, да, миграции в коре обсудили, параметры маршрутов в спин-энд-коре пошифровали, металаму как замена постшарпа обсудили, как писать код, чтобы было удобно и стильно, так скажем, в едином стиле тоже обсудили, подумали, может ли Aspire быть новым Nuget в каком-то смысле для клауда, ну и вендинг фреймворка не будет выделять на дотнете, может хорошо, может плохо, посмотрим. -6474.16 6476.36 SPEAKER_01 Ну или в каком-то обрезанном виде, может быть. -6476.36 6486.56 SPEAKER_00 Ну может что успеют придумать, но я думаю, что если они сказали, что типа нет, будет у нас open design процесс, я думаю, что этот open design процесс займет там месяцы, вряд ли они что-то успеют сделать, лишь бы. -6486.56 6488.20 SPEAKER_01 Ну ладно, зато нам будет много новостей. -6488.20 6489.96 SPEAKER_00 Лишь бы что-нибудь сделали, да. -6489.96 6495.44 SPEAKER_00 Ну чё, на этом всё, 96 выпуск заканчивается, всем спасибо. -6495.44 6506.06 SPEAKER_01 Всем счастливо, всем пока, заставляйте комментарии, рассказывайте друзьям, если вы хотите, чтоб в вашей чатике бросали ссылки на Aspire Dashboard, то добавляйтесь к нам на Boosty, там много всего интересного. -6506.06 6507.06 SPEAKER_01 До новых встреч, пока! -6507.06 6507.56 SPEAKER_00 Пока. -6507.56 6508.06 SPEAKER_00 Пока. -6508.06 6522.06 UNKNOWN [музыка] +0.00 16.42 "Анатолий Кулаков" Здравствуйте, уважаемые слушатели, в эфире Радио.нет и выпуск номер 96, и в студии постоянный ведущий Анатолий Кулаков. +16.42 17.42 "Игорь Лабутин" И Игорь Лабутин. +17.42 18.42 "Игорь Лабутин" Всем привет. +18.42 37.10 "Анатолий Кулаков" А за нашей студией наши помогаторы, а именно Александр, Сергей, Владислав, Шевченко Антон, Гурий Самарин, Лазарев Илья, Виктор, Руслан Артамонов, Александр Ерыгин, Сергей Бензенко, Александр Лапердин, Ольга Бондаренко, Дмитрий Сорокин, Сергей Краснов, Константин Ушаков, Андреев Азлеев и Бальсим Альджавахири. +37.10 42.18 "Анатолий Кулаков" Спасибо всем, кто нас поддерживает, а также шарит, репостает и комментирует. +42.18 50.02 "Анатолий Кулаков" Поэтому, если вдруг вы никогда не заходили к нам на YouTube, приходите, там у нас разворачиваются интересные дискуссии, некоторые даже полезные. +50.02 59.54 "Анатолий Кулаков" В общем, часто повторяю, поправляют нас и доносят какую-то дополнительную информацию, поэтому как дополнение к выпуску вполне хороший источник. +59.54 62.38 "Игорь Лабутин" Ну, давай на самом деле начинать потихонечку. +62.38 68.82 "Игорь Лабутин" Новостей от Майкрософта у нас особо нету, ничего такого не вышло, превью пока не вышло. +68.82 74.74 "Игорь Лабутин" Скорее всего оно, конечно же, выйдет на следующий день после записи подкаста, но тут уж ничего не поделаешь, придётся ждать следующего выпуска. +74.74 76.78 "Игорь Лабутин" А пока давай пойдём в статьи. +76.78 78.94 "Анатолий Кулаков" Зато мы можем посвятить выпуск статейчикам. +78.94 79.94 "Анатолий Кулаков" Да. +79.94 92.98 "Анатолий Кулаков" Не каждый раз, когда у нас много новостей, мы доходим до каких-то полезных статей, а тут вот вытащили пачку того, что вам может быть полезно в повседневной жизни, и что как раз-таки не зависит от времени, поэтому этот выпуск можно будет прислушивать вечно, и пойдём по статейчикам. +92.98 97.74 "Игорь Лабутин" Ну, может быть, не совсем вечно, но действительно полезные статьи у нас попались. +97.74 101.86 "Игорь Лабутин" И первая статья про EF Core и про миграции. +101.86 121.26 "Игорь Лабутин" Мы довольно много говорим про EF Core, точнее, не то чтобы много на самом деле, потому что в релиз ноутсов дотнета обычно EF Core уделяется довольно мало времени, там довольно куции какие-то, одна-две-три фичи описывается, остальное говорите, идите смотрите changelog, и поэтому довольно подробно мы про него практически никогда и не говорим. +121.26 123.18 "Анатолий Кулаков" Мы же не пойдём смотреть changelog? +123.18 134.54 "Игорь Лабутин" Нет, мы не пойдём смотреть changelog, мы пойдём смотреть статью, которая довольно неплохо, обзорно описывает то, что можно и как можно работать с миграциями в EF Core. +134.54 139.42 "Игорь Лабутин" И давайте для начала просто сообразим и вспомним вообще, что это такое миграция и зачем нам оно надо. +139.42 182.86 "Игорь Лабутин" То есть понятно, что EF Core, там ORM составляет запросы, всё такое прочее, значит, облегчает маппинг ваших результатов запросов обратно в объекты, это всё здорово и полезно, но только в тот момент, когда у вас уже есть база данных, или даже когда она у вас уже есть, вам её иногда нужно менять, и можно это, конечно, делать как-то отдельно, можно руками, можно даже отдельно прям без каких-либо скриптов менять прям впроди на живую схему базы данных, в принципе, такое делали раньше, когда-то давным-давно, наверное, но это всё очень понятно ведёт к ошибкам, ведёт к тому, что у вас будут разные схемы баз данных там-сям, требует времени, в общем, дико неудобно, поэтому нужно автоматизировать. +182.86 187.98 "Игорь Лабутин" Автоматизируется это всё обычно с помощью концепции, которая называется миграцией. +187.98 204.26 "Игорь Лабутин" Это довольно общая концепция, не то чтобы она связана как-то с EF Core конкретно, то есть это просто некоторый способ записать то, как вам нужно изменить базу данных в виде некоторых скриптов, тем или иным способом. +204.26 252.94 "Игорь Лабутин" Есть способы, когда вы описываете то, что вы хотите получить конечный результат, дальше некоторый тул волшебным образом пытается подумать, как же привести вашу базу данных именно в такое состояние, но, к сожалению, в большинстве случаев миграции так просто без некоторого программистского раздумья автоматически изгенерить не очень получится, потому что данные, которые хранятся в базе, как правило, довольно ценные и случайно, неправильно собранные, неправильно автоматически изгенеренные миграции всё испортить не очень здорово, поэтому, как правило, всё-таки они пишутся плюс-минус руками, ну так, полуавтогенерация, сейчас про это немножко расскажу, но обязательно требуют какого-то ревью и после этого можно их уже коммитить и использовать в плюс-минус автоматизированных скриптах во время раскатки вашего приложения. +252.94 271.26 "Игорь Лабутин" Причём здесь Евкор, Евкор здесь при том, что Евкор предоставляет свою собственную, так сказать, модель миграции, то, как вы можете описать то, что вы хотите изменить в вашей базе данных, при том, что большинство вещей можно писать на плюс-минус понятном и знакомом C#. +271.26 327.44 "Игорь Лабутин" Понятно, что могут быть случаи, когда вам C# не хватит и придётся возвращаться уже к SQL, но в целом большинство вещей, не требующих каких-то суперхитрых тюнингов базы данных, справятся с обычным C#, что даёт дополнительное преимущество, что эта миграция может быть применима вообще к любой базе данных, которая поддерживается, понятное дело, Евкором, что, наверное, не то чтобы сильно полезно для продуктов, которые вы ставите куда-то на сервера, но может быть полезно, если вы это делаете в каком-нибудь коробочном продукте, который ставится в какую-нибудь организацию, например, просто так и который в таком случае в качестве полезной фичи может иметь свойство работать на, не знаю, Oracle, SQL Server, PostgreSQL, MySQL, в общем, подставьте сюда любую более-менее плюс-минус поддерживаемую базу данных, которая, например, уже есть в компании, гораздо приятнее. +327.44 348.56 "Игорь Лабутин" В целом, по Евкору есть довольно неплохая документация от самих Microsoft, она вся очень хорошая и понятная, но в статье дается, так скажем, необходимый минимум для понимания того, что со всем этим делать, как с этим обращаться, и поэтому мы по ней пробежимся. +348.56 351.20 "Игорь Лабутин" Для начала надо понять, как эти миграции создавать. +351.20 367.42 "Игорь Лабутин" Значит, если вы работаете с Евкором, у вас уже наверняка есть db.context, у вас есть наверняка какие-то entities, через которые вы общаетесь с базой данных, и для того, чтобы создать вашу первую миграцию, можно сделать одну простую штуку. +367.42 372.98 "Игорь Лабутин" Нужно позвать некоторую command line тулзу, которая вам создает эту самую миграцию. +372.98 383.88 "Игорь Лабутин" Способов позвать эту тулзу, на самом деле, несколько, можно использовать .NET Global Tool, там, соответственно, .NET EF и дальше, все, что связано с миграциями, либо есть PowerShell. +383.88 391.00 "Игорь Лабутин" Статья использует PowerShell, команды в PowerShell, это, соответственно, это addMigration, и дальше название вашей миграции. +391.00 410.92 "Игорь Лабутин" Как правило, первая миграция называется createDb, потому что первое, что она сделает, она, имея на руках ваше определение entities, то есть всех, по сути, табличек, колонок и там, связи между ними, с которыми работает именно ваше приложение, она создаст некоторый кусочек кода. +410.92 414.16 "Игорь Лабутин" На самом деле, она создает класс, который наследуется от класса migration. +414.16 417.24 "Игорь Лабутин" В этом классе есть два метода, up и down. +417.24 427.80 "Игорь Лабутин" Up — это, соответственно, когда вы будете применять эту миграцию для того, чтобы смигрировать базу данных из старой версии в новую, down, соответственно, наоборот, если вам нужно домигрейтить базу обратно. +427.80 445.36 "Игорь Лабутин" И в этих методах, up и down, она сгенерит некоторое тело методов, которые будут, по сути, создавать базу данных необходимую и достаточную для того, чтобы ваше entity, ваше приложение, которое работает с теми entities, обязательно в DB-контексте, могло работать. +445.36 454.84 "Игорь Лабутин" Понятное дело, что, возможно, там нужны какие-то дополнительные индексы, возможно, вам нужны какие-то дополнительные хранимые процедуры, view, функции, ну, все, что угодно нестандартное. +454.84 462.84 "Игорь Лабутин" Такие штуки придется добавлять руками, но базовый набор там таблицы и колонок она создаст и связи между ними. +462.84 488.76 "Игорь Лабутин" Дальше это все, конечно, хорошо и здорово, таким образом, вы можете создать первую миграцию, как правило, первая миграция более-менее адекватна, вот, исключением всяких специальных SQL вещей, либо каких-то кастомизаций, которые вы знаете, что вы будете запускаться только на Postgres, и вы хотите сразу кастомизировать создание базы именно под Postgres, дополнив его какими-то специфическими позгоревыми штуками. +488.76 492.68 "Игорь Лабутин" Но дальше нужно эту миграцию кастомизить, как правило. +492.68 512.32 "Игорь Лабутин" Вы точно так же можете говорить add migration, даже когда у вас уже есть другие миграции, и в этот момент, на самом деле, EF Core будет поднимать некоторый временный контекст базы данных, смотреть, что у вас есть сейчас в вашей базе данных, которую вы укажете connection строкой, и сравнивать это с тем, что есть в модели данных, которую вы написали в коде. +512.32 534.52 "Игорь Лабутин" То есть вы в коде дописываете, допустим, новое поле в какой-нибудь entity, говорите EF, там, migration, add, и имя новой миграции, и после чего EF Core сравнит базу данных с новым набором классов entity и добавит или что-то изменит в вашей схеме базы данных, добавит код, который будет изменять схему базы данных. +534.52 535.52 "Игорь Лабутин" В чем проблема? +535.52 538.84 "Игорь Лабутин" Проблема в том, что этот код может быть довольно наивен. +538.84 548.28 "Игорь Лабутин" То есть одно время, я не помню, сейчас поменялся это или нет, по-моему, это все-таки пофиксили, но одно время, если, например, вы переименовываете колонку в базе данных, EF Core генерил довольно простую штуку. +548.28 550.92 "Игорь Лабутин" Он сначала дробил колонку, потом добавлял колонку с новым именем. +550.92 563.52 "Игорь Лабутин" Формально миграция верная, фактически миграция ведет к потере данных, поэтому понятно, что, как правило, вы это меняли на явный вызов функции renameColumn, которая делает это без потери данных. +563.52 581.28 "Игорь Лабутин" Особенно, когда мы говорим про down-миграцию, т.е. когда мы говорим, что нам нужно что-нибудь откатить обратно, если вы в миграции drop-аете колонку, которая по какой-то причине вам стала не нужна, то понятно, что в down-миграции вы уже никакую колонку ниоткуда не восстановите. +581.28 594.72 "Игорь Лабутин" И некоторые миграции однонаправленные, либо некоторые миграции нужно смотреть, как делать, если вам действительно нужно уметь откатиться, колонку, не знаю, переименовывать во что. +594.72 607.68 "Игорь Лабутин" Я даже не знаю, я обычно исповедую подход, что down-миграции никогда не надо, всегда движемся только в сторону up, потому что на моей практике как-то редко были случаи, когда нужны были именно down-миграции. +607.68 610.20 "Анатолий Кулаков" Ну действительно, они пригождаются практически никогда. +610.20 621.04 "Игорь Лабутин" И мне кажется, что как только они потребуются, это будет как раз тот случай, где типа drop-колонка был, и down-миграция тебе ничего не даст, всё равно восстановить колонку не получится. +621.04 622.04 "Игорь Лабутин" Да-да. +622.04 642.00 "Игорь Лабутин" Для того, чтобы кастомизировать, там есть довольно шикарный набор fluent API, т.е. вы пишете NaVi, Sharpie, но если вам нужен прям кастомный SQL, то там есть метод под названием SQL, незамысловато названый, куда передаётесь просто строчку с SQL, куда можно записать любой кастомный SQL, который вы хотите. +642.00 649.64 "Игорь Лабутин" Ну допустим, вы создали миграцию, вы написали набор миграции, теперь в вашем приложении есть пачка миграций. +649.64 665.20 "Игорь Лабутин" Это некоторый набор C# файликов или возможно рядом лежащих там SQL скриптов, которых вы заполняете внутри вот этого SQL метода, и надо, собственно, понять, а как применять-то, что со всем этим делать, как же это применять. +665.20 675.64 "Игорь Лабутин" Ну, первый способ, он такой довольно прямой, в лоб, я его практически не видел, чтобы он когда-либо использовался, но он есть. +675.64 684.76 "Игорь Лабутин" Можно сделать это, давайте не так, давайте прежде чем говорить, как это можно сделать, поговорим, когда это нужно делать, потому что может быть это более важно. +684.76 701.80 "Игорь Лабутин" Вот у нас есть наше приложение, вы как-то поменяли код, чтобы оно работало с, требовало каких-то новых фич от базы данных, у вас даже в коде есть миграция, которая говорит о том, как же это нужно сделать, чтобы привести базу в новое состояние, но вопрос, когда же это делать. +701.80 717.72 "Игорь Лабутин" Есть несколько вариантов, вариант, точнее как, вариант такой, что ваш код, скорее всего, в любом случае ждет так или иначе каких-то новых фич от базы данных, иначе зачем миграция, если код работает все еще со старой версией. +717.72 720.64 "Игорь Лабутин" Могут быть случаи, когда это нужно, но это большая редкость. +720.64 730.88 "Игорь Лабутин" Например, добавление индекса, в принципе его можно делать как угодно, от этого работа кода с точки зрения корректности не пострадает, возможно скорость где-то улучшится или ухудшится. +730.88 743.96 "Игорь Лабутин" Но предположим, что у нас есть изменения, которые требуют такое, так что нам нужно, чтобы новый код работал с новой схемой базы данных, желательно тогда миграцию провести перед тем, как приложение стартует. +743.96 770.96 "Игорь Лабутин" Это все понятно, но у нас в нашем современном мире кубернетес и прочих горизонтально масштабируемых сервисов есть проблема с тем, что довольно многие используют так называемый rolling upgrade, то есть когда вы кубернетесу говорите вот новая версия нашего контейнера, давай мы его раскатим аккуратненько, и кубернетес по очереди накатывает один код, выключает один из старых, накатывает еще один новый, выключает один из старых. +770.96 780.72 "Игорь Лабутин" То есть у нас есть некоторое время, когда у вас с одной стороны работает старый код, с другой стороны работает новый код, и при всем при этом миграция уже должна быть как бы проведена. +780.72 782.96 "Игорь Лабутин" Отсюда следует несколько важных выводов. +782.96 787.28 "Игорь Лабутин" Во-первых, которые не совсем связаны прямо с EFCore, они применимы к любым миграциям. +787.28 798.44 "Игорь Лабутин" Когда вы пишете ваши миграции, делайте так, чтобы эти миграции не нарушали работу старого кода, то есть желательно старый код, чтобы продолжала работа, добавляйте новую колонку обязательно с каким-нибудь там дефолтным значением. +798.44 808.96 "Игорь Лабутин" Добавляйте и там, и nullable она должна быть, добавляйте, или там убирайте колонку, нельзя убирать колонку до тех пор, пока старый код ее хоть как-то использует. +808.96 819.52 "Игорь Лабутин" Даже если вам очень хочется и вы знаете, что в новом коде она вам больше не нужна, придется потерпеть, сначала раскатить новый элис, который не использует колонку и уже в следующей миграции, в следующем апгрейде удалить колонку. +819.52 822.84 "Игорь Лабутин" Ну вот такие случаи, в общем, надо понимать и надо отслеживать. +822.84 839.32 "Игорь Лабутин" Тот факт, что обе версии кода могут работать, но фактически это означает, что миграция будет выполняться по сути параллельно с работающим кодом, то есть у нас работают старые коды, например, если мы в кубере, нам нужно накатить миграцию, пока они работают, а потом раскатывать нужную версию. +839.32 850.80 "Анатолий Кулаков" Это очень похоже, например, если мы задумывались, когда мы обсуждали версионирование в API, мы тоже там советовали не делать breaking changes, не убирать те поля, которые могут юзаться каким-то внешним системами. +850.80 854.36 "Анатолий Кулаков" А здесь вы 100% знаете, что ваше поле юзается какой-то системой. +854.36 860.60 "Анатолий Кулаков" И в принципе вот все те же правила по постепенной миграции, про избегание breaking changes и так далее, они сюда очень хорошо ложатся. +860.60 876.68 "Игорь Лабутин" Все так, все так, но на самом деле при апгрейдах баз данных очень рекомендую иногда поспрашивать о ваших DBA, не настроили ли они какую-нибудь там репликацию в какое-нибудь DWH-хранилище вашей схемы, потому что выяснится, что вы проапгрейдите схему, у них сломается репликация. +876.68 915.12 "Игорь Лабутин" Я встречал такое как-то в одном из проектов, что как-то нужно было замутить какие-то отчетики, но те, кому нужно было, они сказали, ну есть BD, давайте админ, и вы нам это, реплицируйте просто в наше хранилище, все нормально, мы по ним сами сколько будем строить, не нагружая основную базу, ну хорошо же, хорошо, репликация ресурсов особо не жрет, ну как бы, по крайней мере не тормозит основную BD, она может запаздывать, если ресурсов не хватает, но в целом как бы основную работу приложения не тормозит, все хорошо, но мы поменяли схему и сломали отчеты, такое бывает, знайте кто вами пользуется, это тоже в каком-то смысле API может быть, хоть и не очень удобный. +915.12 938.28 "Игорь Лабутин" Ну вот, возвращаясь к тому, когда же запускать, есть простой способ, который вы увидите, наверное, во всех примерчиках простых на EFCore, можно в самом начале вашего приложения, до того как-то вы там начали слушать ваши контроллеры, сказать, дорогой, значит, EFCore, сделай так, чтобы мы убедились, что база данных на месте. +938.28 1031.32 "Игорь Лабутин" Мигрейт, что-то там, migrate_db_async, по-моему, называется, не помню, я особо не пользуюсь этим методом, поэтому точное название не помню, но в общем есть там такой метод, функция, который просто приведет в состояние, что точная база данных на месте, но вспоминаем наш предыдущий пойнт про то, что, во-первых, у вас может быть несколько инстансов приложения, и если вы в Кубере такое запустите, то каждый из подов, допустим, у вас довольно большие лимиты на тему масштабирования, и тогда в момент роллинга апгрейдов, Кубернет сможет, на самом деле, по нескольку подов за раз новые версии закидывать в запускаемые, и в таком случае все они побегут обновлять базу данных, конечно же, все эти миграции, ну, как бы, там есть вариант, как сделать такую глобальную блокировку на уровне всех миграций, чтобы только один под смог что-то обновить, но дальше возникнет вопрос, что пока он обновляет, все остальные тупо ждут, у позгрессов, у Кубернетеса есть некоторые лимиты на тайм-аут, на поднятие подов, ну, в общем, там могут возникнуть всякие разные проблемы, а миграции бывают долгие, надо сказать, очень долгие, особенно если вы там перелопачиваете всю табличку, то не знаю, индексы какие-нибудь навешиваете, это может быть очень долго, поэтому не очень хороший способ, кроме того, миграция может упасть, и тогда у вас как-то вроде это, приложение непонятно, то ли стартовать, то ли не стартовать, если не стартовать, то у вас под свалится, Кубернетес его снова попробует поднять, он снова попробует смигревать, что он там натворил в бд, ну, не очень понятно, вот. +1031.32 1050.16 "Игорь Лабутин" При этом такая опция очень удобна для локальной разработки, то есть вот поставить эту штуку под условия их окружения, их environment, development, в принципе, удобно, тогда вы сразу получаете каждый раз обновленную бдшку, если вы миграциями свою локальную бдшку обновляете, ну, что, в принципе, тоже рекомендуется. +1050.16 1051.16 "Игорь Лабутин" Вот, это один вариант. +1051.16 1071.00 "Игорь Лабутин" Второй вариант — это некоторый deployment script, ну, то есть у вас наверняка есть некоторая автоматическая CD-система, которая так или иначе разворачивает ваше приложение, это может быть просто какой-нибудь bash скриптик или не баш, на чем-нибудь написано, парашейль скриптик, там, это может быть Octopus, это может быть кто угодно другой, который разворачивает ваше приложение. +1071.00 1079.60 "Игорь Лабутин" Можно туда, до того, как вы попросили, не знаю, кубер или еще что-то, развернуть ваше приложение, впилить, соответственно, запуск некоторого deployment скрипта. +1079.60 1093.64 "Игорь Лабутин" Это, в принципе, неплохой вариант, мы им пользовались довольно долго в случае, когда вы живете не в Кубернетесе, а именно просто разворачиваете ваше, не знаю, приложение в одном единственном экземпляре ваш большой монолит. +1093.64 1103.20 "Игорь Лабутин" Вполне нормальный вариант, если что-то в базе данных не смогло прогрейдиться, ну, ваш deployment упадет, дальше приложение не пойдет разворачиваться, все нормально, пойдете фиксить. +1103.20 1109.28 "Игорь Лабутин" Риск в том, что если апгрейд упал в базе данных, то база данных может быть в каком-нибудь странном состоянии, так он и всегда есть. +1109.28 1120.32 "Игорь Лабутин" От этого риска, к сожалению, мне кажется, никак особо не избавится, кроме как предварительного тестирования на каком-нибудь хорошем бэкапе, который у вас есть, для рисковых и длинных апгрейдов. +1120.32 1139.00 "Игорь Лабутин" И последний вариант, если вы живете в Кубернетесе, то тогда есть, точнее, предпоследний вариант, если вы живете в Кубернетесе, то тогда у вас есть вариант сделать отдельный так называемый init-контейнер и применить еще некоторые штуки под названием jobs. +1139.00 1155.52 "Игорь Лабутин" Я сейчас проверю, нет, у меня нет ссылки, я потом повешу ссылочку еще, добавлю в шоу-ноуты, ссылочку на статьи Koindrelog, мы ее не рассматривали подробно, потому что она все-таки не совсем по профилю нашего подкаста, она там продолжает немножко, но в основном про диплоймент. +1155.52 1199.60 "Игорь Лабутин" Там есть хорошая статья, как как раз-таки диплоить Asp.core-приложение с миграциями в Кумбер с использованием jobs и init-контейнеров, то есть jobs — это некоторая сущность, коллекция подов, которая просто исполняется от начала и до конца, но, возможно, с ретраями, и дальше нужно просто сделать так, чтобы ваша миграция выполнялась как java, а каждый контейнер с помощью концепции называемой init-контейнера ждал, пока эта java закончится, и тогда у вас приложение будет спокойно ждать, это не входит во всякие вот эти вот стартовые пробы Кумбера, соответственно, оно спокойно дождется, пока java-миграция закончится, в единственном экземпляре она одна будет, и все контейнеры, которые ее ждут, спокойно запустятся. +1199.60 1204.24 "Игорь Лабутин" Вот, прекрасная штука, хорошо работает в окружении, когда у вас Кумбер. +1204.24 1226.12 "Игорь Лабутин" Вот, и есть еще один способ, он, в принципе, немножко пересекается с дипломинскриптом, потому что в дипломинскрипте вам как-то что-то надо сделать все-таки, вот, то давайте теперь поймем, а как вот нам в дипломинскрипте надо что-то запустить, давайте теперь мы плюс-минус выяснили, когда нужно запускать, точнее, какие у нас есть варианты, теперь давайте поймем как. +1226.12 1234.20 "Игорь Лабутин" Ну, в случае со стартапом, я уже сказал, там все просто, вызываем код и db.context.database.migrate, и все нормально, это работает. +1234.20 1237.76 "Игорь Лабутин" В остальных же случаях надо понять, что можно делать. +1237.76 1263.96 "Игорь Лабутин" Первый случай можно сделать через sql script, у вас есть некоторая либо PowerShell, либо опять же через .NET EF Tool команда, называется, если в PowerShell варианте, script.migrate, script.migration, в которой указывается, от какой миграции и до какой нужно сгенерить скрипт, можно не указывать миграции, а, главное, сгенерить скрипт вообще на все, такое с нуля до последнего состояния, ну, в общем, интервал указывайте. +1263.96 1269.28 "Игорь Лабутин" И он генерирует sql script, который соответствует ровно тем миграциям, которые вы выбрали. +1269.28 1282.00 "Игорь Лабутин" Проблема в том, что по дефолту он генерирует не идемпотентный скрипт, то есть если в скрипте написано create table, в смысле, что он понимает, что нужно создать табличку, в скрипте так и будет написано create table, без всяких условий, без всего. +1282.00 1304.44 "Игорь Лабутин" Это не очень здорово, потому что могут быть ситуации, когда этот скрипт будет накатываться, пытаться накатываться несколько раз из-за каких-то переповторов, лучше всегда передавать ключик idempotent, тогда он каждую миграцию будет оборачивать в некоторые условия, проверить, то есть он понимает, что если нужно создать табличку, то он делает, если табличка не создана, если добавить колонку, он будет проверять, что колонка не добавлена. +1304.44 1316.56 "Игорь Лабутин" Я, кстати, не знаю, какие условия он вставляет, если там вставки просто .sql, вот этого я что-то не помню, по-моему, он ничего не делает и тупо их выполняет, это ответственность разработчика, сделать так, чтобы эти вставки были идемпотентными. +1316.56 1329.60 "Игорь Лабутин" То есть вы того, вы можете просто генерить .sql скрипт, например, в билдтайме, положить его вместе с артефактами вашего приложения и в диплоймент скрипте его выполнить, это один вариант. +1329.60 1357.92 "Игорь Лабутин" Второй вариант можно, если у вас есть исходники вашего приложения, можно просто сказать dotnet.ef.update_database, по-моему, либо PowerShell.update_database вызвать, указать туда, до какой миграции нужно докатить, указать connection string и .net.ef.tool поднимет кусочек вашего приложения, поднимет db.context, поднимет connection string и накатит все эти миграции как нужно. +1357.92 1362.12 "Игорь Лабутин" Это способ, если у вас исходнички рядом. +1362.12 1371.68 "Игорь Лабутин" Ну и последний вариант, который как раз таки максимально подходит для варианта с кубером, ну впрочем для диплоймента скрипта он тоже подходит, это называется migration_bundles. +1371.68 1396.96 "Игорь Лабутин" Это, по сути, некоторое исполнимое приложение, которое вы создаете с помощью команды bundle_migration или dotnet.ef.bundle, оно полностью self-contained, то есть оно не требует никаких исходников, ничего-ничего-ничего, то есть это просто полностью готовое приложение, которое единственное, что нужно передать connection string и оно накатит тот набор миграций, который вы выбрали, на заданную bd с заданным connection string. +1396.96 1406.32 "Игорь Лабутин" Вот такой бандл уже можно упаковать в контейнер, можно упаковать тоже как артефакт вашего сборки, чтобы отдать его диплоймент скрипту и он уже накатит. +1406.32 1415.40 "Игорь Лабутин" Вроде как Microsoft считает, что это чуть ли не самый лучший вариант сейчас, не знаю из каких соображений, но вот я из того, что видел, они довольно активно его именно продвигали. +1415.40 1428.72 "Игорь Лабутин" Ну понятно, что как бы от простого command line отличается тем, что не нужно тащить исходники все, от SQL скрипта не знаю чем отличается, возможно каким-то более расширенным логированием или еще чем-то, вот. +1428.72 1438.68 "Игорь Лабутин" Ну а из кода db.context.db.is_migrate я подозреваю, что бандл делает ровно то же самое, но просто в более контролируемом и self-contained окружении. +1438.68 1444.48 "Игорь Лабутин" Вот примерно такая штука с миграциями EF Cora. +1444.48 1450.80 "Игорь Лабутин" Признаться, мы только на одном проекте использовали миграции EF Cora, в основном я пользовался другими тулами для миграций. +1450.80 1455.76 "Игорь Лабутин" Я не знаю, Только есть что добавить именно про EF миграции? +1455.76 1458.88 "Анатолий Кулаков" Наверное нет, кроме того, что мы везде используем EF миграции. +1458.88 1462.44 "Анатолий Кулаков" Почему-то на другие тулзы и не осмотрели, наверняка пока хватало. +1462.44 1464.00 "Анатолий Кулаков" Что тебя на них натолкнуло? +1464.00 1473.48 "Игорь Лабутин" Я не помню, что нас натолкнуло, вот EF миграции мы использовали в проекте, в котором мы с нуля все это делали, в остальных, видимо, оно уже просто было и поэтому просто не переделывали. +1473.48 1475.48 "Игорь Лабутин" Значит, что есть из других тулов? +1475.48 1484.56 "Игорь Лабутин" С двумя тулами я встречался, один это Fluent Migrator, это даже не тул, они это гордо называют Migration Framework. +1484.56 1500.88 "Игорь Лабутин" По сути, там подход похожий на Entity Framework, то есть там тоже для миграции задаются классы, они наследуются от некоторого специального базового класса, там их несколько вариантов есть, для двухсторонних миграций как раз таки, ну с Up и Down есть односторонние, какие-то вариантики есть. +1500.88 1506.80 "Игорь Лабутин" И есть еще отдельный раннер, то есть это некоторый тоже класс, который позволяет эти все миграции заранить. +1506.80 1516.84 "Игорь Лабутин" Вы можете этот класс использовать внутри вашего приложения, либо классический подход это написать отдельную маленькую консольную тулзу, которая возьмет этот раннер и, соответственно, применит все миграции. +1516.84 1522.88 "Игорь Лабутин" То есть это просто набор некоторых Nuget пакетов, которые вы используете для того, чтобы накатить изменения на вашу базу. +1522.88 1533.28 "Игорь Лабутин" Максимально похожий на EFCore, просто другой, написан полностью на C#, в общем, если надо, можно смотреть, как он устроен внутри, он сушит на GitHub вот это все. +1533.28 1537.76 "Игорь Лабутин" Его мы использовали, никаких, в общем, нареканий к нему не было вообще, все прекрасно работало. +1537.76 1542.88 "Игорь Лабутин" Так же, собственно, и к EFCore у меня тоже особых нареканий в общем-то не было, тоже работало. +1542.88 1565.64 "Игорь Лабутин" Есть еще небольшая библиотечка на дотнете, это dbUp, она, по сути, предназначена просто для применения SQL скриптов, то есть если вы не хотите писать SQL скрипты или по какой-то причине не пишете апгрейд скрипты миграции на C#, а хотите их писать на SQL, то, может быть, вам и не нужна вся вот эта вот мощь и умения EFCore либо Fluent Migrator. +1565.64 1576.00 "Игорь Лабутин" Возможно, вам будет достаточно dbUp, это просто некая библиотечка, которая отдается набор из SQL скриптов и говорится, вот мне, пожалуйста, от C# до C# примени, ну и она их применяет. +1576.00 1586.68 "Игорь Лабутин" С треками, что там применено, что не применено, ну, понятно, все как положено для нормального мигратора, но вот тоже на GitHub, тоже open-source, тоже на дотнете, можно посмотреть. +1586.68 1603.92 "Игорь Лабутин" Дальше есть тул, которым я не пользовался, называется Grate, Grate как решетка, в смысле, G-R-A-T-E, он тупо выполняет SQL скрипты из папочки, грубо говоря, как я понял по описанию, возможно, тоже кому-то пригодится. +1603.92 1606.92 "Игорь Лабутин" В общем, похож на dbUp, но dbUp — это библиотечка, это тул. +1606.92 1607.92 "Игорь Лабутин" Вот. +1607.92 1638.52 "Игорь Лабутин" Ну и еще в одном проекте, несмотря на то, что он был дотнет, но и у нас использовался Liquibase, Liquibase и Flyway — это тулы, наверное, более известные в мире Java, потому что они написаны на Java, Liquibase точно, Flyway, по-моему, тоже, вот, но они в этом смысле максимально агностик для языка, в смысле, вы не можете написать на C#, конечно, миграции для них, но они там пишутся либо в SQL, либо условно в XML, и поэтому абсолютно все равно, просто, ну, вам нужна Java, да, для того, чтобы запускать эти самые миграции. +1638.52 1645.44 "Игорь Лабутин" Был у нас проект, где вот они тоже почему-то, видимо, исторически использовались, ну, в принципе, тоже работали прекрасно. +1645.44 1646.44 "Игорь Лабутин" Вот. +1646.44 1669.16 "Игорь Лабутин" Вот такой вот у нас сейчас обзор получился разных всяких миграций, то есть если вам хватает EF-корных миграций, просто берете и пользуйтесь, если не хватает, посмотрите в сторону Fluent Migrator, возможно, там что-то будет чуть поудобнее сделано, или вам будет чуть по, не знаю, там можно получше покастомизировать, какие миграции накатывать, какие нет. +1669.16 1681.56 "Игорь Лабутин" Во Fluent Migrator там была, вот я помню, мы даже пользовались одно время, развесистая система тегов, то есть можно миграции тегать, и типа, не знаю, там разным заказчикам, например, в разных окружениях накатывать разные кусочки. +1681.56 1691.76 "Игорь Лабутин" У нас таким образом не были миграции, которые были помечали, типа, такие сид данные для автотестов, и вот они накатывались только при указании спецтега, при накатке схемы. +1691.76 1697.40 "Анатолий Кулаков" Ну удобно, да, действительно, когда у тебя такие какие-то сложные процессы, сложные миграции. +1697.40 1710.64 "Игорь Лабутин" То есть вот он этим, мне кажется, наиболее мощный в каком-то смысле, то есть EF, по-моему, такого, наверняка на EF тоже можно такое написать, понятное дело, да, никто не мешает функции up писать все, что вы хотите, но это все-таки сложнее. +1710.64 1711.64 "Игорь Лабутин" Такая альтернативная поддержка. +1711.64 1721.04 "Игорь Лабутин" Ну и остальные они такие попроще, тулы, ну, dbup и graded чисто для SQL скриптов, но, может быть, вам этого тоже будет достаточно. +1721.04 1722.04 "Анатолий Кулаков" Такие дела. +1722.04 1730.76 "Анатолий Кулаков" Ну в Quantity Framework раньше миграции были довольно убогие, то есть мне кажется, вот с тех пор, когда они перелезли там на core и более или менее стабилизировались, то там миграции стали довольно хорошие. +1730.76 1743.04 "Анатолий Кулаков" Ну и опять же, вспоминая, не знаю, мои старые проекты, где мы все миграции писали чисто на SQL скриптах, которые по порядочку складывали в папочки, я до сих пор такого, ну, такого удовольствия от написания миграции не получаю. +1743.04 1748.96 "Анатолий Кулаков" То есть надо признаться, что миграции EF, это все равно там на 80% какая-то дикая магия. +1748.96 1761.04 "Анатолий Кулаков" Если ты раньше мог бы зайти в эти SQL скрипты и посмотреть их и проанализировать каким-то образом или даже сделать им downgrade, если ты захотел бы назад что-то вернуть, вот там все это как-то было возможно. +1761.04 1774.60 "Анатолий Кулаков" В общем-то сейчас EF скрипты, если вы захотите посмотреть, что он там генерирует, какие там вещи делает, иногда волосы там становятся, что, как он эти миграции прокручивает. +1774.60 1780.76 "Анатолий Кулаков" Они все, конечно, работают, все, конечно, хорошо, но это не для того, чтобы пользователь на них смотрел, не для того, чтобы им как-то ручками управлять. +1780.76 1785.04 "Анатолий Кулаков" И это мне, конечно, всегда не очень нравится в EF миграциях. +1785.04 1798.12 "Игорь Лабутин" Да, именно для этого, я так понимаю, была создана в том числе вот эта вот команда script-migrate, чтобы можно было заскриптовать то, что он будет делать в нормальной понятной SQL, например, отдать DBA им, чтобы они посмотрели и хоть, ну, так сказать, одобрили. +1798.12 1803.48 "Анатолий Кулаков" Там тоже ее нельзя назвать, что она прям хорошая, читабельная. +1803.48 1810.00 "Анатолий Кулаков" Точно так же, как и C#-код, который у тебя генерирует стандартный генератор, они не для того, чтобы их люди читали. +1810.00 1815.08 "Игорь Лабутин" Ну, он хотя бы на SQL, где уже точно понятно, что будет исполняться. +1815.08 1817.12 "Игорь Лабутин" То есть тут как бы уже хоть что-то. +1817.12 1822.48 "Анатолий Кулаков" Опять же, все равно такое удовольствие, как написание мануальных скриптов, вы не получите ни в одного из этих лоз. +1822.48 1827.62 "Анатолий Кулаков" Опять же, не будете писать, как в DBA, например, просто скриптики. +1827.62 1828.62 "Игорь Лабутин" Ну да, да. +1828.62 1830.56 "Игорь Лабутин" Ну, в общем, такие дела. +1830.56 1831.56 "Игорь Лабутин" Давай дальше. +1831.56 1834.16 "Анатолий Кулаков" Ну, отлично, в принципе, хорошая темка. +1834.16 1837.34 "Анатолий Кулаков" Миграции, я думаю, нужны и всем важны. +1837.34 1838.34 "Анатолий Кулаков" Пойдем дальше. +1838.34 1843.68 "Анатолий Кулаков" Что еще, интересно, всем нужно и всем важно, но никто это не осознает, это шифровать ваши урлы. +1843.68 1847.64 "Анатолий Кулаков" Вот, мы, конечно же, о таком не задумывались, а вот давайте теперь задумаемся. +1847.96 1853.72 "Анатолий Кулаков" Все началось с того, что один из авторов начитался Энди Рахина. +1853.72 1868.00 "Анатолий Кулаков" Это такой опасный человек, кто не знает, это автор RavenDB, наверное, самая популярная и самая единственная база данных, которая написана на C#, и у него очень много интересных концептуальных мыслей в голове рождается. +1868.00 1872.48 "Анатолий Кулаков" Не все он их применяет именно к RavenDB, но блок у него довольно познавательный. +1872.48 1891.32 "Анатолий Кулаков" Там много мусора, конечно, но если появляются самородки, они там многие годы живут, и вот там, не знаю, статья четырехлетней, наверное, давности, когда Энди задался вопросом, а почему мы вообще выставляем наши, допустим, идентификаторы сущностей наружу, в общем, этот вопрос все еще открыт. +1891.32 1905.00 "Анатолий Кулаков" И вот Халид Абдухамед, он тоже знаменитый автор блогов, вот, прочитал эту статью, вдохновился и решил разобраться, а как же сделать хорошо на уровне Айспенета. +1905.00 1908.24 "Анатолий Кулаков" И вот мы сейчас с вами все эти темки и пройдем. +1908.24 1917.04 "Анатолий Кулаков" Почему плохо выставлять голые попоидентификаторы наружу, ну, в частности, в Урлы, например, их отдавать, и что же с этим мы можем сделать в Айспенеткой. +1917.04 1922.36 "Анатолий Кулаков" Прежде всего, давайте разберемся, что же в этом плохого, обычно все идентификаторы выставляют, и все нормально. +1922.36 1935.52 "Анатолий Кулаков" Ну, здесь нужно понимать, что речь в основном идет об идентификаторах, интовых, то есть многие спрашивают, зачем там использовать буйды, зачем использовать строки в виде идентификаторов, и давайте использовать наши красивые инты. +1935.52 1943.36 "Анатолий Кулаков" Ну вот, статья, она в основном рассчитана на то, чем инты плохо выставлять наружу, но некоторые моменты, конечно, можно и гуйдам тоже натянуть. +1943.36 1947.92 "Анатолий Кулаков" Давайте по порядочку, чем же плохо, например, интовые идентификаторы выставлять наружу. +1947.92 1955.44 "Анатолий Кулаков" Прежде всего, есть такая атака, которая называется "Url Tempering", это, по сути, подделка Урла. +1955.44 1957.80 "Анатолий Кулаков" И в чем она выражается? +1957.80 1980.04 "Анатолий Кулаков" Когда вы, например, пишете типичный код, вот сервер мой, вот у меня есть ресурс users, и у этого ресурса я хочу вернуть юзера под идентификатором 1, то абсолютно всем ожидаемое поведение, что если мы идентификатор 1 поменяем на идентификатор 2, то нам вернется уже другой юзер, не с идентификатором 1, а тот, который с идентификатором 2. +1980.04 1990.24 "Анатолий Кулаков" И, в принципе, это очень плохая ситуация, потому что здесь мы можем открыть те данные, которые не подразумевались, что нам будут доступны. +1990.24 2004.40 "Анатолий Кулаков" Эта проблема решается в основном тем, что мы заводим некий security слой, мы заводим аутентификацию, авторизацию, и тому пользователю, которому не нужно доставать юзера 2, а только доставать юзера 1, мы ему эти данные просто напросто не вернем. +2004.40 2019.60 "Анатолий Кулаков" Но здесь, опять же, очень большая сложность влетает в виде security, и очень часто бывает, что разработчики забывают разметить специальный контроллер или специальные методы вот такими параметрами security, или еще где-то что-то пропустить. +2019.60 2041.60 "Анатолий Кулаков" В общем, такая ошибка, когда мы подставляем вместо идентификатора какой-то другой идентификатор, следующий идентификатор, или перебираем пачку из миллиона идентификаторов и пытаемся запросить этот ресурс, она очень частая, и, в принципе, наверное, это самая легкая атака, которую вы можете провернуть, если вдруг общаетесь с какими-то другими сервисами и видите какой-нибудь интовый идентификатор, попробуйте так поделать. +2041.60 2066.00 "Анатолий Кулаков" В общем, я очень много открывал таких видеофайлов и всяких, даже на платных курсах, много платных курсов есть, которые вот так вот идентифицируют свои ресурсы и дают вам ссылку только к тому, что вы купили, но при этом проставляя другие идентификаторы, интовые, по порядку вы можете найти еще очень много открытых курсов, которые никаким security не спрятаны, а спрятаны только тем, что вы якобы не знаете идентификатор ресурса. +2066.00 2073.68 "Анатолий Кулаков" В общем, на самом деле, какая бы эта атака смешная и глупая ни казалась, в сети огромное количество ресурсов, которые ей подвержены. +2073.68 2079.00 "Анатолий Кулаков" И это один из принципов, почему плохо интовые идентификаторы выставлять наружу. +2079.00 2091.08 "Анатолий Кулаков" Потому что вы не знаете, каким образом они попадут наружу и кто их будет использовать, и закроются ли они во всех нужных местах с помощью всяких ваших security авторизаций. +2091.08 2094.88 "Анатолий Кулаков" Могут они закрыться, при этом хакеры могут утянуть ваши данные с помощью такого способа. +2094.88 2104.08 "Анатолий Кулаков" И если мы вдруг идентификатор каким-то образом прячем, то это уже становится невозможным. +2104.08 2121.52 "Анатолий Кулаков" Вторая причина, почему плохо интовые идентификаторы выставлять наружу, это потому что данные идентификаторы они могут вам раскрыть, даже не вам, а внешнему наблюдателю, могут раскрыть тонкости реализации вашей системы. +2121.52 2128.12 "Анатолий Кулаков" Ну, например, известно, что интовые идентификаторы очень любят программисты из реалиционных баз данных. +2128.12 2135.08 "Анатолий Кулаков" Вот именно там у них есть такое поверье, что инты - это всегда красиво, это всегда коротко, и вот давайте делать интовые идентификаторы. +2135.08 2140.48 "Анатолий Кулаков" Если же мы возьмем документные базы данных, то там сразу были введены строки. +2140.48 2141.88 "Анатолий Кулаков" И более популярные строки. +2141.88 2158.76 "Анатолий Кулаков" И именно анализируя вот эти данные, можно раскрыть строение вашей внутренней системы, и также можно выяснить некие архитектурные решения, которые у вас есть, и таким образом тоже спланировать каким-то образом вектор атаки на вашу систему. +2158.76 2166.68 "Анатолий Кулаков" Ну, вплоть до того, что даже если мы берем ГУИДы, то дефолтный алгоритм генерации ГУИДов у большинства вас разный. +2166.68 2173.04 "Анатолий Кулаков" То есть мы легко можем отличить какой-нибудь ГУИД от mongdb, от ГУИДа, который там генерирует mssql. +2173.04 2187.08 "Анатолий Кулаков" Также точно вспоминаем, что у нас есть sequential ГУИДы или ГУИДы, которые ни разу не sequential, у нас у ГУИДов есть разные версии, и вот в зависимости от каких-то определенных параметров мы более или менее можем уже узнать, а что там за база данных стоит. +2187.08 2201.00 "Анатолий Кулаков" Более того, некоторые базы данных со временем переходят на новые генерации ГУИДов, но новой версией, то есть мы можем определить не только базу данных, но и даже ту версию, которая база данных там работает. +2201.00 2213.56 "Анатолий Кулаков" Ну, например, тот же самый ravendb менял способ генерации дефолтных идентификаторов с одного формата на другой, и видя этот формат, вы точно можете сказать, что там raven и даже можете сказать от какой до какой версии. +2213.56 2230.40 "Анатолий Кулаков" В общем, это тоже кажется, что ситуация мало, ну как бы мало опасности она в себе внесёт, но на самом деле, зная то, какая база данных там установлена, злоумышленник уже получает какой-то набор о том, о какие эксплойты можно посмотреть для того, чтобы попытаться её проатаковать. +2230.40 2235.04 "Анатолий Кулаков" То есть это какой-то первичный анализ архитектуры очень хорошо раскрывает. +2235.04 2237.56 "Анатолий Кулаков" Поэтому тоже опасная штука. +2237.56 2248.48 "Анатолий Кулаков" Ну и третий аргумент, который здесь можно привести, то есть почему интовые идентификаторы опасно отдавать наружу, то это может раскрыть некие ваши бизнес-показатели, довольно критичные бизнес-показатели. +2248.48 2266.20 "Анатолий Кулаков" Например, если мы посмотрим на идентификаторы, то их очень любят часто без дырок инкрементировать, это один из плюсов интовых идентификаторов, которые вам приводят, что там не бывает никаких дырочек, ну там кроме удалений, этим мы сейчас можем пренебречь, ну не бывает так, что у тебя там появился идентификатор 200, а потом стал идентификатор 5000. +2266.20 2277.04 "Анатолий Кулаков" В общем, всё-таки их стараются инкрементировать по порядку, ну и базы данных нас на это подвигают, если мы сделаем автоинкрементную колоночку, то она тоже всё будет делать по порядку. +2277.04 2278.04 "Анатолий Кулаков" Чем это плохо? +2278.04 2290.84 "Анатолий Кулаков" Ну естественно, тем, что этот инкремент, его можно анализировать, и благодаря вот этому анализу вы легко можете отследить, какие данные у вас были, например, в начале месяца и какие данные, какой идентификатор у вас был в конце месяца. +2290.84 2308.12 "Анатолий Кулаков" И таким образом вы вполне можете вычислить, а какое количество, например, ордеров у вас было, если это идентификатор ордера, какое количество там заказов поступило в вашу систему, какое количество продуктов может быть ваша система оформила или отослала, или какие пользователи там, сколько пользователей сделал покупок. +2308.12 2311.80 "Анатолий Кулаков" Опираясь на эти идентификаторы, вот такие данные очень легко из системы получить. +2311.80 2320.52 "Анатолий Кулаков" Это в большинстве случаев бизнес не хочет делиться такими показаниями, опять же, всем-всем подряд наружу, и даже об этом никто не задумывается. +2320.52 2329.44 "Анатолий Кулаков" Но анализируя расход идентификаторов через API, злоумышленник, опять же, очень легко вот такие показатели считывает и получает. +2329.44 2330.44 "Анатолий Кулаков" Это неплохо. +2330.44 2335.64 "Анатолий Кулаков" Поэтому вот примерно от вот этих трех векторов мы сами и пытаемся защититься. +2335.64 2345.84 "Анатолий Кулаков" Ну, хорошо, мы выяснили, что интовые идентификаторы - это плохо, но если они у вас уже в системе есть, то, естественно, никто их менять и переводить не будет. +2345.84 2346.84 "Анатолий Кулаков" Что же в этом случае делать? +2346.84 2352.52 "Анатолий Кулаков" Очень просто, прежде чем отдать интовые идентификаторы наружу, их очень полезно можно зашифровать. +2352.52 2356.88 "Анатолий Кулаков" А когда принимаем их обратно, их полезно расшифровать и работать с ними дальше. +2356.88 2367.48 "Анатолий Кулаков" Естественно, руками в каждом запросе шифровать и расшифровывать, это никто делать не будет, поэтому у нас есть неявные методы, в которых нам помогает ISP.NET Core. +2367.48 2370.96 "Анатолий Кулаков" Прежде всего, давайте посмотрим, каким образом мы можем зашифровать значения. +2370.96 2373.56 "Анатолий Кулаков" Это делается довольно просто. +2373.56 2387.12 "Анатолий Кулаков" Для этого нам понадобится свой собственный классик, который мы пронаследуем от специального интерфейса, который называется iOutboundParameterTransformer, как несложно догадаться по названию. +2387.12 2398.40 "Анатолий Кулаков" Интерфейс требует от нас, чтобы мы каким-то образом заэнкодили параметры, которые выдаются наружу, а энкодить мы их будем с помощью такого механизма, как Data Protection. +2398.40 2409.96 "Анатолий Кулаков" Data Protection - это прекрасный слой, который скрывает от нас весь ужас шифрования и все знания о ключах, где они хранятся, как они ротетятся, кому принадлежат и прочее. +2409.96 2418.12 "Анатолий Кулаков" Он выдает прекрасный API, у которого есть два метода - protect и unprotect, и все счастливы при этом. +2418.12 2419.76 "Анатолий Кулаков" Но опять же, это пример. +2419.76 2429.32 "Анатолий Кулаков" В данном примере используется Data Protection, который делает все операции памяти, все ключи, генерирует на лету и так далее. +2429.32 2441.52 "Анатолий Кулаков" Если вы будете это в продакшене использовать, то, естественно, вам нужен более сложный подход, как-то ваши ключи хранятся где-то в пересистительном сторе, у них настроен понятный роллинг и так далее. +2441.52 2450.32 "Анатолий Кулаков" Для примера нам достаточно и какой-нибудь In-Memory криптовальщика, в коем как раз и выступает данная имплементация Data Protection. +2450.32 2456.36 "Анатолий Кулаков" Так, после того, как мы написали наш прекрасный классик с интерфейсиком, его достаточно зарегистрировать в сервисах. +2456.36 2471.16 "Анатолий Кулаков" У нас есть прекрасный RouteOptions, у которого есть ConstraintMap, к которому мы добавляем наш класс и все, после этого все руты, которые проходят через нашу систему, подвергаются нашему шифрованию. +2471.16 2475.48 "Анатолий Кулаков" Поэтому все, что вы выдадите наружу, все ID-шники будут зашифрованы. +2475.48 2482.40 "Анатолий Кулаков" Естественно, это касается не того, когда вы урлы ручками форматируете, это касается каких-то системных утилит. +2482.40 2491.16 "Анатолий Кулаков" Например, есть LinkGenerator, который позволяет вам сгенерить урлы для определенного контроллера, экшена, параметров и так далее. +2491.16 2499.44 "Анатолий Кулаков" Если вы будете пользоваться как положено с помощью LinkGenerator, то у вас все вот эти параметры будут зашифрованы, как мы и рассчитывали. +2499.44 2513.16 "Анатолий Кулаков" Также, если вы там используете какие-то RazorPages, и в этих RazorPages у нас там есть RouteTemplates, эти RouteTemplates, естественно, тоже подхватят наш трансформер, и все RazorPages-ссылочки тоже у вас будут за encryption, и пользователь там, естественно, ничего не увидит. +2513.16 2522.36 "Анатолий Кулаков" Если мы используем DataProtection, то внутри у него используется серьезная, как я уже сказал, шифровальная система, там, по-моему, IS какой-то даже стоит. +2522.36 2532.96 "Анатолий Кулаков" Минусы этого IS составляют в том, что после того, как мы маленький int зашифровали, тот же самый единичку, двоечку, из него получается огромная-огромная стакища из месива буковок. +2532.96 2539.64 "Анатолий Кулаков" В общем, минус данного подхода в том, что урлы у вас начинают выглядеть как полная каша, полное месиво. +2539.64 2542.84 "Анатолий Кулаков" Но посмотрим, что с этим можно сделать чуть попозже. +2542.84 2548.48 "Анатолий Кулаков" Давайте теперь вернемся к другой части, да, то есть мы данные-то зашифровали, а как нам их обратно получать? +2548.48 2555.32 "Анатолий Кулаков" А, ладно, обратно там нам хочется тоже int-овые единички получить вместо всего вот этого месива, которое у нас в результате IS вышло. +2555.32 2558.56 "Анатолий Кулаков" И в этом нам поможет ISP NetCoreModelBinder. +2558.56 2563.48 "Анатолий Кулаков" У байндера есть точно такая же система, но только на оборот. +2563.48 2570.24 "Анатолий Кулаков" Есть специальный интерфейс, который называется IModelModelBinder, от которого мы должны пронаследовать наш вышеупомянутый классик. +2570.24 2582.40 "Анатолий Кулаков" И у него всего лишь там навсего перекрыть один метод, который как раз-таки вычленяет нужные данные из контекста, который приходит, из HTTP-контекста, и вызывает у нашего протектора метод unprotect. +2582.40 2586.52 "Анатолий Кулаков" То есть с помощью того же DataProtection API мы эти данные расшифровываем. +2586.52 2601.92 "Анатолий Кулаков" После того, как мы такой интерфейс экземпляризировали, нам нужно вот этот протектор рассказать, то есть рассказать ISP Net, когда применять этот протектор, каким свойствам. +2601.92 2614.88 "Анатолий Кулаков" Самый примитивный способ это сделать, это прямо над свойством навесить атрибут, bind property, и в этом bind property указать того байндера, через который ISP NetCore будет пропускать все реквесты. +2614.88 2627.80 "Анатолий Кулаков" Таким образом мы можем навесить bind property на наши айдишники все, и в эти айдишники после всех наших преобразований будет записываться тот чистый красивый int, который вы и ожидали увидеть. +2627.80 2631.56 "Анатолий Кулаков" В общем так, довольно прозрачно можно сделать и шифрование, и дешифрование. +2631.56 2641.00 "Анатолий Кулаков" И это все сделается, естественно, на уровне ISP Net, и ваш бизнес-логика от этого никак не страдает, она продолжает работать с интами и ничего не знает о всех этих ужасах. +2641.00 2642.00 "Анатолий Кулаков" Криптографии и секьюрити. +2642.00 2647.08 "Анатолий Кулаков" Так, теперь давайте посмотрим, а что же у нас получилось и какие минусы, в принципе, у этого подхода есть. +2647.08 2671.28 "Анатолий Кулаков" Ну, прежде всего, шифрование и дешифрование в данном случае, это настоящее криптографическое шифрование IS, как я уже сказал, оно требует очень много ресурсов, ресурсов процессора прежде всего, поэтому если у вас вдруг какие-то запросы очень частые, и высоконагруженный сервис, и железа мало, то тут уже стоит думать, нужно оно вам или не нужно, потому что encrypt и decrypt идет на каждый реквест. +2671.28 2675.52 "Анатолий Кулаков" Дальше у нас получаются слишком длинные строки. +2675.52 2676.52 "Анатолий Кулаков" Ну как слишком? +2676.52 2683.16 "Анатолий Кулаков" С точки зрения шифрования эти строки нормальны, но если мы будем читать их глазками, то это очень некрасиво выглядит. +2683.16 2690.80 "Анатолий Кулаков" Если у вас с этим нет проблем, вы используете какой-нибудь Razor Pages, никто ваши урлы глазками не читает, то, в принципе, наверное, можно и забить. +2690.80 2699.44 "Анатолий Кулаков" Если же вы все-таки хотите, чтобы ваши урлы были красивыми, более-менее помещались хотя бы в строку браузера, то можно пойти на небольшой компромисс. +2699.44 2704.56 "Анатолий Кулаков" В принципе, в то, что мы делаем, здесь security нам не так сильно важна. +2704.56 2709.72 "Анатолий Кулаков" Нам здесь не нужно полное шифрование, здесь хватило бы какой-то базовой офускации. +2709.72 2726.08 "Анатолий Кулаков" Даже если мы получим, сделаем какую-то базовую офускацию, то есть просто-напросто каким-нибудь шифром Цезаря сдвинем все буквки слева на все байтики или битики слева направо и так далее, не зная алгоритм офускации, довольно сложно подобрать. +2726.08 2729.08 "Анатолий Кулаков" Опять же, довольно сложно подобрать вот этот ключ. +2729.08 2751.32 "Анатолий Кулаков" Поэтому если у вас там не какая-то банковская тайна или финансовая информация или какие-нибудь данные о здоровье, то есть где вам реально не нужна настоящая криптография, а вы просто храните котиков и просто хотите повыпендриваться, то там можете отказаться от криптографии и взять какую-нибудь любую библиотечку по офускации коротких адресов, по офускации интов, айдишников. +2751.32 2755.72 "Анатолий Кулаков" Их в интернете миллион, ну и у нас в выпусках тоже были хорошие обзоры таких библиотечек. +2755.72 2766.40 "Анатолий Кулаков" Можете взять их, но только в этот момент помните, что никакой криптографии там на самом деле нет, а есть просто security by obscurity, то есть пока ваш алгоритм неизвестен, то мало шансов, что его кто-то откроет. +2766.40 2775.80 "Анатолий Кулаков" Также мы получаем небольшой шум из-за вот этих атрибутов, как я уже сказал, что нужно на айдишник навесить специальный атрибут bind property и так далее. +2775.80 2801.48 "Анатолий Кулаков" Но на самом деле вот навешивать атрибуты над каждое свойство не нужно, есть более элегантные хуки, которые позволяют вам там проанализировать всю модель и независимо от, то есть в зависимости от каких-то там параметров, например, если поле называется id или заканчивается на id и его тип int, то применить вот этот bind property атрибут. +2801.48 2817.32 "Анатолий Кулаков" В общем, такие условия тоже можно написать и гораздо лучше их написать и не вымазывать модельки во все эти bind атрибуты, потому что, опять же, последняя проблема это в том, что вы можете забыть навесить такой bind атрибут, то есть навесить такие constraint и получите утечку данных, что очень-очень плохо. +2817.32 2819.08 "Анатолий Кулаков" Лучше таких вещей еще не допускать. +2819.08 2822.68 "Анатолий Кулаков" Если возможно что-то забыть, значит нужно это делать на другом уровне. +2822.68 2826.78 "Анатолий Кулаков" Вот на уровне как раз hook reflection это сделать намного приятнее. +2826.78 2829.08 "Анатолий Кулаков" Там вот 100% ничего не забудете. +2829.08 2839.12 "Анатолий Кулаков" Если property заканчивается на id и имеет тип int, допустим, ее можно автоматически считать, что это property, которое нужно шифровать или аффуцировать и отдавать наружу. +2839.12 2842.40 "Анатолий Кулаков" В общем, и тогда никаких вот этих проблем не будет. +2842.40 2856.92 "Анатолий Кулаков" В общем, вот такой интересный вброс, смотрите, то есть я думаю, что очень важно каждому разработчику понимать, почему int-ы отдавать наружу это плохо, это прежде всего, это главное, что хотелось бы вынести из статьи. +2856.92 2862.92 "Анатолий Кулаков" А то, будете ли вы там шифровать, аффуцировать или дальше как-то этим загоняться, уже зависит от вашего бизнес-кейса. +2862.92 2870.72 "Анатолий Кулаков" Иногда бывает, на большинстве случаев, ситуации, когда бизнесу все равно показывают котиков и никому не интересно сколько котиков мы загрузили в базу. +2870.72 2880.06 "Анатолий Кулаков" В общем, но если это не так, то смотрите, как с антами можно защититься, как их можно аффуцировать и как можно избежать хотя бы базовых проблем. +2880.06 2906.84 "Игорь Лабутин" Ну да, и надо еще помнить, что если как ты говоришь, как-то автоматически это делать, если у нас поле типа int, то автоматически его шифровать или еще как-то заменять на string, то дальше возникает вопрос, если вы автогенерите при этом OpenAPI-спеку из вашей модели, то надо чтобы ваш OpenAPI-генератор дружил с этой логикой и понимал, что там на самом деле надо показать string, а не int. +2906.84 2913.16 "Игорь Лабутин" Потому что многие просто посмотрят на модель и скажут, что вот это там int, и у вас в модельке, ну в спеке будет int. +2913.16 2944.32 "Анатолий Кулаков" Ну опять же, скорее всего, когда ты описываешь вот эти наружные DTOшки, по которым будет генериться OpenAPI-спецификация, то наверное там лучше всего сразу сказать одичнику, что это string, и таким образом вы себя тоже немножко обезопасите, как мы уже обсуждали, как одичники выставляют наружу тему недавнешнюю, что чем меньше внешняя система знает и предполагает о вашей системе, тем лучше, поэтому string – это универсальный идентификатор, самый безопасный тип, который вы можете отдать наружу, и чтобы потребляющая страна ничего об этом не подозревала. +2944.32 2948.92 "Игорь Лабутин" Все так, но ModelBinder и прочее как раз к этим самым DTOшкам-то и применяются. +2948.92 2952.60 "Игорь Лабутин" Поэтому если делать это на автомате, то там должен быть int. +2952.60 2957.80 "Игорь Лабутин" Если применять логику вида int и начинается или заканчивается на id. +2957.80 2960.48 "Анатолий Кулаков" Да, я бы только на одичнике заложился, мне кажется. +2960.48 2962.48 "Анатолий Кулаков" На keep закладываться не стоит. +2962.48 2969.68 "Игорь Лабутин" Я бы явно, на самом деле, писал бы string id, и я бы руками расставлял нужные атрибуты. +2969.68 2994.16 "Игорь Лабутин" То есть мы такое делали, мы, правда, использовали не шифрование, мы использовали когда-то библиотечку hashids.net, сейчас там ее автор переписал, и теперь она называется sqids.net, там я немножко изменил алгоритм, но в принципе это не шифрование никаким образом, это штука, которая генерирует такие, как она называется, ютуб-подобные айдишники. +2994.16 2996.52 "Анатолий Кулаков" Ну да, это как раз вот эти обфускаторы, про которые +2996.52 2997.52 "Игорь Лабутин" я говорил. +2997.52 2998.52 "Игорь Лабутин" Да-да-да. +2998.52 2999.52 "Игорь Лабутин" Это просто, наверное, пожалуй, одна. +2999.52 3005.04 "Игорь Лабутин" Вот hashids на момент, ну, несколько лет назад была чуть ли не одной из самых популярных, мне кажется, которая в среднем гуглилась. +3005.04 3011.84 "Игорь Лабутин" Сейчас автор, она уже давно не обновляется, последний комитет, там четыре года три, по-моему, назад были в нее. +3011.84 3016.60 "Игорь Лабутин" Вот сейчас автор сосредоточился на новой, которая sqids, которая под новый .net уже работает нормально и так далее. +3016.60 3018.76 "Анатолий Кулаков" Я тоже боюсь представить, а что-то можно обновлять. +3018.76 3031.92 "Игорь Лабутин" Ну я не знаю, вот он прямо одну забросил, потом написал, что типа вот, мол, ребрендит и придумал новый алгоритм, который называется sqids, и потом пошел писать отдельную библиотечку для нее. +3031.92 3033.76 "Анатолий Кулаков" Надо же ради интереса посмотреть. +3033.76 3034.76 "Анатолий Кулаков" Вот да. +3034.76 3035.76 "Анатолий Кулаков" Реализация обычная. +3035.76 3063.76 "Игорь Лабутин" Не, я точно знаю, что в старой версии можно было задать seed, то есть ты задавал, мог задать свой кастомный алфавит, но если ты хочешь, например, там по дефолту типа, ну понятно, английские буквы, uppercase, lowercase и цифры, причем там хитро подобрано, чтобы там не было связи, ну в смысле в алфавите не встречалось одновременно там a из-за главной и какая-нибудь там единичка и l прописная, да, чтобы у тебя в идентификатор он был человекочитаемым и легко диктуемым, грубо говоря, в смысле. +3063.76 3066.64 "Анатолий Кулаков" Ну это тоже такое требование есть, но не всегда нужно. +3066.64 3077.52 "Игорь Лабутин" Ну оно не всегда нужно, да, но вот типа по дефолту, ну там были такие настройки, там можно было еще указать seed, чтобы, понятно, он был чуть более уникален, а не так, что это ты написал такое же приложение, куда и перебором все подобрал. +3077.52 3078.52 "Игорь Лабутин" Вот. +3078.52 3084.92 "Игорь Лабутин" А у этого seed указать нельзя, но зато можно указать свой shuffled алфавит типа. +3084.92 3085.92 "Игорь Лабутин" Вот. +3085.92 3094.40 "Игорь Лабутин" Короче, видимо, какая-то, наверное, мелочь, я не знаю почему, ну в общем, решил почему-то переписать, может быть это был повод переписать на новый dotnet и забить на поддержку старого, например. +3094.40 3095.40 "Игорь Лабутин" Тоже вариант. +3095.40 3096.40 "Игорь Лабутин" Ну можно, возможно. +3096.40 3100.20 "Игорь Лабутин" Я не смотрел, с чем он там совместим с точки зрения фреймворков. +3100.20 3113.36 "Игорь Лабутин" Вот, поэтому не знаю, но в общем, да, мы, в принципе, пользовались, приятно, да, когда нужно не показывать чиселки, обычно этого достаточно, в большинстве случаев, вряд ли вам нужно прямо именно шифрование-шифрование. +3113.36 3115.32 "Анатолий Кулаков" Ну если надо, почему нет. +3115.32 3118.00 "Анатолий Кулаков" Да, да, да, обычно так есть. +3118.00 3150.48 "Игорь Лабутин" Ну давай пойдем дальше, дальше у нас блок статей, в смысле, что-то несколько статей, объединенных общей темой, но именно все это от компании, которая поддерживает и развивает фреймворк, тул, не знаю, библиотеку под названием PostSharp, это штука, которая долгое время, я же не знаю, сколько лет живет и, наверное, является чуть ли не одним из основных, источников неправильное слово, из основных библиотек, которые реализуют подход аспектно-ориентированного программирования в дотнете, вот так скажем. +3150.48 3153.04 "Анатолий Кулаков" Из источников проблем ты хотел сказать, да? +3153.04 3158.88 "Анатолий Кулаков" Потому что все, что я знаю про PostSharp, это то, что его надо срочно выпиливать, если вы в каком-то проекте +3158.88 3159.88 "Игорь Лабутин" его нашли. +3159.88 3164.92 "Игорь Лабутин" Ну типа того, давай немножко сначала кратенько скажем, что это вообще такое, в чем была идея. +3164.92 3183.48 "Игорь Лабутин" Идея PostSharp была в следующем, когда-то давно, когда все это начиналось, вы не могли во время компиляции ничего делать со сходным кодом, не было еще никаких сорс-генераторов для рослин, ничего, максимум что было, это всякие T4-шаблоны или самописные кусочки MSBuild скриптов, которые вам что-то там генерили. +3183.48 3185.52 "Игорь Лабутин" А иногда хочется изменять код. +3185.52 3195.16 "Игорь Лабутин" Например, не знаю, там классический пример, который всегда приводит почему-то для аспектно-ориентированного программирования, это что мы хотим залогировать вход и выход каждой функции. +3195.16 3200.08 "Игорь Лабутин" И ни разу не встретил, что бы такое хотелось, но вот это такой классический пример. +3200.08 3227.24 "Игорь Лабутин" Значит для этого можно встроить специальный плагин по сути в MSBuild pipeline, который после того, как у вас изгенерена сборка, уже DLL собрана MSBuild, возьмет эту сборку, декомпилирует ее, разберет IL-код, найдет везде, где есть ваши методы, и в нужные места пропатчит IL-код и соберет обратно сборку согласно тому, как вы ему описали. +3227.24 3231.16 "Игорь Лабутин" То есть там атрибутами поверх функции, либо еще как-то. +3231.16 3239.04 "Игорь Лабутин" То есть некоторый патчинг вашей DLL, вашего кода, уже после его сборки на уровне IL-кода. +3239.04 3247.44 "Игорь Лабутин" С одной стороны это позволяет сделать огромное количество вещей, потому что в IL-коде можно сделать практически все. +3247.44 3284.84 "Игорь Лабутин" С другой стороны эта штука довольно сложна, она очень хрупкая, потому что она по сути, если вы хоть как-то изучали, во что превращается ваш async метод, когда это стоит машина, и большой метод с кучей свитч кейсов, это все нужно аккуратно поддерживать на уровне IL-кода, это у вас все просто, в C#, а на IL-коде это может развернуться в довольно большие простыни, разные методы, еще что-нибудь, какие-то промежуточные объекты, это все надо как-то понимать, куда все это внести, как это распознать и понять, куда что встраивать. +3284.84 3296.98 "Игорь Лабутин" Поэтому эта штука действительно источник проблем, потому что на уровне IL-кода можно было это все сломать, причем можно было это сломать на уровне, чтобы получалась сборка, которая при попытке загрузки говорила, что у тебя вообще-то невалидная сборка. +3296.98 3299.48 "Игорь Лабутин" Что-то такое мне встречалось как-то пару раз. +3299.48 3305.00 "Игорь Лабутин" То есть IL-код был приведен в состояние, что он, ну короче, некорректный. +3305.00 3316.64 "Игорь Лабутин" Компания, ну PathShark при этом довольно популярный, ну видимо потому что плюс-минус единственный, вот, наверное какие-то вещи с ним действительно делать удобно или других способов может быть нет. +3316.64 3324.72 "Игорь Лабутин" Если вы, например, использовали какую-нибудь там кодогенерилку или какую-нибудь стороннюю библиотеку, с которой вы ничего не можете сделать, то PathShark можно было ее хоть как-то подходить. +3324.72 3354.56 "Игорь Лабутин" Но жизнь не стоит на месте, Roslin двигается, дотнет меняется, и компания поняла в какой-то момент, на самом деле это было несколько лет назад, судя по статейочке, одно из, что становится все это поддерживать сложнее и сложнее, а Roslin развивается, появились сурс-генераторы, появилась возможность генерить код нормально в каком-то разумном виде в момент компиляции, причем генерить сразу C#, чтобы дальше компилятор уже сам все компилировал. +3354.56 3361.56 "Игорь Лабутин" Но есть одна проблема, все еще нельзя менять код. +3361.56 3367.08 "Игорь Лабутин" То есть вы пока Roslin с сурс-генераторами не можете изменять существующий код. +3367.08 3374.36 "Игорь Лабутин" То есть если у вас есть, например, задача добавить то самое логирование для всех вызываемых методов, то Roslin вы это сейчас делать не сможете. +3374.36 3378.18 "Игорь Лабутин" По C# можно, но по C# это все делать хрупко и ненадежно. +3378.18 3401.48 "Игорь Лабутин" Поэтому компания подумала, поняла, что по C# что-то как-то сложно становится поддерживать, и все свои силы кинула на новый продукт, который теперь называется Metalama, он вышел чуть больше полгода назад, но тут сейчас прошел ряд статей по поводу опенсурсности некоторых кусочков, поэтому он снова появился у нас в наших источниках новостей и мы про него рассказываем. +3401.48 3404.48 "Игорь Лабутин" Что же такое Metalama? +3404.48 3417.20 "Игорь Лабутин" Это, как они называют, очень простой и очень мощный инструмент для генерации кода и для валидации кода для C#, для метапрограммирования. +3417.20 3432.80 "Игорь Лабутин" У него фокус на простоту и безопасность, то есть это в отличие от PostSharp они стараются сделать так, чтобы ничего не ломалось в ваших приложениях, и они сказали, что они reimagined, то есть они перепридумали аспектно-ориентированное программирование для современного дотонета. +3432.80 3435.40 "Игорь Лабутин" Значит, что же такое и как это теперь выглядит? +3435.40 3462.64 "Игорь Лабутин" Значит, аспекты, у них есть два понятия, аспект и, ну они это называют fabrics, это не фабрики, в смысле фабрики были бы factories, это скорее fabrics, в смысле нити, ткани, ну то есть что-то такое вот связующее, видимо, эта мысль была при назывании, это все C#-классы, которые исполняются внутри компилятора или внутри IDE, пока вы редактируете код. +3462.64 3482.68 "Игорь Лабутин" То есть позволяют делать следующее, позволяют генерить код в compile-time, либо менять код в compile-time, позволяют, если все это работает во время IDE, верифицировать ваши исходники по всяким паттернам и правилам, ну и дальше даже позволяются какие-то фиксы и рефакторинги. +3482.68 3484.48 "Игорь Лабутин" Как этим всем пользоваться? +3484.48 3490.08 "Игорь Лабутин" Давайте сначала с простого поймем, потом попаковаемся внутри, как же это устроено и работает. +3490.08 3506.48 "Игорь Лабутин" Значит, есть NuGet пакет, называется metalama.framework, который вы добавляете в ваш продукт, можно добавить некоторые экстенджеры для Visual Studio и поставить, тогда там будут некоторые полезные тулзы доступны, и дальше вы создаете аспект. +3506.48 3539.16 "Игорь Лабутин" Ну, например, возвращаясь к нашему простому примеру с логированием, вы создаете аспект, это, по сути, класс, который будет применяться, как правило, атрибутом, в данном случае тогда вы его назовете LogAttribute по конвенции C#, который наследуется от класса OverrideMethodAspect, после чего в нем нужно заверрадить единственный метод, который называется OverrideMethod, который возвращает, вот тут я прям удивился, он возвращает nullableDynamic, прикинь, вот. +3539.16 3540.16 "Игорь Лабутин" Да. +3540.16 3548.76 "Игорь Лабутин" То есть динамик с вопросиком, прям такой, туда подойдет все что угодно, вообще, не знаю, зачем динамик с вопросиком. +3548.76 3551.60 "Игорь Лабутин" Типа теперь точно вообще все что угодно. +3551.60 3563.64 "Игорь Лабутин" Вот, и внутри у вас есть, соответственно, некоторый базовый protected property под названием meta, у которого есть пачка properties и методов, с помощью которых вы можете общаться с тем методом, который вы заверраете. +3563.64 3575.64 "Игорь Лабутин" То есть метод.target.method даст вам название этого метода, метод.proceed, собственно, вызовет этот метод, и если он возвращает какой-то результат, вы присваиваете его в переменную result и его возвращаете. +3575.64 3578.64 "Игорь Лабутин" Благодаря динамику вы можете вернуть вообще все что угодно. +3578.64 3585.68 "Игорь Лабутин" Я не знаю, ничего не сказано, как это будет работать с ассинк методами, вот этим всем, но как бы надо изучать. +3585.68 3587.88 "Игорь Лабутин" Настолько детально я туда не копался. +3587.88 3594.92 "Игорь Лабутин" Дальше вы этот атрибют, который, LogAttribute вы объявили, вы его применяете к нужным методам, либо вы можете сделать по-другому. +3594.92 3603.24 "Игорь Лабутин" Вы можете объявить новый класс, который тот самый Fabric, и внутри с помощью linkStyle сделать такую штуку. +3603.24 3640.68 "Игорь Лабутин" То есть вы, например, можете написать, там появляется пропертиа под названием amender, от английского amend, ну типа изменять, да, и дальше вы там делаете select, в скобочках пишите условия там на все типы, where, там где эти типы объявлены как public, из них делаете select many, там методы where, там допустим, хочу все public и при этом чтобы они были не toString, да, ну типа toString не будем блокировать, и потом добавляем, типа addAspect, и указываете ваш атрибутчик, который вы создали, и оно автоматически в compile-time все добавится, вот. +3640.68 3656.68 "Игорь Лабутин" Когда происходит compile-time, эта лама меняет C# код перед тем, как отдавать его собственно к компилятору на компиляцию, она меняет C# код и физически вставляет туда кусочки C#, ну вот того, что вы написали с точки зрения Console.WriteLine и так далее. +3656.68 3691.12 "Игорь Лабутин" То есть на самом деле, вот эти вот override метод, который динамик с вопросиком, я так понимаю, выполняться не будет именно как выполнение, то есть это по сути просто шаблон аспекта, и нужен там этот динамик просто чтобы компилятор был доволен, ну потому что это тоже же код, который он как бы пытается скомпилить, возможно, вот, а фактически получается, что ваш код меняется так, что вот эти вот кусочки, которые вы добавили там до, например, вызова .prosheet и после, они будут аккуратно вставлены в те места, которые размечены правильными атрибутами. +3691.12 3699.96 "Игорь Лабутин" Вот, такая вот магия, выглядит действительно немножко магически, но прикольно. +3699.96 3721.08 "Игорь Лабутин" Дальше вы можете сказать, что на самом деле, на самом деле, это металлама, я так все, постшарп, постшарп, постшарп не единственная штука, которая позволяет, ну делать что-то подобное, то есть во-первых, есть постшарп действительно, во-вторых, есть сам рослинг, который что-то там позволяет, и в-третьих, есть еще такая штука, тоже, может быть, слышал или даже, наверное, какой-то, или выпиливал из проектов, это Фоди. +3721.08 3725.88 "Анатолий Кулаков" Ну да, да, Фоди, мне кажется, самый популярный, потому что он бесплатен, в отличие от этого монстра. +3725.88 3764.80 "Игорь Лабутин" Ну да, вот, наверное, кстати, да, ты прав, мне вот Фоди, ну Фоди, кстати, я нигде не встречал в живых проектах, даже постшарп встречал почему-то, ну да ладно, значит, и там в этой статичке есть сравнение, что можно сделать с помощью постшарпа, розлина и Фоди, значит, и несколькими киллер-фичами, собственно, этой самой металламы, это как раз-таки отладка и экспорт трансформированного кода, то есть можно скомпилировать его со специальным ключиком, когда вы увидите весь код именно C#, да, он выплюнет его в какой-нибудь OPJ output, так, чтобы вы видели, как ваш код выглядит после того, как к нему применены все ваши аспекты. +3764.80 3769.32 "Игорь Лабутин" Ну и там всякие разные варианты, что ещё можно с ним делать. +3769.32 3775.08 "Игорь Лабутин" Значит, как ты правильно сказал, Фоди бесплатный постшарп. +3775.08 3778.56 "Игорь Лабутин" Я не помню, что там было с лицензиями, но по-моему, там какая-то версия была платная, там была какая-то +3778.56 3783.32 "Анатолий Кулаков" бесплатная версия, но… Не знаю, я помню, что всегда постшарп был довольно дорогой штукой. +3783.32 3785.48 "Игорь Лабутин" Ну может быть, может быть, не помню. +3785.48 3791.72 "Игорь Лабутин" С Pentalama тоже история такая, что она частично платная, частично бесплатная. +3791.72 3798.40 "Игорь Лабутин" Ну точнее как, у неё есть несколько эдишенов, один из них это бесплатный эдишен, полный себе, берите, пользуйтесь. +3798.40 3802.92 "Игорь Лабутин" У него есть ограничения, то есть вот этих вот аспектов можно сделать три штуки максимум на проект. +3802.92 3820.92 "Игорь Лабутин" Ну и там другие есть, самые… Не будет никакого отладки, то есть вы не сможете делать степ-ин в Generated Code, то есть вы не сможете при отладке заходить в ваши аспекты внутрь, и у вас не будет там тестинг-фреймворка для ваших аспектов. +3820.92 3823.56 "Игорь Лабутин" Так, у них есть аж специальный тестинг-фреймворк для аспектов. +3823.56 3830.48 "Игорь Лабутин" Вот, и еще есть некоторое количество ограничений, но мне кажется, самое важное – это все самые три аспекта на проект. +3830.48 3833.28 "Игорь Лабутин" Если уж вы хотите в аспекты ориентирования и программирования, ну наверное, трех будет мало. +3833.28 3841.00 "Игорь Лабутин" Ну и даже там какие-то цены, понятно, я особо сейчас не буду распространяться, потому что всё это может меняться и так далее. +3841.00 3847.16 "Игорь Лабутин" Давай к интересной части, как это всё построено, как это всё устроено и на основе чего это всё сделано. +3847.16 3856.76 "Игорь Лабутин" Сам по себе metalama-компилятор, он open-source, его можно посмотреть, его можно взять, его можно использовать, и это просто форк рослина. +3856.76 3857.76 "Игорь Лабутин" Форк? +3857.76 3858.76 "Анатолий Кулаков" Да. +3858.76 3859.76 "Анатолий Кулаков" Прямо форк? +3859.76 3860.76 "Анатолий Кулаков" Прямо форк. +3860.76 3861.76 "Анатолий Кулаков" И как его поддерживают-то? +3861.76 3876.60 "Игорь Лабутин" То есть это прямо форк, если зайти в github-репозиторий metalama-компайлер, там прямо написано forked from.net/roslin, то есть это прямо не просто копия, знаешь, как иногда делают, типа ну клонируют и коммитируют к новой репозитории, это честный прямо форк в уровне гитхаба. +3876.60 3878.64 "Анатолий Кулаков" Ну то есть они забираются как-то поддерживать. +3878.64 3902.12 "Игорь Лабутин" Да-да-да, они сделали следующую штуку, значит вот этот framework, который metalama-framework, она является по сути плагином для компиляторов в compile-time, или плагином для самого основного рослина, если у нас в design-time, в design-time ты же не можешь подменить рослин, который внутри студии живет, но можно к нему заплагиниться. +3902.12 3917.16 "Игорь Лабутин" Внутри рослина у нас есть аналайзеры и генераторы, то есть на основе аналайзеров можно делать любые аналайзеры, на основе генераторов можно генерировать новый код, тут все хорошо, и не хватало только трансформеров, вот они добавили концепцию трансформеров. +3917.16 3941.28 "Игорь Лабутин" Можно посмотреть, как это сделано, вероятно они собираются это дело поддерживать в том смысле, что когда будет меняться рослин под новые версии компилятора, они будут себе обновлять из AppStream, грубо говоря, основной рослин и допиливать свою поддержку вот этих source-трансформеров под какие-то новые фичи языка, например, и так далее. +3941.28 3944.56 "Игорь Лабутин" То есть но базовый рослин, базовый компилятор остается базовым. +3944.56 3947.08 "Игорь Лабутин" Прямо вот нативный, который берется из дотнета. +3947.08 3953.40 "Анатолий Кулаков" Ну смотри, кажется, если вот думать, а как, можно было бы по-другому сделать, но это, скорее всего, один из самых лучших вариантов. +3953.40 3998.60 "Игорь Лабутин" Ну, кажется, что да, то есть они сказали, что они сначала пытались сделать это, там у них есть такие небольшие размышления какие-то, ну, историю, что они сначала делали это в private форке, не зная, насколько они смогут сделать прям вот такой форк, который можно будет именно обновлять из AppStream, но, видимо, все получилось, поэтому оно в open-source, его можно, если вам нужен рослин с source-трансформерами, можно взять Metalama Compiler, у него, по-моему, нормальная лицензия, если я правильно помню, а вот Metalama Framework, собственно, статья, из-за которой мы это все добавили сюда, снова всплыло оно в новостях, его тоже за open-sourcely, то есть вот этот Metalama Framework, который, как я сказал, он там платный, вот это все, он open-sourced. +3998.60 4004.92 "Анатолий Кулаков" А как же там ограничение в три штучки, если любой дурак может пойти себе собственный фреймворк собрать? +4004.92 4010.04 "Игорь Лабутин" Вот, собрать ты его не можешь, по двум причинам. +4010.04 4011.60 "Игорь Лабутин" Причина первая, лицензия не позволяет. +4011.60 4014.20 "Анатолий Кулаков" Погоди, у нас параллельный импорт, как лицензия. +4014.20 4015.20 "Анатолий Кулаков" Давай по существу. +4015.20 4017.64 "Игорь Лабутин" Второе, там нет ничего для сборки. +4017.64 4018.64 "Игорь Лабутин" Исходники C#? +4018.64 4026.84 "Игорь Лабутин" Ну, как они сказали, мы выложили 99%, одного процента не хватает и без него вы не соберете это в нормальный работающий +4026.84 4027.84 "Анатолий Кулаков" вид. +4027.84 4030.12 "Анатолий Кулаков" Ну интересно, конечно, посмотреть, а что именно там не хватает. +4030.12 4035.50 "Анатолий Кулаков" Мне кажется, что айтузоазисты, по сравнению с ценой на настоящую металламу, этот 1% должны дописать за один +4035.50 4036.50 "Игорь Лабутин" вечер. +4036.50 4037.50 "Игорь Лабутин" Ну, возможно, возможно. +4037.50 4040.80 "Игорь Лабутин" Я с интересом посмотрю, во что это превратится. +4040.80 4046.32 "Игорь Лабутин" Пока никаких следов я поискал, ничего не видно, никаких энтузиастов не появилось. +4046.32 4067.92 "Игорь Лабутин" И сделали они это для двух целей, соответственно, это упрощение отладки, потому что если у вас вдруг, видимо, они научены опытом постшарпа, который там портил лейкод и вот это все, короче, упрощает отладку, то есть вам нужно посмотреть, как оно там, черт возьми, трансформирует что-то куда-то, ну вот, пожалуйста, вот исходники. +4067.92 4080.08 "Игорь Лабутин" Ну и какая-то общая фраза про increase trust and transparency, вот это все, но 1% мы вам не дадим, но можно купить металлама source code subscription, и тогда вам дадут остатки исходников. +4080.08 4083.56 "Анатолий Кулаков" Ну вот кто-то один, может, купит и выложит всего старым. +4083.56 4099.16 "Игорь Лабутин" Ну, короче, понятно, что способы есть наверняка, да, можно и по шармам было, наверное, бесплатно пользоваться, но как бы такой вот забавный, забавная, так скажем, забавный подход к open-source, посмотрим, человек. +4099.16 4118.76 "Анатолий Кулаков" Нужно признать, что постшарп это один из просто старейших инструментов в дотнете, которые есть, если вспоминать какие-нибудь старые фреймворки, которые выжили, ну и выкинуть оттуда все юайные компоненты, то старее постшарпа, я не знаю, фреймворка коммерческого именно, который выжил, и парадокс в том, что я реально встречал его в многих компаниях. +4118.76 4129.36 "Анатолий Кулаков" Ну, то есть, у него, наверное, была какая-то хорошая пиар-акция когда-то на заре времен, что его затащили и купили, главное, что смешно как бы, в очень большом количестве компаний. +4129.36 4134.08 "Анатолий Кулаков" В общем, но я не встречал ни одной компании, которая об этом не пожалела и не хотела бы его выпилить. +4134.08 4145.32 "Игорь Лабутин" Ну, вот посмотрим металлам, может быть, кстати, они тоже этот тренд увидели, что там, не знаю, выпиливают, и юзедж сокращается, и продавать стало сложнее, и решили переписать это все на более безопасный вариант. +4145.32 4146.32 "Анатолий Кулаков" Ну, да. +4146.32 4152.08 "Игорь Лабутин" И в принципе, если даже постшарп продавался с опасным вариантом, то этот тоже, наверное, будет продаваться. +4152.08 4158.12 "Анатолий Кулаков" Ну, наверняка, опять же, потому что аспектно-ориентированное программирование дает нам очень много интересных возможностей. +4158.12 4160.76 "Анатолий Кулаков" Особенно если мы говорим про сложные интерпрайзы, ну а где у нас еще деньги? +4160.76 4161.96 "Анатолий Кулаков" Ну, естественно, в сложных интерпрайзах. +4161.96 4195.84 "Анатолий Кулаков" В общем-то, там действительно есть случаи, когда таких инструментов не хватает, и если те инструменты не будут как бы пилить иль код, который ломается с новой версии компилятора, а все делается на честных генераторах, а честные генераторы, нужно понимать, их плюс, что теперь команда постшарпа металлама не отвечает за то, чтобы их поддерживать, теперь команда Рослина отвечает, что все, что было сгенерировано, компилировалось с любой версией компилятора, то у них там просто 80% всей работы с них спадает, и поэтому они могут больше сосредоточиться на каких-нибудь интересных фичах или тех же самых маркетинговых статьях. +4195.84 4207.20 "Игорь Лабутин" Не, ну те самые трансформеры все-таки Рослин никак не поддерживает, поэтому с ними-то как раз все еще мучиться надо, разбирать все новинки языка, чтобы понимать, как их трансформировать. +4207.20 4215.40 "Анатолий Кулаков" Скорее всего тебе там нужно было просто сунуться в нужную точку и всё, а все новинки языка – это тебе просто-напросто существующая Рослин-дерево приходит и разбирает как хочешь. +4215.40 4226.68 "Игорь Лабутин" Не, ну Рослин-дерево – это большой бонус, понятно, и понятно, почему они взяли Рослин, это просто очевидно, что еще в тот ней-то брать, учитывая, что он тебе доступен, плюс-минус. +4226.68 4232.84 "Игорь Лабутин" Но все равно какая-то логика понятная, с самой металламой там есть, то есть как-то все эти нужно. +4232.84 4237.60 "Анатолий Кулаков" Ну наверняка, мне просто кажется, что здесь в миллиард раз меньше усилий, чем поддерживать постшарп. +4237.60 4238.60 "Анатолий Кулаков" Конечно, конечно. +4238.60 4240.40 "Анатолий Кулаков" Постшарп вот с именем их, это вообще ужас. +4240.40 4241.40 "Анатолий Кулаков" Да. +4241.40 4246.72 "Анатолий Кулаков" И то работал, и то люди платили, и то были в принципе счастливы, поэтому да, наверное, свои вендоры найдутся. +4246.72 4256.60 "Анатолий Кулаков" Ну если вы вдруг использовали или до сих пор самое интересное, почему-то используете постшарп, и при этом не хотите его выпиливать, прийдите в комменты, расскажите, что у вас за юзкейсы такие-то интересные. +4256.60 4260.36 "Игорь Лабутин" Ну или может быть проапгрейдитесь на металламу и посмотрите, что там как. +4260.36 4261.36 "Анатолий Кулаков" Или так, да-да. +4261.36 4282.24 "Анатолий Кулаков" Ну и чтобы далеко не отпускать металламу, надо признаться, что у металламы главный ментейнер и главный фаундер и лид-девелопер – это товарищ Гаэль, фамилию Фрайтер. +4282.24 4286.32 "Анатолий Кулаков" Ты помнишь, как у него фамилия произносится? +4286.32 4296.52 "Игорь Лабутин" Я её обычно произношу Фрэтер, но он то ли француз, то ли бельгиец, я не помню, кто он. +4296.52 4305.16 "Игорь Лабутин" И у них как-то фамилия не всегда правильно, в смысле легко произносится, букв много, а иногда, как скажешь, так там это. +4305.16 4308.64 "Анатолий Кулаков" Короче, в узком круге, да, он знаменит как Гаэль. +4308.64 4315.04 "Анатолий Кулаков" В общем, Гаэль является фаундер и лид постшарпа, и естественно металламы той же самой. +4315.04 4324.84 "Анатолий Кулаков" И вот Гаэль тут недавно пришёл и рассказал в статьечке, а каким образом они обеспечивают качество своих продуктов, даже качество кода. +4324.84 4331.16 "Анатолий Кулаков" Так как они много выкладывают в open-source, все себе красивые, все такие, в общем в open-source код должен быть красивым. +4331.16 4333.88 "Анатолий Кулаков" Работать не работай, там за лицензией или что-то это дело десятое. +4333.88 4335.16 "Анатолий Кулаков" Главное, чтобы было красиво. +4335.16 4346.64 "Анатолий Кулаков" И вот он пришёл и рассказал, а как же они собственно обеспечивают красоту своего кода, чтобы он был весь отлаженный, проанализированный, отформатированный, что у них там, собственно, в команде происходит. +4346.64 4347.64 "Анатолий Кулаков" Давайте же нырнём. +4347.64 4350.52 "Анатолий Кулаков" Раз продукт мы посмотрели, давайте посмотрим теперь, как они работают. +4350.52 4359.92 "Анатолий Кулаков" И обсудим его статичку, которая называется Codestyle for Better Productivity, т.е. что же они там такого для улучшенной производительности делают со своим стилем кода. +4359.92 4389.84 "Анатолий Кулаков" Ну, прежде всего, когда вы начинаете новый проект, то первые шаги, на которые вы должны сделать, это сделать так, чтобы в вашей команде удобно было работать вместе, и чтобы, например, тот код, который вы пишете, он был согласованным и все в команде его хорошо понимали, все хорошо представляли, в каком виде этот код надо писать, все хорошо понимали тот Codestyle, которому он должен соответствовать. +4389.84 4395.36 "Анатолий Кулаков" Ну и даже если они плохо это понимают, что какие-то инструменты, били их по рукам и рассказывали, как надо понимать хорошо. +4395.36 4405.52 "Анатолий Кулаков" Это означает, что вы должны на берегу ещё договориться, желательно до первой строчки кода, пока вы напишете, договориться о кодформатинге и нейминге. +4405.52 4415.40 "Анатолий Кулаков" Ну, кодформатинг — это пресловутые вещи, там, табы против спейсов, сколько там пустых линий, пустых строчек оставлять, где расставлять скобочки, вот это вот все. +4415.40 4422.80 "Анатолий Кулаков" И нейминги, то есть какие суффиксы давать, какие префиксы давать, что как называть, это все относится к неймингу. +4422.80 4436.56 "Анатолий Кулаков" А также есть банальные какие-то вещи, там, использовать var, использовать this, ну, то есть самые священные страшные коровы, из-за которых только бывают войны, вот это все относится как раз к форматингу, неймингу и то, что мы сегодня будем с вами обсуждать. +4436.56 4462.14 "Анатолий Кулаков" Поэтому желательно эти войны сделать до того, как вы пойдете писать код, потому что если эти войны будут начинаться постепенно, когда кто-то уже что-то написал, потом кто-то несогласен, взял переформатировал, сделал pull request, тот не одобрил, в общем, эти вот распри, они могут длиться еще дольше, чем то время, которое вы потеряете перед тем, как сесть вот на берегу и это все написать. +4462.14 4469.16 "Анатолий Кулаков" И вот команда Metalama как раз хочет поделиться с нами своим опытом, как это происходило у них и что они делали. +4469.16 4471.80 "Анатолий Кулаков" Прежде всего, зачем все это нужно? +4471.80 4473.44 "Анатолий Кулаков" Ну, это консистентность. +4473.44 4485.04 "Анатолий Кулаков" Консистентность прежде всего для чтения, когда вы читаете код и знаете, что он отформатирован одинаково во всех файлах, которые бы вы не открыли, вам его удобней читать, удобней по нему навигироваться, удобней по нему понимать. +4485.04 4503.08 "Анатолий Кулаков" И так как по выдуманной статистике разработчик проводит 80% именно читая код, а не написывая его, то мы как раз увеличиваем вот эту вот самую главную точку, на которую он тратит свое время, мы как раз увеличиваем читабельность кода. +4503.08 4513.72 "Анатолий Кулаков" Также единообразность кода дает вам возможность проще разбираться в коде и дает вам меньше конфликтов на мерш-реквестах. +4513.72 4527.36 "Анатолий Кулаков" Или на pull-request, когда вы заливаете свой код, то если он отформатирован и украшен правильно, то в этот момент у вас будет меньше проблем с конфликтами, которые могли внести другие разработчики. +4527.36 4541.72 "Анатолий Кулаков" Особенно если другие разработчики взяли и нажали там кнопочку какой-нибудь отформатировать, и все, весь файл, который вы там так радостно редактировали, вот эта функция форматирования она вам выдала сразу 100-500 конфликтов. +4541.72 4545.88 "Анатолий Кулаков" В общем, весь файл поехал, и все, и формат превратился в какую-то для вас кашу. +4545.88 4551.08 "Анатолий Кулаков" В общем, если вы вдруг используете единый код-стайл, то такой ситуации у вас уже технически даже быть не может. +4551.08 4561.60 "Анатолий Кулаков" Так, теперь давайте посмотрим все-таки, откуда нам брать стили и как нам дойти к этому общему соглашению. +4561.60 4578.56 "Анатолий Кулаков" Мы все знаем прекрасно, что у каждого, каждый человек это гребаная снежинка, и у этой снежинки есть какое-то свое мнение о том, каким образом должны расставляться табы и где быть скобочки, и если мы начнем об этом спорить, то такие священные войны, они могут продолжаться до бесконечности. +4578.56 4584.28 "Анатолий Кулаков" Но, опять же, как советует автор, лучше все-таки договориться до начала написания кода. +4584.28 4586.52 "Анатолий Кулаков" Как нам к этим можно договориться? +4586.52 4604.16 "Анатолий Кулаков" Ну, прежде всего, с основу автор рекомендует взять стандарт Микрософта, у Микрософта есть такая прекрасная страничка, которая называется Common Coding Conventions for C#, то есть как ни трудно догадаться, там есть какие-то базовые основы, что в C# нормальном коде в современном должно быть. +4604.16 4612.24 "Анатолий Кулаков" И там куча, кстати, интересных рекомендаций, если вы вдруг давно не обновляли или не знали, то можно просто пройти посмотреть, статичка не очень большая. +4612.24 4627.84 "Анатолий Кулаков" Ну, кстати, оттуда же можно подчеркнуть такий интересный факт, что конфигура wait нужно использовать всегда, что нужно использовать space вместо табов, что ширина строчки должна быть 65 символов, не больше, и так далее. +4627.84 4635.64 "Анатолий Кулаков" Такие базовые вещи, за которых многие спорят, их можно честно ссылаться на Микрософт и эти халевары такие заканчивать. +4635.64 4640.64 "Анатолий Кулаков" Документ хороший, но, к сожалению, он не покрывает абсолютно всего. +4640.64 4645.48 "Анатолий Кулаков" И мне кажется, это большая недоработка Микрософта до сих пор. +4645.48 4654.48 "Анатолий Кулаков" Если бы она выпустила какой-нибудь документ, который, не знаю, как у Python, допустим, который строго говорит, как надо форматировать, и всё, ни шагу влево, ни шагу вправо. +4654.48 4656.68 "Анатолий Кулаков" Мне кажется, было бы намного меньше у нас проблем. +4656.68 4667.12 "Анатолий Кулаков" В общем, но опять же, оставим какое-то место, чтобы люди могли поспорить, поэтому Микрософт какие-то основные вещи обозначила, но обозначила не всё. +4667.12 4670.96 "Анатолий Кулаков" И вот это не всё, вот этим уже нужно договариваться. +4670.96 4684.20 "Анатолий Кулаков" Вот конкретно для каждого проекта вырабатывать какие-то договорённости, спрашивать опыт разработчиков на тех или иных проектах, в общем, каким-то образом пытаться это свести к какому-то общему договорённости. +4684.20 4692.68 "Анатолий Кулаков" И как только мы все договорились, пусть даже кто-то из разработчиков не согласен в итоге с этой договорённостью, каждый разработчик обязан эти договорённости соблюдать. +4692.68 4694.60 "Анатолий Кулаков" Без всяких обсуждений и так далее. +4694.60 4700.52 "Анатолий Кулаков" Если эта договорённость зафиксирована в команде, то всё, дальше обратного хода уже никакого нет. +4700.52 4711.52 "Анатолий Кулаков" Также ещё нужно помнить, что в принципе вырабатывание стандартов – это интеративный процесс, если вы до всего сразу не смогли договориться или все сразу скобочки не вспомнили, то естественно вы не обязаны это делать. +4711.52 4722.64 "Анатолий Кулаков" Как только вы начнёте разрабатывать, и у вас станет такой вопрос, в будущем, а почему эта скобочка забыта здесь, и мы её не перенесли, вот в этот момент можно опять же этот вопрос поднять и снова вернуться к нашим скобочкам. +4722.64 4727.52 "Анатолий Кулаков" Поэтому процесс итеративный, главное договориться о каких-то базовых вещах, и всё остальное потом можно дорабатывать. +4727.52 4730.96 "Анатолий Кулаков" Так, теперь, предположим, вы договорились, что же дальше мы будем делать? +4730.96 4736.16 "Анатолий Кулаков" То есть каким же образом нам теперь нужно сконфигурить наши инструменты для того, чтобы они нам помогали работать? +4736.16 4749.76 "Анатолий Кулаков" Ну, прежде всего любая уважающая себя IDE должна поддерживать файлы Editor-Config, Visual Studio, Visual Studio Code, ReSharper, ReRider, и тому, и, в общем, мне кажется, всё, что возможно поддерживать сейчас Editor-Config и хотя бы в каком-то там минимальном его наборе. +4749.76 4755.68 "Анатолий Кулаков" Поэтому рекомендуется добавить файл Editor-Config и обязательно залить его в репозиторий. +4755.68 4761.40 "Анатолий Кулаков" То есть это не должен быть файл, который у каждого разработчика свой, куда-то он его там положил, где-то там заинклудил, нет. +4761.40 4771.32 "Анатолий Кулаков" Это штука, которая лежит в репозитории, и он один у всех разработчиков, и более того, он один даже на Continuous Integration систему, она его в том числе обязана учитывать. +4771.32 4781.56 "Анатолий Кулаков" В идеале вот этот файл, он не должен оставлять какого-то места для самовольности, да, то есть чтобы вот таких нелепых снежинок у нас не появлялось. +4781.56 4789.44 "Анатолий Кулаков" Если у нас есть какое-то правило, как должен использоваться код, то он обязан прописываться в этом файле. +4789.44 4799.68 "Анатолий Кулаков" В частности, рекомендуется выставить warning, где только возможно, на всех возможных там форматированиях, скобочках и так далее. +4799.68 4806.84 "Анатолий Кулаков" В Editor-Config это можно прописать как warning, да, то, что если скобочка находится не на своем месте, он вам выдает warning. +4806.84 4815.76 "Анатолий Кулаков" И при этом рекомендуется поддерживать zero warning код, да, то есть у вас там не должно быть warning в вашем коде, естественно, за этим надо следить. +4815.76 4821.84 "Анатолий Кулаков" Вот, еще существует такой инструмент, как ReSharper Code Formatting. +4821.84 4830.80 "Анатолий Кулаков" Наверняка каждый из вас сталкивался с непонятными файликами, которые появляются в вашем репозитории и имеют окончание .sln.dotsettings. +4830.80 4837.12 "Анатолий Кулаков" Вот dotsettings, это и есть те файлики, которые создает ReSharper для того, чтобы доставить какие-то там свои настройки. +4837.12 4841.68 "Анатолий Кулаков" И это гораздо более гибкий и мощный механизм, чем Editor-Config. +4841.68 4852.44 "Анатолий Кулаков" Но в Editor-Config есть преимущество в том, что он cross-EDE-шный, а dotsettings - это штуки чисто JetBrains, поэтому никто, кроме JetBrains их не понимает, но зато они более мощные. +4852.44 4869.92 "Анатолий Кулаков" У JetBrains'ких tools есть такая прекрасная штука, как слоеные настройки, когда вы можете этих dotsettings наделать сколько угодно, разложить их по папочкам, заинклюдить там друг друга и, соответственно, сделать какой-то dotsettings, который шарится между всей командой. +4869.92 4877.36 "Анатолий Кулаков" И сохранить его в отдельный файлик, и вот этот dotsettings, который шарится между всей командой, естественно, тоже должен быть в репозитории. +4877.36 4878.36 "Анатолий Кулаков" Там ему самое место. +4878.36 4880.36 "Анатолий Кулаков" Так, переходим дальше. +4880.36 4889.52 "Анатолий Кулаков" Теперь мы договорились о каких-то настройках, законфигурировали, чтобы они у нас где-то хранились, как мы, собственно, будем применять форматирование. +4889.52 4899.52 "Анатолий Кулаков" Есть такой процесс, который называется CodeCleanup, и подразумевает, что код каким-то образом чистится в соответствии с теми настройками, которые находит этот инструмент. +4899.52 4903.24 "Анатолий Кулаков" Что здесь стоит сказать? +4903.24 4917.28 "Анатолий Кулаков" Так как CodeCleanup обычно выполняется автоматически, то есть не хочется, чтобы человек смотрел и сравнивал, а что там, собственно, нужно закленапить, как там что-то нужно выровнять, обычно так не делается. +4917.28 4922.68 "Анатолий Кулаков" Обычно просто запускается автоматический Cleanup, он проходится по всем файлам, и все файлы выравниваются, чтобы были все равны. +4922.68 4929.44 "Анатолий Кулаков" Поэтому, тут встает хороший вопрос, а что включать в CodeCleanup, а что включать не стоит? +4929.44 4933.12 "Анатолий Кулаков" То есть какие форматоры, какие фиксеры нужно включать? +4933.12 4935.52 "Анатолий Кулаков" В общем, критерий довольно простой. +4935.52 4939.20 "Анатолий Кулаков" Стоит включать те фиксеры, которые 100% не дадут вам ошибок. +4939.20 4945.68 "Анатолий Кулаков" Ну, например, есть фиксер, который говорит, на каких строчках должны расставляться скобочки фигурные. +4945.68 4955.24 "Анатолий Кулаков" Договорились вы в компании, что фигурные скобочки расставляются там каждая на своей отдельной строке, и они обязательны для любого стейтмена, ну и все, и это можно применить автоматически, никаких проблем с этим не будет. +4955.24 4960.12 "Анатолий Кулаков" А есть код-фиксер, который, например, проставляет ReadOnly в вашем приватном поле. +4960.12 4965.80 "Анатолий Кулаков" И этот код-фиксер может быть очень опасным, особенно если вы случайно проставите ReadOnly к какой-нибудь структурке. +4965.80 4975.64 "Анатолий Кулаков" И это может привести к очень большим багам, и притом багам неочевидным, которые можно поймать только по утечке ресурсов, профайлером и так далее. +4975.64 4983.96 "Анатолий Кулаков" В общем, такие фиксеры в Cleanup включать нельзя, потому что вы можете поймать очень много проблем с ними. +4983.96 4991.06 "Анатолий Кулаков" Вот на вот эти два набора вам и стоит разделить код-Cleanup, который можно применять автоматически, и который автоматически примерять не стоит. +4991.06 4997.96 "Анатолий Кулаков" Также, когда вы запускаете код-Cleanup, у вас должна быть 100% гарантия, что там будет все хорошо. +4997.96 5000.36 "Анатолий Кулаков" Вот почему мы должны выбирать именно правильные фиксеры. +5000.36 5010.72 "Анатолий Кулаков" Поэтому любой член команды должен запускать код-Cleanup без всяких там ручных галочек, без каких-нибудь там хаков, и при этом он не должен бояться, что что-то сломается. +5010.72 5015.12 "Анатолий Кулаков" Он должен уверенно, всегда, без всяких проблем запускать свой код-Cleanup. +5015.12 5020.68 "Анатолий Кулаков" Поэтому к настройке вот этого нужно подойти довольно таки хорошо и тщательно. +5020.68 5021.68 "Анатолий Кулаков" Инструменты. +5021.68 5035.28 "Анатолий Кулаков" Visual Studio, прежде всего, она поддерживает код-Cleanup, но, к сожалению, у нее нет возможности сохранить тот профиль, который вы наконфигурировали, сохранить его в виде какого-то отдельного файлика для того, чтобы закинуть Source Control. +5035.28 5038.56 "Анатолий Кулаков" В общем, почему-то они это не сделали. +5038.56 5049.92 "Анатолий Кулаков" А это ключевой момент, потому что те фиксеры, тот Cleanup, тот вид кода, который должен быть у вашего приложения, его должны использовать абсолютно все члены команды. +5049.92 5052.28 "Анатолий Кулаков" Они должны использовать один и тот же профиль. +5052.28 5056.96 "Анатолий Кулаков" Не бывает такого, что каждый настраивает, как хочет, и потом все вместе пытаются дело смешать. +5056.96 5072.80 "Анатолий Кулаков" У JetBrains, у райдера в частности, дела намного лучше, потому что он позволяет сохранить все настройки код-Cleanup в тот самый settings-слоеный файлик, который, естественно, можно расшарить между командой и залить в репозиторий. +5072.80 5081.56 "Анатолий Кулаков" Также райдер позволяет автоматически запускать код-Cleanup, например, перед каждым коммитом, что тоже бывает довольно удобно. +5081.56 5088.72 "Анатолий Кулаков" Но UGL все-таки настаивает, что решение должно быть не привязано к конкретному вендору. +5088.72 5096.40 "Анатолий Кулаков" Они пользуются и тем, и тем, но желательно, конечно, найти какое-то решение, которое бы не зависело от конкретного вендора. +5096.40 5099.44 "Анатолий Кулаков" Тут мы, к сожалению, сейчас ничего не можем предложить. +5099.44 5106.56 "Анатолий Кулаков" У нас есть или решение от Microsoft, или решение от JetBrains, и у каждого есть свои плюсы и минусы. +5106.56 5110.92 "Анатолий Кулаков" Так, давайте теперь посмотрим на сам процесс, на как же собственно команде с этим совсем работать. +5110.92 5131.32 "Анатолий Кулаков" Ну, прежде всего нужно понимать, что если вы слишком сильно затянете гайки, например, ограничите количество пробельщиков, которые у вас может в коде быть, то это приведет к тому, что при каждой проверке, при каждом комите, у вас будет очень много ошибок. +5131.32 5139.48 "Анатолий Кулаков" То есть вам будет какой-нибудь анализатор, какой-нибудь форматор сообщать, что вот смотри, ты тут не тот пробельщик поставил, подсмотри, ты тут форматирование не так красиво сделал, как могло бы быть. +5139.48 5144.20 "Анатолий Кулаков" И, в общем, это все вернет, ведет к деградации производительности именно разработчиков самих. +5144.20 5153.96 "Анатолий Кулаков" А тут нужно понимать, что, в принципе, кодстайл и форматинг, они не призваны к тому, чтобы ухудшить продуктивность разработчиков. +5153.96 5155.76 "Анатолий Кулаков" Наоборот, они хотят ее улучшить. +5155.76 5168.16 "Анатолий Кулаков" В общем, здесь вам как раз нужно соблюсти баланс, потому что если вы сделаете слишком строгие правила, вот этого будут страдать разработчики, а если сделаете слишком слабые правила, то от этого будет страдать код. +5168.16 5169.76 "Анатолий Кулаков" То есть у вас код уже не будет таким консистентным. +5169.76 5173.24 "Анатолий Кулаков" И вот выбор этого баланса – это задача каждой конкретной команды. +5173.24 5178.62 "Анатолий Кулаков" Гаэль со стороны команды может бросить несколько советов. +5178.62 5187.62 "Анатолий Кулаков" Прежде всего, выставляйте уровень анализов, кодстайл анализов в ворнинг. +5187.62 5195.18 "Анатолий Кулаков" Это тоже можно регламентировать, какой анализ, какой уровень вам предупреждения выдаст. +5195.18 5199.66 "Анатолий Кулаков" Он говорит, что ворнинг – это то, что команда обязана соблюдать. +5199.66 5201.22 "Анатолий Кулаков" То, через что переступить нельзя. +5201.22 5211.86 "Анатолий Кулаков" Далее, убедитесь, что вы проверяете код анализ при каждом билде. +5211.86 5214.54 "Анатолий Кулаков" То есть вы проводите код анализ при каждом билде. +5214.54 5228.34 "Анатолий Кулаков" Для этого достаточно выставить свойство, которое называется «Enforced code style in build» в директоре buildprops, то есть это стандартная мс-билдовская настроечка, которая вам как раз будет этот анализ проводить. +5228.34 5239.82 "Анатолий Кулаков" Еще один интересный момент, что в команде металлама позволяется допускать ворнинги на машине разработчика. +5239.82 5250.68 "Анатолий Кулаков" На машине разработчика, пока разработчик не дописал код, и он хочет просто-напросто запустить тест или еще что-то, нет никакого смысла обламывать ему компиляцию. +5250.68 5253.30 "Анатолий Кулаков" Поэтому ворнинги на машине разработчика вполне допустимы. +5253.30 5255.16 "Анатолий Кулаков" С этим проблем нет никаких. +5255.16 5264.20 "Анатолий Кулаков" Но вот на CI-системе у них выставлен флаг «Thread warnings as errors», то есть на CI-системе любой ворнинг приводит к ошибкам. +5264.20 5274.52 "Анатолий Кулаков" Чтобы задетектировать ситуацию, когда ваш мс-билд скрипт запускается на CI-системе, есть прекрасное свойство, которое называется «Continuous integration build». +5274.52 5276.96 "Анатолий Кулаков" Оно может иметь значение true или false. +5276.96 5288.00 "Анатолий Кулаков" Интересное значение, то есть интересное свойство, я почему-то раньше на него внимания не обращал, я знал, что каждая система выставляет, каждая CI-система выставляет какие-то свои настройки окружения, в общем. +5288.00 5294.00 "Анатолий Кулаков" А тут появилось такое универсальное, которое само я так понимаю анализирует все эти настройки и выводит вам в каком-то одном предсказуемой свойстве. +5294.00 5295.52 "Анатолий Кулаков" В общем, тоже полезная штука. +5295.52 5302.24 "Анатолий Кулаков" Далее, из советов, включите различные код-анализы. +5302.24 5307.84 "Анатолий Кулаков" Для этого есть специальная статейка от Microsoft, которая называется «Обзор.NET Source код-анализов». +5307.84 5315.02 "Анатолий Кулаков" Там рассказывается, какие код-анализы есть, как их включить, что они там красиво ищут, ну в общем, это стандартные вот эти розлиновские подсказы-возвращенники. +5315.02 5318.44 "Анатолий Кулаков" Такие умные, хорошие, прям некоторые из них просто must-have. +5318.44 5321.00 "Анатолий Кулаков" Поэтому можно не пренебрегать чистой совестью. +5321.00 5329.94 "Анатолий Кулаков" Также Metalama Team использует StyleCop, который сейчас интегрирован прям в розлин-компайлер и является частью C#-компилятора. +5329.94 5338.88 "Анатолий Кулаков" Так, теперь насчет того, а когда же нужно все-таки применять Clion App и как с этим поступать. +5338.88 5347.00 "Анатолий Кулаков" В общем, Гаэль говорит, что, в принципе, погоня за тем, чтобы каждый pull-request был идеально отформатирован, она бессмысленна. +5347.00 5352.04 "Анатолий Кулаков" И поэтому в каждом pull-request они такую проверку не вставляют. +5352.04 5358.68 "Анатолий Кулаков" И при этом со временем у них набирается, соответственно, вот этот, грубо говоря, технический долг по форматированию. +5358.68 5362.20 "Анатолий Кулаков" То есть у них код не всегда идеально отформатирован. +5362.20 5380.24 "Анатолий Кулаков" И они раз в какой-то промежуток времени, то есть в их случае перед фризом майлстоуна, это происходит где-то в 6-12 недель, они запускают полный код Clion App и преобразуют всю их кодовую базу к красивому, понятному виду. +5380.24 5382.48 "Анатолий Кулаков" Не знаю, я этого аргумента, если честно, не понял. +5382.48 5391.80 "Анатолий Кулаков" То есть намного легче, кажется, и соответствует всем признакам того, что Гаэль говорил вначале, намного легче перед каждым pull-request заставлять форматировать код правильно. +5391.80 5399.88 "Анатолий Кулаков" И тогда у вас в репозитории будет вливаться красивый код, в pull-requests и в merge-requests будет красивый код, и другие разработчики будут ревьюить красивый код. +5399.88 5403.04 "Анатолий Кулаков" Никакого смысла допускать это раз в 12 недель, вообще никакого нет. +5403.04 5404.04 "Анатолий Кулаков" Поэтому не знаю. +5404.04 5412.80 "Анатолий Кулаков" На своей практике мы перед, то есть у нас проверка на соответствие эдитер-конфигу, она запускается на каждый билд, на каждый merge-request. +5412.80 5416.76 "Анатолий Кулаков" То есть вы не можете в мастер залить код, который плохо отформатирован. +5416.76 5419.04 "Анатолий Кулаков" И минусов этого подхода я не вижу. +5419.04 5434.00 "Анатолий Кулаков" Так, следующий момент, он повторяется, что запуск клеонап-тулза должен быть полностью предсказуемый, не должен доставлять каких-то неудобств неразработчикам, не должен вводить в ступор ревьюеров, ничего. +5434.00 5438.48 "Анатолий Кулаков" Он должен строго красиво отрабатывать и делать предсказуемые вещи. +5438.48 5444.28 "Анатолий Кулаков" Для того, чтобы так можно было делать, нам нужен клеонап на основании каких-то настроек. +5444.28 5456.32 "Анатолий Кулаков" У нас из инструментов, из инструментов для того, чтобы это делать, например, на Continuous Integration Server, нам нужен какой-то инструмент, который не зависит от локального и локального энвариомента разработчика. +5456.32 5465.56 "Анатолий Кулаков" Прежде всего, это .NET-формат, это консольная утилитка, которая форматирует ваш код в зависимости от того, что написано в Editor Config. +5465.56 5479.16 "Анатолий Кулаков" Это сейчас самая стандартная, самая полная, самая красивая из всех .NET-утилиток, которые есть, поддерживается она непосредственно Microsoft, и поэтому, как минимум, вы должны поддерживать ее. +5479.16 5485.60 "Анатолий Кулаков" То есть как минимум она прекрасна, она хороша, и она понимает хотя бы базовые вещи Editor Config. +5485.60 5490.04 "Анатолий Кулаков" Огромным ее минусом является то, что понимает она не все. +5490.04 5494.24 "Анатолий Кулаков" Понимает она даже, честно сказать, мало, поэтому все с помощью нее отформатировать невозможно. +5494.24 5508.68 "Анатолий Кулаков" На помощь приходит JetBrains, ну кроме того, что у JetBrains есть интерактивный клеонап, который может воспользоваться каждый разработчик, опять же, нас больше интересует автоматизированность системы, и есть такой прекрасный инструмент, который называется ReSharper Kleonap Command Line Tool. +5508.68 5518.36 "Анатолий Кулаков" Это тоже консольная утилита, которая понимает .settings файлы, в которых можно сохранить намного больше настроек, и с помощью которых вы можете автоматически тоже все форматировать. +5518.36 5540.16 "Анатолий Кулаков" И теперь, чтобы этот формат тоже был более-менее предсказуемый на каждой машине, потому что что ReSharper-овская утилита, что .NET-формат, они имеют кучу настроек, и в зависимости от того, какие настройки вы туда передадите, по каким путям найдутся файлы конфигурации, опять же, формат может отличаться. +5540.16 5549.44 "Анатолий Кулаков" Поэтому рекомендуется сделать какой-то предсказуемый скрипт, и в этом скрипте заполнить, записать все точные параметры, с помощью которых должны запускаться эти утилиты. +5549.44 5552.32 "Анатолий Кулаков" Может быть, даже не одна утилита, а несколько утилит. +5552.32 5561.48 "Анатолий Кулаков" Чтобы, несмотря на то, где этот скрипт запущен, у локального разработчика или на CI-системе, он всегда стабильно выдавал один и тот же результат. +5561.48 5563.96 "Анатолий Кулаков" Поэтому все это нужно сделать именно так. +5563.96 5584.96 "Анатолий Кулаков" Это базовые вещи, которые просто обязаны быть в любом проекте, но если вы их вдруг здесь сделали, то если они у вас есть, то вы большой молодец, но если вы хотите пойти дальше, то можно вернуться, то есть можно уже углубиться в какие-то более интересные аспекты, которые также можно отнести к качеству кода. +5584.96 5603.80 "Анатолий Кулаков" Ну, например, можно проверять, что если у вас есть интерфейс iFactory, то все классы, пронаследованные от этого интерфейса iFactory обязаны заканчиваться на слово "factory", или более ближе, наверное, к каждому разработчику, это все, что пронаследовано от атрибута, от системы атрибут, должно заканчиваться на слово "атрибут". +5603.80 5606.76 "Анатолий Кулаков" То есть вот такие вещи, если вы хотите поддерживать в своем проекте. +5606.76 5625.56 "Анатолий Кулаков" Ну или что-то более сложное, например, если у вас есть неймспейс биллинга, то в этом неймспейсе никогда не должны использоваться даблы, потому что любые там деньги мы подразумеваем, что в биллинге должны обрабатываться с помощью интов или с помощью децималов. +5625.56 5634.08 "Анатолий Кулаков" Такие условия тоже можно писать, их можно проверять, но это уже не обойтись нам какими-то простыми средствами, которые чисто для кодформатирования придуманы. +5634.08 5636.64 "Анатолий Кулаков" Есть более интересные, более глубокие средства. +5636.64 5639.04 "Анатолий Кулаков" Во-первых, это архитектурные тесты. +5639.04 5648.88 "Анатолий Кулаков" Кстати, если вам интересно поговорить про архитектурные тесты, обязательно напишите нам в комментариях, у нас лежит статьечка про них, мы давно ждем какого-нибудь хорошего повода. +5648.88 5656.20 "Анатолий Кулаков" Ну и второй инструмент, который Каэль не мог не предложить, это металлама, который мы как раз-таки сами обсуждали. +5656.20 5664.80 "Анатолий Кулаков" То есть с помощью аспектно-ориентированных вот этих навешанных атрибутов мы можем сделать все вот эти проверки, ну и даже больше, как Игорь упоминал в предыдущей статье. +5664.80 5681.16 "Анатолий Кулаков" В общем, вот такое развитие, вот такие базовые инструменты, поэтому если вдруг вы нашли что-то интересное, какие-то интересные анализаторы техники, которые у вас еще не применяются, рассмотрите возможность, потому что никогда не бывает мало красивого кода, красивый код должен быть всегда много и стандартный между всей командой. +5681.16 5697.40 "Игорь Лабутин" Да, прикольно, ну иметь такой максимально автоматизированный способ поддерживать кодовую базу в нормальном состоянии, это самое, да, наверное, довольно сложно, чтобы его внедрить, ну потому что надо всем договориться, но зато потом жить проще. +5697.40 5698.40 "Игорь Лабутин" Проверено. +5698.40 5709.08 "Анатолий Кулаков" Ну да, особенно прекрасно, когда вы начинаете его внедрять прямо в новом проекте, когда ни о чем договариваться, там ничего переписывать не надо, договариваться все равно придется, переписывать ничего не надо, это самый большой бич. +5709.08 5731.08 "Игорь Лабутин" С этим старым проектом, как правило, в общем, включаете анализаторы, фиксите какое-то ограниченное время, максимальное количество самых явных проблем, так скажем, и дальше потихонечку включаете, все больше и больше, потихонечку дофикшивая, инкрементно, не спеша, ну или наоборот поспешает, в зависимости от того, сколько у вас времени и команды есть. +5731.08 5732.08 "Игорь Лабутин" Ну чё, давай дальше. +5732.08 5733.08 "Игорь Лабутин" Еще, да? +5733.08 5734.08 "Игорь Лабутин" Еще хотите? +5734.08 5735.08 "Игорь Лабутин" Мало? +5735.08 5741.28 "Игорь Лабутин" Давай, давай, да, мы же это до 2 часов должны добить, мы же собирались писать выпуск на 1 час. +5741.28 5747.92 "Анатолий Кулаков" Да, мы собирались записать коротенький выпуск, что получится, ну уже понятно, что получится, поэтому давай во все чашки, что что. +5747.92 5788.20 "Анатолий Кулаков" Ладно, небольшие вбросы от Фил Хака, как бы не мог пропустить, потому что Фил Хак пишет довольно редко, не знаю, год назад у него последний раз в блокпост выходил, и в принципе, хорошую тему он поднял, он написал в своем твите следующую штуку, что это в принципе не самая великолепная аналогия, но все-таки попробуйте поразмыслить, что Aspire, ну как вы могли выпуск без Aspire сделать, правда же, Aspire, Aspire это как Nuget, только для облачных сервисов, то есть когда мы делали Nuget, наша задача была, это как можно проще затаскивать к себе различные библиотеки, различные зависимости в наших проектах. +5788.60 5838.76 "Анатолий Кулаков" Ну и до того, как появился Nuget, слишком много это нам приносило неудобств и боли, потому что нам нужно было их как-то найти, определить, какой версии мы хотим, как-то затащить свой проект, как-то их где-то прописать, что делает сейчас Nuget автоматически, мы даже об этом не задумываемся, мы не понимаем, на какой огромный пласт сложности он нас убирает, и в наше время как раз мы сталкиваемся почти с такой же точной проблемой, у нас есть Postgres, у нас есть RabbitMQ, у нас есть всякие Kafka, всякие memcache, и все это точно такие же сервисы, которые нужны нашему приложению в качестве зависимости, и мы точно так же должны понять, откуда мы их возьмем, о какой версии, а как мы их к себе притащим, а как сконфигурируем, и в принципе те же самые задачи, но просто немножко на другом уровне перед нами стоят. +5838.76 5841.56 "Анатолий Кулаков" Разберемся с этой мыслью. +5841.56 5842.72 "Анатолий Кулаков" Зачем придумался Nuget? +5842.72 5858.12 "Анатолий Кулаков" В общем, если мы почитаем там первые постулаты, зачем был нужен Nuget, то, как я уже упоминал, у нас была большой комьюнити, в котором было много библиотек, и среди этих библиотек ориентироваться было довольно-таки сложно. +5858.12 5881.56 "Анатолий Кулаков" Неизвестно, кто был в каком состоянии, через как он распространялся, как его в конце концов было заподключить в свой проект, и где его найти, и как с этим проектом его потом таскать, эти библиотеки, в общем, все те проблемы, которые очень хорошо будут вам видны, если вы сходите в какой-нибудь язык, в котором до сих пор проблемы с такими системами контроля версий. +5881.56 5889.00 "Анатолий Кулаков" Допустим, у C до последних времен были очень большие проблемы, а сейчас средние проблемы с этим. +5889.00 5899.48 "Анатолий Кулаков" Ну, то есть, представляете, самый, наверное, древний из мейнстримовых языков до сих пор не обзавелся системой наподобие Nuget, системой, которая управляет его пакетами. +5899.48 5909.48 "Анатолий Кулаков" И там люди довольно страдают, вплоть до того, что передают друг другу DLL в виде zip архивчиков и каким-то образом версионируют их по-старинке. +5909.48 5927.72 "Анатолий Кулаков" В общем, Nuget сделал для нас огромный шаг вперед, то есть он уменьшил количество тех операций, которые нам необходимы для того, чтобы было найти пакет, установить его и вместе с проектом каким-то образом сопровождать, обновлять и так далее. +5927.72 5963.00 "Анатолий Кулаков" И что немаловажно, Nuget все это сделал абсолютно бесшовно, то есть мы получили очень хороший опыт нового разработчика, когда он может склонировать просто репозиторий из нашего центрального хранилища, нажать F5 и у себя локально этот проект запустить, не загоняясь о том, что под капотом там происходит .NET restore, который лезет где-то, достает актуальные версии библиотек, который их куда-то подключает, как-то складывает, где-то копирует, разрешает конфликты, в общем, под капотом там творится очень много сложной магии, сложной операции. +5963.00 5969.96 "Анатолий Кулаков" Для обычного разработчика ты склонировал, нажал F5, проект у тебя запустился и этот опыт очень дорогого стоит. +5969.96 5979.32 "Анатолий Кулаков" И теперь если мы взглянем на наши облачные сервисы, которыми нас со всех сторон пытаются окутать, то там же происходит такая же точная ситуация. +5979.32 5986.80 "Анатолий Кулаков" У нас есть зависимости у нашего проекта и эти зависимости обычно от каких-то других сервисов, которые есть. +5986.80 6002.56 "Анатолий Кулаков" Уже просто так нельзя, мы не можем уже просто так взять и запустить наш проект с помощью F5, мы обязательно требуем какую-то базу данных, может быть какой-то кэш, может быть какую-то очередь, без этого наш сервис может быть не стартануть, а если в хорошем случае он и стартанет, то работать он точно не будет. +6002.56 6017.64 "Анатолий Кулаков" И .NET expire здесь очень похож на Nuget, вот в .NET expire как раз и входит задача уменьшить количество тех шагов, которые нам нужны для того, чтобы добавить, для того, чтобы внедрить вот эти клауд сервисы, облачные сервисы в наше приложение. +6017.64 6026.40 "Анатолий Кулаков" Но в отличие от обычных библиотек, с которыми работает Nuget, у облачных сервисов гораздо больше различных требований. +6026.40 6034.56 "Анатолий Кулаков" Их нужно каким-то образом настроить, их нужно каким-то образом задеплойить, их нужно каким-то образом мониторить. +6034.56 6038.92 "Анатолий Кулаков" В общем, там стоит намного больше задач, чем стояло перед Nuget. +6038.92 6047.92 "Анатолий Кулаков" Или, допустим, если мы берем connection string, то их нужно каким-то образом пробросить между сервисами, и желательно все это сделать безопасно, чтобы никакие лишние пароли никуда не утекли. +6047.92 6054.92 "Анатолий Кулаков" И expire как раз и позволяет это все делать, он как раз и призван нам для того, чтобы упростить все эти точки. +6054.92 6063.44 "Анатолий Кулаков" Он знает, откуда затянуть, он знает, как настроить, он знает, как отмониторить, как вам даже это показать в красивом дашборде, и даже пытается как-то дружить с секьюрити. +6064.04 6070.68 "Анатолий Кулаков" Поэтому он примерно эти вещи и решает, но только для веб-сервисов. +6070.68 6082.04 "Анатолий Кулаков" В комментариях тут же набежала куча народу и сказали, что в принципе есть какое-то сходство, но вам не кажется, дорогой сударь, что это больше не про expire, а про докер? +6082.04 6114.12 "Анатолий Кулаков" Ведь это именно докер позволяет нам хорошо упаковать сервисы, как упакуются Nuget пакеты, и именно докер позволяет вам локально это все запустить, как делается локальный дотнет рестор, и в принципе докер - это ключевая технология, которая должна ассоциироваться с Nuget, но ни разу не expire, на что в принципе Фил Хак резонно заявляет, что докер - это всего лишь навсего формат хранения, как для Nuget формат хранения - это zip. +6114.12 6115.12 "Анатолий Кулаков" Хороши ли zip архивы? +6115.12 6116.12 "Анатолий Кулаков" Да, хороши. +6116.12 6120.76 "Анатолий Кулаков" Позволили ли нам в виде одного красивого файлика доставлять любые данные на клиента? +6120.76 6121.76 "Анатолий Кулаков" Да, позволили. +6121.76 6122.76 "Анатолий Кулаков" А упаковать локально? +6122.76 6123.76 "Анатолий Кулаков" Да, тоже позволили. +6123.76 6125.88 "Анатолий Кулаков" Но все-таки Nuget - это нечто большее. +6125.88 6129.36 "Анатолий Кулаков" Так же точно и expire - это нечто большее над обычным докером. +6129.36 6141.08 "Анатолий Кулаков" Это то, что вам как раз делает провиженинг, конфигурацию, диплоймент, какой-нибудь security management, сервис-дискавери, вот это вам все делает именно expire, и докер этого из коробки сделать не может. +6141.08 6151.52 "Анатолий Кулаков" Поэтому у expire намного больше преимуществ для того, чтобы вот этот workflow заклонировал и запустил, сделать реальным на локальном компьютере. +6151.52 6154.08 "Анатолий Кулаков" Больший преимуществ, чем у простого докера. +6154.08 6163.72 "Анатолий Кулаков" У простого докера с этим будет намного больше проблем, а у expire все-таки мы можем получить тот долгожданный экспириенс, когда мы заклонировали репозиторий, нажали в пять и у нас все работает. +6163.72 6172.52 "Анатолий Кулаков" Но теперь оно работает не просто так, не просто потому что есть какие-то зависимости, а еще он и эти зависимости к себе подтаскивает. +6172.52 6177.56 "Анатолий Кулаков" Подтаскивает, обновляет, мигрирует, связывает друг с другом и показывает в удобном дэшбарде. +6177.56 6184.68 "Анатолий Кулаков" И вот этот экспириенс, когда заклонировал и запустил, вот этот наброс возвращается даже в наших самых сложных приложениях, которые только можно было придумать. +6184.68 6197.36 "Анатолий Кулаков" Вот такой интересный наброс, в общем, поэтому, может, когда вы в следующий раз будете смотреть на expire или объяснять кому-то, что такое expire, аналогия, что это nuget для облачных сервисов, будет для вас близка. +6197.36 6218.88 "Игорь Лабутин" Ну да, и посмотрим, куда подвинется expire, потому что у нас был в каком-то из чатиков ссылочка на отдельный сайт под названием expire-dashboard.com, где прям вообще такой супер модный сайт, супер рекламирующий этот самый expire, ну для программистов рекламирующий, понятное дело. +6218.88 6226.24 "Игорь Лабутин" Со всякими трейсами, там open telemetry, примеры кода на питончике, на джаве, на джава скрипте, на c-шарпе, в общем, прям это очень классно выглядит. +6226.24 6236.48 "Анатолий Кулаков" Ну да, знатный сайт, прям, который видно, что продает отдельный продукт expire-dashboard, ну как продает, он, естественно, фришный, но заставляет задуматься, не хотите ли вы его завязать. +6236.48 6243.96 "Игорь Лабутин" Поэтому, да, хорошо, что… Да, то есть именно прям вот видно, что дешборд они как-то отдельно продвигают и показывают. +6243.96 6259.00 "Игорь Лабутин" А вторая половинка, это вот тот самый provisioning, который уже делается, если вы полноценно тащите expire в важный проект, он тогда, да, позволяет вам всё это дело запровиженить и удобно использовать. +6259.00 6264.04 "Игорь Лабутин" Ну и хорошо, давай мы будем потихонечку загругляться. +6264.04 6271.76 "Игорь Лабутин" В этот раз есть только одна новость из кратко о разном, это про .NET Eventing Framework. +6271.76 6383.80 "Игорь Лабутин" Если вы помните, наверное, месяца два назад, может быть три, я упоминал про то, что в гитхабе Майкрософта появилась ишью, по-моему, в рантайм, нет, наверное, не в рантайм, там, где, короче, библиотечки живут, репозитории, появилась ишью, которая называлась .NET Eventing Framework, туда набежала куча народу, про то, что ой, всё, вы сейчас убьёте, всё, значит, так сказать, стороннее open-source ПО вокруг ивентинга, то есть все какие-то мастранзиты и сервисбас больше будут не нужны, и Майкрософт напишет свой ивентинг фреймворк, причём, ну, были те, кто вот так вот с этой стороны жаловался, были те, кто говорили, наконец-то, нормальный ивентинг фреймворк от .NET, выкинем нафиг мастранзиты, сервисбасы, всё, ну, в общем, как обычно, все разделились на несколько лагерей, при том, что Майкрософт это всё говорил, да ладно вам, что вы это, мы только делаем там для Azure Functions и вебджобов, как бы узкая нишевая штука, ну, назвали, как бы, ивентинг фреймворк, ну, на самом деле это, типа, только для конкретного юзкейса, вот, но в результате там ишьи, по-моему, обсуждения идут до сих пор, не помню, сколько там, сотен комментариев уже, но смысл в том, что вот буквально недавно Майкрософт таки сказали, Фаулер, Дэвид Фаулер написал в этой ишьи, что мол, не, значит, мы комьюнити услышали, никаких, по крайней мере, в девятом .NET ивентинг фреймворка не будет и что мы будем использовать, так сказать, open design process for future version, то есть они не отказываются от идеи сделать какой-то ивентинг фреймворк, но судя по тому, что они будут использовать, так сказать, engage-ить весь open source комьюнити в то, чтобы с правильной фреймворкой дизайнить, таки, видимо, там всё-таки должен был получиться какой-то чуть более глобальный ивентинг фреймворк, чем просто для Ажура, но вот посмотрим, будет ли нас с заменой масс-транзита и энд-сервис баса, но, видимо, уже в тот на десять дней раньше. +6383.80 6402.20 "Анатолий Кулаков" Слушай, ну обидно, обидно, я как раз из тех, кто хотел бы всё-таки получить какой-то стандарт ивентинга, потому что сейчас задолбали как бы изобретать какие-то убогие колечные консюмеры, очень не хватает, не хватает такого же вот, как мы сделали для контроллеров, какой-то стандарта, вот такого же нужно для ивентинга. +6402.20 6409.40 "Игорь Лабутин" Ну посмотрим, может, что и сотворят, и неплохое, и в сообществе с open-source будет даже как-то совместимо. +6409.40 6419.80 "Игорь Лабутин" По большому счёту же им нужно сделать что-то а-ля iLogger, то есть какой-то как бы интерфейс, им не обязательно делать реализацию в целом, а дальше все остальные подстроятся. +6419.80 6424.08 "Игорь Лабутин" Ты же используешь Serilog в качестве как бы подкладки под iLogger реализации? +6424.08 6434.20 "Анатолий Кулаков" Да, да, но это, наверное, единственное, что выжило после всех контейнеров, после всех логеров, после всех тех же самых minimal API, Serilog единственный, кто выжил. +6434.20 6435.20 "Анатолий Кулаков" Ну вот посмотрим. +6435.20 6436.20 "Анатолий Кулаков" Поэтому не зарекайся. +6436.20 6438.08 "Анатолий Кулаков" Ну глянем, что будет. +6438.08 6444.00 "Анатолий Кулаков" Ну ладно, давай закругляться, вроде уложились, пусть не в 1 часик, но в 2. +6444.00 6474.16 "Игорь Лабутин" Ну в 2, я надеюсь, мы уложились, судя по таймеру, да, миграции в коре обсудили, параметры маршрутов в спин-энд-коре пошифровали, металаму как замена постшарпа обсудили, как писать код, чтобы было удобно и стильно, так скажем, в едином стиле тоже обсудили, подумали, может ли Aspire быть новым Nuget в каком-то смысле для клауда, ну и вендинг фреймворка не будет выделять на дотнете, может хорошо, может плохо, посмотрим. +6474.16 6476.36 "Анатолий Кулаков" Ну или в каком-то обрезанном виде, может быть. +6476.36 6486.56 "Игорь Лабутин" Ну может что успеют придумать, но я думаю, что если они сказали, что типа нет, будет у нас open design процесс, я думаю, что этот open design процесс займет там месяцы, вряд ли они что-то успеют сделать, лишь бы. +6486.56 6488.20 "Анатолий Кулаков" Ну ладно, зато нам будет много новостей. +6488.20 6489.96 "Игорь Лабутин" Лишь бы что-нибудь сделали, да. +6489.96 6495.44 "Игорь Лабутин" Ну чё, на этом всё, 96 выпуск заканчивается, всем спасибо. +6495.44 6506.06 "Анатолий Кулаков" Всем счастливо, всем пока, заставляйте комментарии, рассказывайте друзьям, если вы хотите, чтоб в вашей чатике бросали ссылки на Aspire Dashboard, то добавляйтесь к нам на Boosty, там много всего интересного. +6506.06 6507.06 "Анатолий Кулаков" До новых встреч, пока! +6507.06 6507.56 "Игорь Лабутин" Пока.