Обновить
128K+

.NET *

Хаб со знаниями про .NET

87,42
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

Avalonia UI и Linux Embedded: делаем Grafana-дашборд на старом Raspberry Pi и древнем 32-битном OrangePi

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели5.2K

В этой статье расскажем, как сделали информационную панель для офиса. Мы написали приложение на Avalonia UI, которое забирает данные из Grafana через REST API и рисует их напрямую, а затем запустили его на старых одноплатных компьютерах — без браузера, рабочего стола и оконного менеджера.

Читать далее

Новости

Native AOT заставил меня переписать весь .NET проект

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели10K

Мне хотелось, чтобы знакомство с HydraScript выглядело просто: скачал интерпретатор, запустил скрипт. Сомнительно предлагать человеку сначала установить подходящий .NET Runtime ради моего языка программирования.

Переход на Native AOT поначалу казался правкой .csproj. Включил настройку, опубликовал бинарник, пошёл дальше. На практике пришлось переписать всё. Досталось даже интеграционным тестам. А в процессе рефакторинга ещё и пропали логи.

Читать далее

Redis в маршрутах.NET: кэш, Pub/Sub, Streams с группами и Claim Check одним коннектором

Уровень сложностиСложный
Время на прочтение9 мин
Охват и читатели9.8K

Коннектор Redis для redb.Route: все структуры данных как шаги маршрута, Pub/Sub, Streams с группами потребителей, список как очередь и Claim Check на Redis.

В интеграционном проекте Redis редко бывает чем-то одним. Это кэш ответов внешних систем, счётчики и блокировки, шина событий через Pub/Sub, журнал сообщений через Streams, очередь задач на списке. Обычно каждая из этих ролей живёт в своём куске кода со своим подключением, своими повторами и своим логированием.

В redb.Route все они собраны в одном коннекторе redb.Route.Redis. Любая операция Redis становится шагом маршрута, а подписка, стрим или список становятся его входом. Подключение, телеметрия и плавная остановка при этом общие с остальными коннекторами. Под капотом StackExchange.Redis 2.11.8.

Потребители Redis описаны здесь начиная с ...

Читать далее

Почему "+=" сложнее реализовать, чем "+": опыт HydraScript

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели12K

Мой язык программирования HydraScript, написанный на C#, уже умел выполнять такой код:

let x = 10 x = x + 1 >>> x

Получаем 11; >>> — это оператор вывода. Присваивание работает, сложение работает. Захотелось добавить привычное сокращение:

let x = 10 x += 1 >>> x

Результат должен остаться тем же — 11. Зачем учить весь компилятор ещё одной операции, если всё необходимое у него уже есть? Можно прямо в парсере превратить x += 1 в дерево для x = x + 1.

Эта часть уместилась в несколько строк. Основная работа досталась методу Clone().

Читать далее

Blazor против Vue.js: что замечает C#-разработчик

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели10K

Два фронтенда, один C#-мозг — что действительно различается, что похоже сильнее, чем принято считать, и что говорит рынок труда.

До 2019 года моим фронтендом были семантический HTML и CSS. Div'ы, классы, разметка, которую я мог удержать в голове. Я был бэкенд-разработчиком, и меня это вполне устраивало.

Потом случились две вещи. Компания попросила меня залезть в проект на Vue, а Microsoft выпустила Blazor. В следующие годы я плотно поработал с обоими: с Vue — у двух работодателей, с Blazor — на личном проекте, который до сих пор работает.

Это не статья с бенчмарками. Это про то, как эти две технологии ощущаются, когда мышление у тебя C#-овое.

Читать далее

XML‑маршруты в redb.Route: схема в редакторе, проверка на сборке и замена модуля на лету

Уровень сложностиСложный
Время на прочтение18 мин
Охват и читатели7.5K

Маршрут в .route.xml на том же движке, что и C#: подсказки в VS Code, проверка пакета в dotnet build, граф-редактор и горячая замена модуля.

Интеграционный маршрут живёт дольше, чем код вокруг него. Партнёр переезжает в другую папку на SFTP, аналитик просит отдельную ветку под новый тип файла, поддержка хочет понять, каким путём прошла заявка, которую ночью отклонили. Всё это вопросы к маршруту, и отвечать на них через C#-проект, сборку и выкладку модуля выходит дороже, чем сам вопрос.

В 4.0 у redb.Route появилась вторая запись маршрута: XML. Файл .route.xml кладётся в пакет, пакет в папку работающего сервиса, и меньше чем через полсекунды по новому маршруту идёт первое сообщение. При этом ...

Читать далее

Heartbeat: как мы создали систему управления системой вместо обычных сигналов

Время на прочтение13 мин
Охват и читатели7.2K

