⚡️ Если ты запускаешь десяток терминалов для старта приложения
С .NET Aspire можно запускать backend, frontend и все зависимости одновременно — быстро и удобно!
Смотри, как это сделать: justkeepcoding.tech/blog/integrating-angular-into-dotnet-aspire
С .NET Aspire можно запускать backend, frontend и все зависимости одновременно — быстро и удобно!
Смотри, как это сделать: justkeepcoding.tech/blog/integrating-angular-into-dotnet-aspire
🗂️ Entity Framework Core — ORM нового поколения для работы с БД. Этот инструмент от Microsoft кардинально меняет подход к взаимодействию с реляционными и NoSQL базами данных.
Для работы инструмент предоставляет мощный слой абстракции, позволяя работать с данными как с объектами, автоматизируя CRUD-операции и миграции схемы. EF Core поддерживает широкий пласт СУБД: от классических SQL Server и PostgreSQL до документоориентированной Cosmos DB. Для SQLite-разработчиков есть отдельный оптимизированный провайдер Microsoft.Data.Sqlite.
🤖 GitHub
Для работы инструмент предоставляет мощный слой абстракции, позволяя работать с данными как с объектами, автоматизируя CRUD-операции и миграции схемы. EF Core поддерживает широкий пласт СУБД: от классических SQL Server и PostgreSQL до документоориентированной Cosmos DB. Для SQLite-разработчиков есть отдельный оптимизированный провайдер Microsoft.Data.Sqlite.
🤖 GitHub
Forwarded from C++ Academy
This media is not supported in your browser
VIEW IN TELEGRAM
🚀 Разработчик показал движок на C, который работает в 14 раз быстрее Unity в браузере — и теперь доступна онлайн-демо.
Многие не поверили в заявленную разницу в производительности, поэтому он выложил демо в открытый доступ. Сравнение проводится с реальным Unity-проектом, выложенным на GitHub.
🛠️ C-движок демонстрирует:
• Существенно более высокую FPS в браузере
• Минимальную просадку при рендеринге
• Низкий overhead по сравнению с WebAssembly-сборкой Unity
💬 Автор пока не решил, выкладывать ли исходники C-версии — рассматривает вариант лицензии CC (non-commercial).
🔗 Демо: https://cgamedev.com/
🔗 Код: https://github.com/gabrieldechichi/unity_webglperftest
@cpluspluc
Многие не поверили в заявленную разницу в производительности, поэтому он выложил демо в открытый доступ. Сравнение проводится с реальным Unity-проектом, выложенным на GitHub.
🛠️ C-движок демонстрирует:
• Существенно более высокую FPS в браузере
• Минимальную просадку при рендеринге
• Низкий overhead по сравнению с WebAssembly-сборкой Unity
💬 Автор пока не решил, выкладывать ли исходники C-версии — рассматривает вариант лицензии CC (non-commercial).
🔗 Демо: https://cgamedev.com/
🔗 Код: https://github.com/gabrieldechichi/unity_webglperftest
@cpluspluc
👶 Junior developer пишет:
🧑 Middle developer пишет:
🧓 Senior developer пишет:
🤔 Почему так происходит?
👉 Потому что булевы переменные — просты по сути, но часто используются неинтуитивно, что делает код запутанным и плохо поддерживаемым.
Вот 7 простых правил, как работать с булевыми значениями в C# и резко улучшить читаемость вашего кода:
1. 🚫 Избегайте двойных отрицаний
❌
✅
❌
✅
❌
✅
Двойные отрицания сбивают с толку и делают логику трудной для чтения.
2. ✅ Используйте понятные префиксы
✅
✅
✅
Префиксы мгновенно раскрывают назначение переменной.
3. 🔤 Предпочитайте единственное число
❌
✅
Единственное число делает значение ясным и конкретным.
4. 🎯 Используйте прилагательные для описания состояния
❌
✅
Булевы переменные должны описывать состояние, а не действие.
5. ⏱ Используйте настоящее время
❌
✅
Текущие состояния — проще и универсальнее в коде.
6. 🔁 Принцип раннего возврата (Return Early)
Пишите условия и булевы проверки так, чтобы код читался сверху вниз, как история — коротко, логично, понятно.
7. ⚠️ Не передавайте булевы параметры
❌
✅
Используйте перечисления или именованные константы — они понятны без документации.
📌 Вывод:
Хорошие имена булевых переменных — это не косметика, а основа читаемости и архитектурной чистоты.
Хорошо названный
💬 А ты какие правила используешь для наименования булевых переменных? Делись в комментариях 👇
notInactive
, tempBool
🧑 Middle developer пишет:
hadSubscriptionOnceUponATime
🧓 Senior developer пишет:
hasSubscription
, isActive
🤔 Почему так происходит?
👉 Потому что булевы переменные — просты по сути, но часто используются неинтуитивно, что делает код запутанным и плохо поддерживаемым.
Вот 7 простых правил, как работать с булевыми значениями в C# и резко улучшить читаемость вашего кода:
1. 🚫 Избегайте двойных отрицаний
❌
user.IsNotActive
✅
user.IsActive
❌
user.HasNoDept
✅
user.HasDept
❌
creditCard.IsNotExpired
✅
creditCard.IsExpired
Двойные отрицания сбивают с толку и делают логику трудной для чтения.
2. ✅ Используйте понятные префиксы
✅
Is
: user.IsActive
✅
Has
: user.HasDept
✅
Should
: order.ShouldBeCanceled
Префиксы мгновенно раскрывают назначение переменной.
3. 🔤 Предпочитайте единственное число
❌
areUsers
✅
hasUsers
Единственное число делает значение ясным и конкретным.
4. 🎯 Используйте прилагательные для описания состояния
❌
CancelOrder
✅
IsOrderCanceled
Булевы переменные должны описывать состояние, а не действие.
5. ⏱ Используйте настоящее время
❌
card.WasExpired
✅
card.IsExpired
Текущие состояния — проще и универсальнее в коде.
6. 🔁 Принцип раннего возврата (Return Early)
Пишите условия и булевы проверки так, чтобы код читался сверху вниз, как история — коротко, логично, понятно.
7. ⚠️ Не передавайте булевы параметры
❌
SendEmail(true)
✅
SendEmail(SendMode.Immediate)
Используйте перечисления или именованные константы — они понятны без документации.
📌 Вывод:
Хорошие имена булевых переменных — это не косметика, а основа читаемости и архитектурной чистоты.
Хорошо названный
isActive
понятнее, чем любые комментарии и тесты.💬 А ты какие правила используешь для наименования булевых переменных? Делись в комментариях 👇
[Best Practice] Явная конфигурация приложений ASP.NET Core
В большинстве существующих .NET-проектов конфигурация оказывается неочевидной, хотя в экосистеме .NET уже есть всё необходимое для ясной и понятной настройки ASP.NET Core веб-приложений с DI.
Как устроена конфигурация ASP.NET Core
- Источники (в порядке приоритета):
1. Host configuration
2.
3.
4. User secrets (в среде Development)
5. переменные окружения
6. аргументы командной строки
При дублировании ключей побеждает источник, указанный позже :contentReference[oaicite:0]{index=0}.
Выбор способа доступа к настройкам
- Через
- Через
Предпочтение паттерну Options даёт типобезопасный доступ к группам настроек и делает их использование очевидным :contentReference[oaicite:1]{index=1}.
Где хранить разные параметры
- `appsettings.json` — общие настройки (без секретов).
- `appsettings.{Environment}.json` — переопределения для конкретного окружения.
- User Secrets (`secrets.json`) — локальные секреты (пароли, ключи API); не используйте
- Azure Key Vault — производственные секреты через
- Переменные окружения и CLI — для срочных или разовых переопределений.
Рекомендации по внедрению
- Избегайте дублирования ключей — задавайте значение только там, где оно действительно меняется.
- В README укажите, что разработчикам нужно получить
- В IaC-скриптах чётко обозначьте необходимые секреты и параметры для каждого окружения.
Преимущества подхода
- Новым участникам проекта легко разобраться в конфигурации — каждый ключ встречается в одном месте.
- Возрастает поддерживаемость и прозрачность настроек.
- Упрощается автоматизация развёртывания (IaC): сразу видно, какие секреты и параметры требуются.
Читать
В большинстве существующих .NET-проектов конфигурация оказывается неочевидной, хотя в экосистеме .NET уже есть всё необходимое для ясной и понятной настройки ASP.NET Core веб-приложений с DI.
Как устроена конфигурация ASP.NET Core
- Источники (в порядке приоритета):
1. Host configuration
2.
appsettings.json
3.
appsettings.{Environment}.json
4. User secrets (в среде Development)
5. переменные окружения
6. аргументы командной строки
При дублировании ключей побеждает источник, указанный позже :contentReference[oaicite:0]{index=0}.
Выбор способа доступа к настройкам
- Через
IConfiguration
- Через
IOptions<T>
/ IOptionsMonitor<T>
Предпочтение паттерну Options даёт типобезопасный доступ к группам настроек и делает их использование очевидным :contentReference[oaicite:1]{index=1}.
Где хранить разные параметры
- `appsettings.json` — общие настройки (без секретов).
- `appsettings.{Environment}.json` — переопределения для конкретного окружения.
- User Secrets (`secrets.json`) — локальные секреты (пароли, ключи API); не используйте
appsettings.json
или appsettings.Development.json
для них :contentReference[oaicite:2]{index=2}. - Azure Key Vault — производственные секреты через
builder.Configuration.AddAzureKeyVault(...)
:contentReference[oaicite:3]{index=3}. - Переменные окружения и CLI — для срочных или разовых переопределений.
Рекомендации по внедрению
- Избегайте дублирования ключей — задавайте значение только там, где оно действительно меняется.
- В README укажите, что разработчикам нужно получить
secrets.json
из менеджера паролей и настроить User Secrets. - В IaC-скриптах чётко обозначьте необходимые секреты и параметры для каждого окружения.
Преимущества подхода
- Новым участникам проекта легко разобраться в конфигурации — каждый ключ встречается в одном месте.
- Возрастает поддерживаемость и прозрачность настроек.
- Упрощается автоматизация развёртывания (IaC): сразу видно, какие секреты и параметры требуются.
Читать
In-memory кэш в .NET: плюсы и минусы
✅ Плюсы:
• Очень быстрый
• Легко реализуется
• Не требует внешних зависимостей
⚠️ Минусы:
• Данные теряются при перезапуске
• Работает только в пределах одного инстанса
• Нет шаринга между приложениями
📌 Нужно больше — переходите на распределённый кэш.
Redis — топовый выбор, и в .NET есть два стабильных клиента:
•
•
📘 Хотите понять, когда и как использовать оба подхода?
Вот полный гайд:
https://milanjovanovic.tech/blog/caching-in-aspnetcore-improving-application-performance
✅ Плюсы:
• Очень быстрый
• Легко реализуется
• Не требует внешних зависимостей
⚠️ Минусы:
• Данные теряются при перезапуске
• Работает только в пределах одного инстанса
• Нет шаринга между приложениями
📌 Нужно больше — переходите на распределённый кэш.
Redis — топовый выбор, и в .NET есть два стабильных клиента:
•
StackExchange.Redis
•
Microsoft.Extensions.Caching.StackExchangeRedis
📘 Хотите понять, когда и как использовать оба подхода?
Вот полный гайд:
https://milanjovanovic.tech/blog/caching-in-aspnetcore-improving-application-performance
Реферальная программа для тех, кто не работает в Ozon:
порекомендуйте C#-разработчика уровня senior и заработайте 150 000 ₽.
Посмотреть вакансии, которые включает программа: https://s.ozon.ru/rja14Mz
порекомендуйте C#-разработчика уровня senior и заработайте 150 000 ₽.
Посмотреть вакансии, которые включает программа: https://s.ozon.ru/rja14Mz
Дан код:
using System;
using System.Runtime.ExceptionServices;
class Program
{
static void Main()
{
try
{
Console.WriteLine(Foo());
}
catch (Exception ex)
{
Console.WriteLine($"Catch: {ex.Message}");
}
}
static int Foo()
{
try
{
return Bar();
}
finally
{
throw new Exception("finally in Foo");
}
}
static int Bar()
{
try
{
throw new Exception("error in Bar");
}
finally
{
Console.WriteLine("Bar finally executed");
}
}
}
Вопросы:
• Что напечатает программа и почему?
• В каком порядке выполняются блоки try / finally?
• Какая из двух ошибок дойдёт до catch, а какая потеряется?
• Как изменить код, чтобы не терять информацию о первой ошибке?
Разбор:
• Bar бросает Exception("error in Bar"). Прежде чем исключение покинет метод, выполняется его finally, выводя Bar finally executed.
• Управление переходит в Foo. Там срабатывает finally, который бросает новое исключение ("finally in Foo").
• По правилам CLR новое исключение из finally заменяет текущее. Первая ошибка пропадает.
• В Main перехватывается только «finally in Foo».
Консольный вывод:
Bar finally executed
Catch: finally in Foo
Как сохранить обе ошибки
Обернуть второе исключение так, чтобы первая причина не потерялась, например:
finally
{
var pending = new Exception("finally in Foo");
throw new AggregateException("Foo failed", pending);
}
или переслать исходное исключение через ExceptionDispatchInfo:
Exception pending = null;
static int Foo()
{
try
{
return Bar();
}
catch (Exception ex)
{
pending = ex; // сохраняем первую причину
throw;
}
finally
{
if (pending != null)
ExceptionDispatchInfo.Capture(pending).Throw();
}
}```
Так ни одна ошибка не будет потеряна, а отладка станет нагляднее.
Please open Telegram to view this post
VIEW IN TELEGRAM
🐢 Столкнулись с «тормозным» C#-кодом? Медленные алгоритмы могут растянуть выполнение задачи на минуты вместо миллисекунд.
📅 Приглашаем на открытый урок «Анализ сложности алгоритмов и сортировка на C#» 3 июля в 20:00 МСК.
Разберём, что такое Big O, какие факторы влияют на скорость, и на практике напишем пузырьковую, вставками и другие сортировки.
Вы увидите, как измерять время выполнения, сравнивать производительность и выбирать самый эффективный алгоритм. После занятия ваш код станет быстрее, а техническое интервью — проще.
Регистрируйтесь сейчас — урок проходит перед стартом курса «C# Developer»: https://otus.pw/yQzK/?erid=2W5zFJSuoQ4
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
📅 Приглашаем на открытый урок «Анализ сложности алгоритмов и сортировка на C#» 3 июля в 20:00 МСК.
Разберём, что такое Big O, какие факторы влияют на скорость, и на практике напишем пузырьковую, вставками и другие сортировки.
Вы увидите, как измерять время выполнения, сравнивать производительность и выбирать самый эффективный алгоритм. После занятия ваш код станет быстрее, а техническое интервью — проще.
Регистрируйтесь сейчас — урок проходит перед стартом курса «C# Developer»: https://otus.pw/yQzK/?erid=2W5zFJSuoQ4
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
Проблема: cортировка больших массивов может быть неэффективной при использовании простых алгоритмов, таких как сортировка пузырьком или вставками.
Решение: Автор в книге Algorithms and Data Structures for OOP With C# демонстрирует реализацию QuickSort — одного из самых эффективных алгоритмов сортировки на практике, с рекурсивным разбиением массива.
Пример кода:
public class QuickSortExample
{
public void QuickSort(int[] arr, int low, int high)
{
if (low < high)
{
int pi = Partition(arr, low, high);
QuickSort(arr, low, pi - 1);
QuickSort(arr, pi + 1, high);
}
}
private int Partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j < high; j++)
{
if (arr[j] < pivot)
{
i++;
(arr[i], arr[j]) = (arr[j], arr[i]);
}
}
(arr[i + 1], arr[high]) = (arr[high], arr[i + 1]);
return i + 1;
}
}
Преимущества:
— Быстрая сортировка даже больших наборов данных
— Средняя сложность O(n log n)
— Эффективное использование памяти за счет рекурсии
Please open Telegram to view this post
VIEW IN TELEGRAM