Правильно ли вы внедряете зависимости в Controllers?
Многие разработчики этого не знают
Внедрять зависимости в Controller можно двумя способами:
↳ через конструктор
↳ через внедрение в метод
Сталкивались с раздутыми контроллерами, у которых в конструкторе слишком много зависимостей?
При этом конкретный endpoint использует только часть из них.
❌ Вы зря расходуете память, потому что все зависимости из конструктора аллоцируются в куче при вызове Controller, независимо от того, будут они использоваться или нет.
✅ Так почему бы не внедрять нужные объекты прямо в метод endpoint-а?
Их можно внедрять без атрибута
Когда вы внедряете зависимости только там, где они реально нужны, это улучшает читаемость, упрощает поддержку и повышает производительность контроллеров.
👉 @KodBlog
Многие разработчики этого не знают
Внедрять зависимости в Controller можно двумя способами:
↳ через конструктор
↳ через внедрение в метод
Сталкивались с раздутыми контроллерами, у которых в конструкторе слишком много зависимостей?
При этом конкретный endpoint использует только часть из них.
Их можно внедрять без атрибута
[FromServices], он больше не нужен. Почти так же, как и в Minimal APIs.Когда вы внедряете зависимости только там, где они реально нужны, это улучшает читаемость, упрощает поддержку и повышает производительность контроллеров.
Please open Telegram to view this post
VIEW IN TELEGRAM
👎6❤5👍2🤔2
Хватит инжектить IConfiguration. Вот правильный подход в .NET 10
Однажды я выкатил систему feature-флагов, которая читала настройки из
Исправление? Заменить
Изменение в одну строку, которое стоило мне трёх часов дебага и инцидент-репорта. Этот случай показал мне: понимать Options Pattern — не опционально. Это базовая вещь. Разберёмся.
Завариваем кофею и читаем статью
👉 @KodBlog
Однажды я выкатил систему feature-флагов, которая читала настройки из
appsettings.json через IOptions<FeatureFlagOptions>. В деве всё работало нормально. Но в проде, когда команда DevOps переключала флаг, обновляя appsettings.json, ничего не происходило. API продолжал возвращать старые значения. Пользователи застряли. Чтобы подхватить изменения, мне пришлось перезапустить приложение.Исправление? Заменить
IOptions<T> на IOptionsMonitor<T>.Изменение в одну строку, которое стоило мне трёх часов дебага и инцидент-репорта. Этот случай показал мне: понимать Options Pattern — не опционально. Это базовая вещь. Разберёмся.
Завариваем кофею и читаем статью
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥6🥴2🤨2🤔1
MapReduce — это популярный фреймворк, изначально разработанный в Google, для эффективной и отказоустойчивой обработки больших распределённых наборов данных. Он был создан, чтобы запускать масштабные вычисления на терабайтах данных, собранных из веба, предоставляя удобный слой абстракции поверх тысяч машин.
Фреймворк основан на двух функциях из функциональных языков: Map и Reduce.
- Map принимает на вход список элементов и функцию. Она применяет эту функцию к каждому элементу списка и возвращает результат. Например, если список
- Reduce принимает список, функцию и начальное значение. Она последовательно комбинирует элементы списка с начальным значением через заданную функцию. Например, если функция суммирует два числа, начальное значение 0, а список
Внутреннее функционирование MapReduce можно описать следующими шагами:
1. Разделение данных: входные файлы делятся на несколько частей.
2. Запуск кластерной обработки: запускаются копии программы MapReduce на кластере. Одна копия — мастер, остальные — воркеры. Мастер распределяет Map и Reduce задачи между воркерами. Пользователь может задать количество задач Map и Reduce.
3. Map задачи: воркер читает свою часть входных данных, разбивает её на пары ключ/значение и передаёт в пользовательскую функцию Map.
4. Промежуточные данные: Map функция возвращает набор промежуточных пар ключ/значение. Эти пары разбиваются на партиции, а информация о расположении каждой партиции отправляется мастеру. Эти партиции становятся входом для Reduce воркеров.
5. Reduce задачи: воркер считывает пары, группирует все элементы с одинаковым ключом и передаёт ключ с соответствующим набором значений в пользовательскую функцию Reduce. Результат Reduce добавляется в выходной файл.
6. Завершение работы: когда все Map и Reduce задачи выполнены, мастер возвращает контроль пользователю. Выходные данные доступны через файлы, один файл на каждого Reduce воркера.
Таким образом, MapReduce превращает огромные распределённые вычисления в управляемый процесс с понятной логикой распределения и агрегации данных.
👉 @KodBlog
Фреймворк основан на двух функциях из функциональных языков: Map и Reduce.
- Map принимает на вход список элементов и функцию. Она применяет эту функцию к каждому элементу списка и возвращает результат. Например, если список
[1,2,3,4], а функция возводит число в квадрат, Map преобразует его в [1,4,9,16].- Reduce принимает список, функцию и начальное значение. Она последовательно комбинирует элементы списка с начальным значением через заданную функцию. Например, если функция суммирует два числа, начальное значение 0, а список
[1,2,3,4], Reduce вернёт 10.Внутреннее функционирование MapReduce можно описать следующими шагами:
1. Разделение данных: входные файлы делятся на несколько частей.
2. Запуск кластерной обработки: запускаются копии программы MapReduce на кластере. Одна копия — мастер, остальные — воркеры. Мастер распределяет Map и Reduce задачи между воркерами. Пользователь может задать количество задач Map и Reduce.
3. Map задачи: воркер читает свою часть входных данных, разбивает её на пары ключ/значение и передаёт в пользовательскую функцию Map.
4. Промежуточные данные: Map функция возвращает набор промежуточных пар ключ/значение. Эти пары разбиваются на партиции, а информация о расположении каждой партиции отправляется мастеру. Эти партиции становятся входом для Reduce воркеров.
5. Reduce задачи: воркер считывает пары, группирует все элементы с одинаковым ключом и передаёт ключ с соответствующим набором значений в пользовательскую функцию Reduce. Результат Reduce добавляется в выходной файл.
6. Завершение работы: когда все Map и Reduce задачи выполнены, мастер возвращает контроль пользователю. Выходные данные доступны через файлы, один файл на каждого Reduce воркера.
Таким образом, MapReduce превращает огромные распределённые вычисления в управляемый процесс с понятной логикой распределения и агрегации данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👏3
This media is not supported in your browser
VIEW IN TELEGRAM
Чувак сделал Ctrl+F для всего экрана.
Нажимаешь хоткей → экран «замораживается» → вводишь текст для поиска → совпадения подсвечиваются в реальном времени. Работает с любым видимым контентом — невыделяемые PDF, диалоги ошибок, текст на изображениях и т.д.
Также можно выделить мышью любую область (drag-select), и приложение автоматически копирует весь текст из этой области — как Snipping Tool, только для текста, с автокопированием.
Один
Вот приложение — github.com/sid1552/ScreenFind
TL;DR: Ctrl+F, но для всего экрана.
👉 @KodBlog
Нажимаешь хоткей → экран «замораживается» → вводишь текст для поиска → совпадения подсвечиваются в реальном времени. Работает с любым видимым контентом — невыделяемые PDF, диалоги ошибок, текст на изображениях и т.д.
Также можно выделить мышью любую область (drag-select), и приложение автоматически копирует весь текст из этой области — как Snipping Tool, только для текста, с автокопированием.
Один
.exe, работает локально, используя встроенный в Windows OCR.Вот приложение — github.com/sid1552/ScreenFind
TL;DR: Ctrl+F, но для всего экрана.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥12❤3🤔3🔥2👏1
SignalR позволяет добавлять real-time функциональность в .NET-приложения.
И всё начинается с Hub.
Hub — это центральный компонент приложения, который управляет клиентами и отправляет сообщения.
Чтобы получать и отправлять сообщения, клиенты должны подключиться к Hub.
👉 @KodBlog
И всё начинается с Hub.
Hub — это центральный компонент приложения, который управляет клиентами и отправляет сообщения.
Чтобы получать и отправлять сообщения, клиенты должны подключиться к Hub.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤1🤩1
Когда кажется, что в Postgres уже не осталось того, чего он не умеет… 🐘
Да, даже полнотекстовый поиск.
И его можно подключить через EF Core.
С этим вы можете:
Настроить индексы для полнотекстового поиска
Писать эффективные поисковые запросы
Ранжировать и сортировать результаты по релевантности
Плавно интегрировать это в ваши .NET-приложения
https://www.milanjovanovic.tech/blog/how-i-implemented-full-text-search-on-my-website
👉 @KodBlog
Да, даже полнотекстовый поиск.
И его можно подключить через EF Core.
С этим вы можете:
Настроить индексы для полнотекстового поиска
Писать эффективные поисковые запросы
Ранжировать и сортировать результаты по релевантности
Плавно интегрировать это в ваши .NET-приложения
https://www.milanjovanovic.tech/blog/how-i-implemented-full-text-search-on-my-website
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤩1
Большинство разработчиков могут назвать 10 типов тестирования.
Но лишь немногие могут объяснить, когда использовать каждый из них.
Вот краткий разбор:
1. Smoke Testing (смоук-тестирование)
Приложение вообще запускается?
2. Functional Testing (функциональное тестирование)
Каждая функция возвращает корректный результат?
3. Integration Testing (интеграционное тестирование)
Модули продолжают работать корректно, когда они соединены между собой?
4. Regression Testing (регрессионное тестирование)
Последний коммит не сломал то, что ещё вчера работало?
5. Load Testing (нагрузочное тестирование)
Система справляется с реальным трафиком без «захлёбывания»?
6. Stress Testing (стресс-тестирование)
Что произойдёт, если нагрузку довести до предела?
7. Security Testing (тестирование безопасности)
Может ли кто-то воспользоваться уязвимостью, о которой вы не знали?
8. UI Testing (тестирование пользовательского интерфейса)
Интерфейс ведёт себя так, как ожидает пользователь?
9. Fuzz Testing (фазз-тестирование)
Что сломается, если отправлять приложению случайные или некорректные данные?
10. Reliability Testing (тестирование надёжности)
Система остаётся стабильной после работы в течение дней, а не минут?
👉 @KodBlog
Но лишь немногие могут объяснить, когда использовать каждый из них.
Вот краткий разбор:
1. Smoke Testing (смоук-тестирование)
Приложение вообще запускается?
2. Functional Testing (функциональное тестирование)
Каждая функция возвращает корректный результат?
3. Integration Testing (интеграционное тестирование)
Модули продолжают работать корректно, когда они соединены между собой?
4. Regression Testing (регрессионное тестирование)
Последний коммит не сломал то, что ещё вчера работало?
5. Load Testing (нагрузочное тестирование)
Система справляется с реальным трафиком без «захлёбывания»?
6. Stress Testing (стресс-тестирование)
Что произойдёт, если нагрузку довести до предела?
7. Security Testing (тестирование безопасности)
Может ли кто-то воспользоваться уязвимостью, о которой вы не знали?
8. UI Testing (тестирование пользовательского интерфейса)
Интерфейс ведёт себя так, как ожидает пользователь?
9. Fuzz Testing (фазз-тестирование)
Что сломается, если отправлять приложению случайные или некорректные данные?
10. Reliability Testing (тестирование надёжности)
Система остаётся стабильной после работы в течение дней, а не минут?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🤔3❤1🤩1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4👏4👨💻3
Вот как можно реализовать фильтр запросов на основе тенанта с использованием EF Core.
Вам понадобится сервис, который будет предоставлять TenantId для текущего тенанта. Это значение можно получить из заголовка запроса или клейма
Побочный эффект: вы сможете использовать DbContext только в рамках HTTP-запроса.
👉 @KodBlog
Вам понадобится сервис, который будет предоставлять TenantId для текущего тенанта. Это значение можно получить из заголовка запроса или клейма
Побочный эффект: вы сможете использовать DbContext только в рамках HTTP-запроса.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2👀2
Как создавать фоновые задачи в .NET?
С Quartz это так же просто, как реализовать интерфейс.
Вы можете внедрять любые необходимые зависимости через DI. Фоновые задачи также имеют scoped-область, поэтому можно даже внедрять DbContext.
👉 @KodBlog
С Quartz это так же просто, как реализовать интерфейс.
Вы можете внедрять любые необходимые зависимости через DI. Фоновые задачи также имеют scoped-область, поэтому можно даже внедрять DbContext.
[DisallowConcurrentExecution]
public class MyBackgroundJob : IJob
{
public MyBackgroundJob(...)
{
}
public async Task Execute(IJobExecutionContext context)
{
// Implement your logic here.
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤2😁2👨💻1
Сделать столбец Sparse в Entity Framework 💡
В SQL Server sparse-столбцы — это обычные столбцы, оптимизированные для хранения значений
Хорошими кандидатами для sparse-столбцов являются любые столбцы, у которых в большинстве строк вероятно будет значение
и т. д.
Sparse-столбцы легко настраиваются в EF
👉 @KodBlog
В SQL Server sparse-столбцы — это обычные столбцы, оптимизированные для хранения значений
NULL. Их использование может значительно экономить место.Хорошими кандидатами для sparse-столбцов являются любые столбцы, у которых в большинстве строк вероятно будет значение
NULL, например:dateAccountClosed
discountAmount
Suffix
Address4
DeliveryInstructions
OrderReturnDate
и т. д.
Sparse-столбцы легко настраиваются в EF
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👏1
This media is not supported in your browser
VIEW IN TELEGRAM
REST API vs WebSocket
REST API:
- Модель запрос–ответ
- Клиент отправляет запрос → сервер возвращает ответ
- Stateless (каждый запрос независим)
- Лучше всего подходит для CRUD-операций
- Использует HTTP/HTTPS
• Пример: получение данных пользователя, отправка форм
WebSocket:
- Двусторонняя связь в реальном времени
- Постоянное full-duplex соединение
- Stateful-соединение
- Лучше всего подходит для live-обновлений
- Использует протокол ws/wss
• Пример: чат-приложения, лайв-трейдинг, онлайн-игры
🟢 REST = запросил → получил
🔵 WebSocket = постоянное соединение и обмен данными в любой момент
👉 @KodBlog
REST API:
- Модель запрос–ответ
- Клиент отправляет запрос → сервер возвращает ответ
- Stateless (каждый запрос независим)
- Лучше всего подходит для CRUD-операций
- Использует HTTP/HTTPS
• Пример: получение данных пользователя, отправка форм
WebSocket:
- Двусторонняя связь в реальном времени
- Постоянное full-duplex соединение
- Stateful-соединение
- Лучше всего подходит для live-обновлений
- Использует протокол ws/wss
• Пример: чат-приложения, лайв-трейдинг, онлайн-игры
Please open Telegram to view this post
VIEW IN TELEGRAM
👏7❤2
FluentValidation делает валидацию входных данных очень простой.
Знали ли вы, что валидаторы поддерживают DI (Dependency Injection)?
Вы можете внедрять объекты настроек, сконфигурированные через DI, и использовать их внутри валидаторов.
Посмотрите пример в сниппете кода ниже.👇
Знали ли вы, что валидаторы поддерживают DI (Dependency Injection)?
Вы можете внедрять объекты настроек, сконфигурированные через DI, и использовать их внутри валидаторов.
Посмотрите пример в сниппете кода ниже.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🥴1
Непопулярное мнение:
Большинство разработчиков на самом деле не понимают Git.
Они знают только три команды:
1.
2.
3.
Но Git может гораздо больше:
- ветвление (branching)
- rebase
- stash
- cherry-pick
- разрешение конфликтов (conflict resolution)
Правильное понимание Git может сэкономить часы отладки и исправления сломанных веток.
👉 @KodBlog
Большинство разработчиков на самом деле не понимают Git.
Они знают только три команды:
1.
git add2.
git commit3.
git pushНо Git может гораздо больше:
- ветвление (branching)
- rebase
- stash
- cherry-pick
- разрешение конфликтов (conflict resolution)
Правильное понимание Git может сэкономить часы отладки и исправления сломанных веток.
Please open Telegram to view this post
VIEW IN TELEGRAM
😐21🥴5❤1👎1
Используешь ли ты trunk-based development?
Это стратегия ветвления, при которой все разработчики работают напрямую в «trunk» (основной ветке).
Feature flags — обязательная часть такого подхода.
Незавершённые фичи прячутся за feature flag и выкатываются только тогда, когда они готовы.
👉 @KodBlog
Это стратегия ветвления, при которой все разработчики работают напрямую в «trunk» (основной ветке).
Feature flags — обязательная часть такого подхода.
Незавершённые фичи прячутся за feature flag и выкатываются только тогда, когда они готовы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🤔3❤1
Алгоритм ограничения запросов: Sliding Window Counter
Этот алгоритм — комбинация Fixed Window и Sliding Window.
То есть есть фиксированные окна, но поверх них «скользит» sliding window, которая постоянно проверяет, что текущее окно не превышает допустимое количество запросов (rate limit).
Базовая идея:
Например:
Как видно, есть два фиксированных окна и одно скользящее окно поверх них, которое отслеживает количество запросов внутри себя.
Это значит, что учитываются запросы как из предыдущего окна, так и из текущего — но только та их часть, которая попадает внутрь sliding window. И алгоритм следит, чтобы суммарное число запросов не превышало заданный лимит.
Формула:
Для overlap (перекрытия):
Объяснение overlap:
Представим два окна:
-> 1-е окно: с 1s до 10s
-> 2-е окно: с 10s до 20s
Допустим, мы находимся на 13-й секунде (то есть на 3 секунде второго окна).
Если смотреть назад, sliding window охватывает интервал от 3s до 13s (то есть захватывает 3 секунды из первого окна).
Часть предыдущего окна, которая попадает в sliding window — это промежуток с 3s до 10s. Это и есть overlap.
Соответственно:
-> берём запросы за последние 7 секунд из предыдущего окна (3s–10s)
-> и добавляем запросы за текущие 3 секунды из нового окна (10s–13s)
После этого проверяем: если суммарное количество превышает лимит — отклоняем запрос.
В итоге:
это всегда sliding window длиной, например, 10 секунд, которая «плавает» поверх фиксированных окон и динамически проверяет количество запросов.
Да, разобраться в этом не с первого раза — нормально🙂
👉 @KodBlog
Этот алгоритм — комбинация Fixed Window и Sliding Window.
То есть есть фиксированные окна, но поверх них «скользит» sliding window, которая постоянно проверяет, что текущее окно не превышает допустимое количество запросов (rate limit).
Базовая идея:
Например:
Как видно, есть два фиксированных окна и одно скользящее окно поверх них, которое отслеживает количество запросов внутри себя.
Это значит, что учитываются запросы как из предыдущего окна, так и из текущего — но только та их часть, которая попадает внутрь sliding window. И алгоритм следит, чтобы суммарное число запросов не превышало заданный лимит.
Формула:
effective_requests = current_window_count +
(previous_window_count × overlap_fraction)
Для overlap (перекрытия):
overlap_fraction =
remaining_time_in_previous_window / window_size
Объяснение overlap:
Представим два окна:
-> 1-е окно: с 1s до 10s
-> 2-е окно: с 10s до 20s
Допустим, мы находимся на 13-й секунде (то есть на 3 секунде второго окна).
Если смотреть назад, sliding window охватывает интервал от 3s до 13s (то есть захватывает 3 секунды из первого окна).
Часть предыдущего окна, которая попадает в sliding window — это промежуток с 3s до 10s. Это и есть overlap.
Соответственно:
-> берём запросы за последние 7 секунд из предыдущего окна (3s–10s)
-> и добавляем запросы за текущие 3 секунды из нового окна (10s–13s)
После этого проверяем: если суммарное количество превышает лимит — отклоняем запрос.
В итоге:
это всегда sliding window длиной, например, 10 секунд, которая «плавает» поверх фиксированных окон и динамически проверяет количество запросов.
Да, разобраться в этом не с первого раза — нормально
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4😁2
Если вы хотите использовать Minimal APIs в более вертикально-срезовой (vertical slice) структуре, вот простая абстракция:
- интерфейс IEndpoint для определения эндпоинтов
- несколько методов-расширений для автоматической регистрации эндпоинтов
Цена на старте? Пара миллисекунд.
👉 @KodBlog
- интерфейс IEndpoint для определения эндпоинтов
- несколько методов-расширений для автоматической регистрации эндпоинтов
Цена на старте? Пара миллисекунд.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
Стоит ли Microsoft прекратить поддержку .NET Framework в Microsoft.Data.Sqlite в предстоящем релизе 11.0?
Обсуждение этого вопроса уже закрыто на GitHub, но Microsoft запрашивала мнение сообщества. (судя по скрину, комьюнити не против)
Проблема поддержки .NET Framework в GitHub SqLite: https://github.com/dotnet/efcore/issues/37895
👉 @KodBlog
Обсуждение этого вопроса уже закрыто на GitHub, но Microsoft запрашивала мнение сообщества. (судя по скрину, комьюнити не против)
Проблема поддержки .NET Framework в GitHub SqLite: https://github.com/dotnet/efcore/issues/37895
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Не отправляйте несколько SQL-команд в базу данных (PostgreSQL) последовательно.
Вместо этого делайте так👇
Когда у вас есть кейс, где вы добавляете новую запись и затем читаете её, обычно выполняются два SQL-запроса: INSERT и SELECT.
С точки зрения выполнения это нормально, но что насчёт таких факторов, как:
1/ сетевая задержка (network latency)
2/ количество round-trip’ов к базе данных
Это ведь легко может снизить производительность, верно?
К счастью, с Npgsql это не обязательно.
У этого провайдера есть фича под названием batching.
Batching — это отправка нескольких SQL-команд в PostgreSQL за один round-trip к базе данных, вместо того чтобы вызывать Execute отдельно для каждой команды.
В документации Npgsql это описано через использование NpgsqlBatch, который упаковывает несколько NpgsqlBatchCommand в один запрос к серверу.
Важная деталь: если вы не начали собственную транзакцию, Npgsql автоматически оборачивает batch в неявную транзакцию.
Если один из запросов падает, остальные не выполняются, а весь batch откатывается (rollback).
👉 @KodBlog
Вместо этого делайте так
Когда у вас есть кейс, где вы добавляете новую запись и затем читаете её, обычно выполняются два SQL-запроса: INSERT и SELECT.
С точки зрения выполнения это нормально, но что насчёт таких факторов, как:
1/ сетевая задержка (network latency)
2/ количество round-trip’ов к базе данных
Это ведь легко может снизить производительность, верно?
К счастью, с Npgsql это не обязательно.
У этого провайдера есть фича под названием batching.
Batching — это отправка нескольких SQL-команд в PostgreSQL за один round-trip к базе данных, вместо того чтобы вызывать Execute отдельно для каждой команды.
В документации Npgsql это описано через использование NpgsqlBatch, который упаковывает несколько NpgsqlBatchCommand в один запрос к серверу.
Важная деталь: если вы не начали собственную транзакцию, Npgsql автоматически оборачивает batch в неявную транзакцию.
Если один из запросов падает, остальные не выполняются, а весь batch откатывается (rollback).
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🍌2🔥1