Привет! Меня зовут Александр Илларионов, я бэкенд‑разработчик в Altenar. Мы работаем на довольно сложном и при этом очень интересном рынке: собираем данные о спортивных матчах со всего мира — например, время и место их проведения, описания чемпионатов и участников, а также вероятности наступления ключевых событий вроде голов, аутов и пенальти. И всё это в live‑режиме. 

В этой статье рассказываю, как мы переосмыслили роль Heartbeat‑компонента в нашей системе — от обычного сигнала до инструмента, который реально управляет работой всей системы. Наш опыт будет полезен тем, кто работает с .NET, распределёнными системами или строит инфраструктуру под высоконагруженные real‑time потоки данных. 

Читать далее

А чё, так можно было? Три места в.NET, которые не развидеть

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели9K

Пустой наследник Random работает медленнее родителя. string[] и object[] оказываются одним объектом. А Matrix4x4 до сих пор держит шестнадцать полей float вместо четырёх векторов.

Ни одно из трёх уже не переделать, и на то есть причины.

Читать далее

А чё, так можно было? Опечатка в исходниках .NET, которой больше 20 лет

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели6.7K

В System.Random кто-то двадцать лет назад написал 21 вместо 31. Опечатку заметили, разобрали и оставили как есть — исправить, и new Random(42) начнёт выдавать другие числа.

А ещё new Random() и new Random(42) — вообще разные генераторы. Разница на некоторых методах доходит до 10 раз.

Читать далее

redb для бизнеса: программируем только бизнес, инфраструктура уже написана

Время на прочтение9 мин
Охват и читатели5.8K

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

12 сентября вышла redb 4.0.0. Четыре продукта экосистемы (хранилище, интеграционный движок, рантайм и сервер идентификации) получили общий мажорный номер: 76 пакетов, внутренний аудит безопасности и сборку на .NET 10, который Microsoft поддерживает до ноября 2028 года. Для инженеров изменения разобраны в отдельной статье. Этот текст для тех, кто решает, на чём строить бэкенд: что экосистема заменяет, во что обходится, какие риски снимает и что важно знать до старта.

Коротко, из чего она состоит:

Читать далее

А чё, так можно было? Три недооценённых атрибута.NET

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели10K

Три атрибута, которые меняют результат компиляции. Один запускает метод раньше Main. Второй передаёт текст выражения вместо результата. Третий ускоряет stackalloc в 50 раз.

Все три описаны в документации и применяются внутри .NET. А в рабочем коде я их ни разу не видел.

Читать далее

Очередь на Postgres: почему Kafka не нужна

Время на прочтение8 мин
Охват и читатели8.3K

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

Сервис принимал запрос, писал строку в базу, отвечал 201. Никто не пишет статей про такой код, потому что в нём нечего обсуждать.

Рано или поздно один сервис перестаёт быть одним сервисом. Появляется второй, которому важно узнать о том же событии — обсчитать аналитику, обновить поисковый индекс, отправить письмо. Возникает соблазн просто дёрнуть его по HTTP, и это первая ошибка, которую все совершают и все же исправляют: синхронный вызов делает вас настолько же надёжным, насколько надёжен самый хрупкий из ваших соседей.

Значит нужно асинхронно, через брокер. И почти всегда этим брокером оказывается Kafka.

Читать далее

redb 4.0: XML-маршруты, ленивые ссылки, уникальные ключи и WS-Trust в одном мажоре

Время на прочтение12 мин
Охват и читатели8.4K

Мажор всей экосистемы: что появилось в redb.Core, redb.Route, redb.Tsak и redb.Identity, что закрыто по безопасности и что ломает обновление.

Много работы было сделано ночами при свечах. Обратная связь от людей давала пищу для размышлений и фиксов: комментарии к статьям, обсуждения на GitHub, отчёты с живых стендов. И вот, отработав по-стахановски, выпускаю 4.0.0.

Это мажор всей экосистемы разом. Хранилище redb.Core, интеграционный движок redb.Route, рантайм redb.Tsak и OpenID-сервер redb.Identity выходят одним номером: 76 пакетов на NuGet (у 3.7 было 66), семь образов в GHCR, архивы под Windows и Linux. Pro-издание по-прежнему бесплатно и не требует лицензионного ключа на всей линии 4.x.

Изменений столько, что подробный разбор любого из продуктов тянет на отдельную статью, и такие статьи будут. Здесь коротко, почти списком: что появилось, что закрыто по безопасности и что нужно знать перед обновлением. Полные списки изменений лежат на redb.ru/releases.

Читать далее

Ближайшие события

Что стоит за простым уведомлением: история разработки шаблонизатора на C#

Уровень сложностиПростой
Время на прочтение41 мин
Охват и читатели6.3K

Чтобы напомнить клиенту о встрече, нужно собрать в одном сообщении данные из нескольких записей CRM. С этой задачи началась работа над моим шаблонизатором, который постепенно обзавёлся каталогом понятных параметров, собственным парсером и условиями. Позже тот же механизм понадобился колл-центру уже в микросервисе. Расскажу, какие задачи меняли его устройство и что пришлось продумать, чтобы новое поле в сообщении можно было добавить без очередной задачи разработчику.

Что стоит за уведомлением →

Отбор акций на .NET: 14,5 млн баров в SQLite, фильтр, который мерил не в тех единицах, и перестановочный тест

Уровень сложностиСредний
Время на прочтение22 мин
Охват и читатели6.2K

Каждый вечер мне нужно ответить на один вопрос: на какие бумаги из примерно тринадцати тысяч имеет смысл потратить время сегодня. Не «какие вырастут» — этого никто не знает, — а на каких стоит нарисовать уровень и поставить заявку.

Год назад я написал под эту задачу программу и с тех пор работаю только через неё. Ниже — её устройство: как читаются 14,5 миллиона баров, как считается ранг относительной силы, как устроена воронка фильтров, какой из них год работал неправильно и почему, чем разбирается исход сделки и чем я проверяю, что отбор вообще чего-то стоит. Кода будет много: половина статьи именно про то, где решения оказались не такими, как выглядели на бумаге.

Стек, чтобы дальше не отвлекаться: .NET 10, C#, WinForms для окна, SQLite (Microsoft.Data.Sqlite) вместо сервера, ScottPlot для графиков, xUnit — 867 тестов на три проекта. Ни одного внешнего сервиса, кроме поставщика котировок, ключ к которому вводит пользователь.

Читать далее

Что скрывают популярные ORM для C#: проверка проектов RepoDB и SqlSugar

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели6.1K

Когда речь заходит об ORM, большинство C# разработчиков сразу вспоминают мощный Entity Framework Core или же легковесный Dapper. Но что насчёт RepoDB и SqlSugar? Несмотря на меньшую известность, эти ORM активно используются в реальных проектах и продолжают развиваться. Давайте посмотрим, какие проблемы удастся обнаружить в их исходном коде с помощью статического анализатора.

Читать далее

А чё, так можно было? int == -int

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели7.5K

Есть число, которое не меняется от смены знака. Минус перед ним ничего не делает, а модуля у него не существует: Math.Abs бросает исключение.

Это int.MinValue. И это ещё не всё, что он умеет.

Читать далее

Идемпотентность в платёжном конвейере: «повтори запрос» — это архитектура, а не retry

Время на прочтение22 мин
Охват и читатели7.3K

Начну со сцены, которую видел каждый, кто эксплуатировал платёжный сервис хотя бы год.

Клиент нажимает «Оплатить». Приложение отправляет POST /payments. Проходит пять секунд, и HTTP-клиент падает по таймауту. Ретрай-политика, которую кто-то настроил год назад по гайду, ждёт двести миллисекунд и отправляет запрос ещё раз. Через минуту клиент видит в выписке два списания.

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

Первый вывод: надо выключить retry на POST. Хорошо, выключили. Теперь у нас платежи, про которые никто не знает, прошли они или нет. Поддержка разбирает их руками. Ущерб никуда не делся, он просто переехал на другой счёт.

Второй вывод: надо добавить заголовок Idempotency-Key. Добавили. Дедупликацию сделали в middleware поверх Redis. Через полгода двойное списание случается снова. Потому что Redis пережил failover и потерял ключи. Или потому что повтор пришёл через сутки из файла клиринга, а в файле никакого HTTP-заголовка нет.

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

Retry сам по себе всего лишь тактика. Он работает там, где контракт уже есть. Без контракта retry не делает систему устойчивее. Он делает её быстрее ломающейся.

Читать далее

Создали корпоративный IT-сервис на С# и .NET, который предсказывает будущее

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели6.4K

Называется Контур Оракул. 🔮 За первый день после запуска он собрал сотни реакций сотрудников, и сразу показал, что корпоративные прогнозы могут быть не развлечением, а рабочим инструментом.

Сделали сервис студенты ФИИТ (это программа УрФУ, которую поддерживает Контур). А в этой статье пришли и рассказали, как появилась идея Оракула, как он выглядит внутри, что за технологии использовали в серверной и клиентской частях, и как в основе сервиса работает алгоритм LMSR для расчётов.

Читать далее

А чё, так можно было? Dictionary == List

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели8.4K

Ключ-структура из числа и строки. Поиск по словарю на 10 000 таких ключей занимает 74 975 микросекунд. Тот же ключ, объявленный record struct, — 3,354 микросекунды.

Разница в 22 354 раза, и берётся она не из сравнения ключей.

Читать далее
1
23 ...