🎯 Нестандартные форматы резюме
Листайте карточки и подбирайте вариант резюме под свои навыки. В комментах можете поделиться своими проектами 👇
➡️ В статье ещё два формата
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
Листайте карточки и подбирайте вариант резюме под свои навыки. В комментах можете поделиться своими проектами 👇
📍 Навигация: Вакансии • Задачи • Собесы
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁7👍5🤔2
LangGraph vs Semantic Kernel: архитектура агентов
В .NET мире популярен Semantic Kernel, но индустрия движется к графовым подходам.
Архитектурные преимущества:
— цикличность: нативная поддержка циклов (ReAct pattern);
— state management: управление контекстом похоже на работу с сессиями;
— human-in-the-loop: возможность поставить граф на паузу, получить апрув человека и продолжить.
Курс по архитектуре уже стартовал.
Записаться на курс
Смотреть первую лекцию бесплатно
В .NET мире популярен Semantic Kernel, но индустрия движется к графовым подходам.
LangGraph реализует паттерн, где агент — это не просто цепочка плагинов, а граф с состоянием.Архитектурные преимущества:
— цикличность: нативная поддержка циклов (ReAct pattern);
— state management: управление контекстом похоже на работу с сессиями;
— human-in-the-loop: возможность поставить граф на паузу, получить апрув человека и продолжить.
Курс по архитектуре уже стартовал.
Записаться на курс
Смотреть первую лекцию бесплатно
👍6❤1
В .NET для HTTP-запросов фабрика
IHttpClientFactory упрощает создание клиентов, интегрируется с DI и решает проблемы вроде утечек сокетов.Фабрика кэширует обработчики сообщений, управляет их временем жизни и добавляет логирование.
Зачем нужна фабрика
HttpClient из Framework 4.5 часто создают вручную, но это приводит к проблемам: сокеты не освобождаются, DNS не обновляется. Фабрика решает это через пул обработчиков с лайфтаймом в 2 минуты по умолчанию.
Она регистрируется через
AddHttpClient в IServiceCollection и дает доступ к CreateClient. Короткоживущие клиенты подходят для большинства случаев, в отличие от долгоживущих с PooledConnectionLifetime.Предупреждение: если нужны куки, лучше обойтись без фабрики из-за шаринга
CookieContainer.Способы использования
Разработчики выбирают между базовым, именованными, типизированными клиентами или сгенерированными через Refit.
В базовом варианте инжектят
IHttpClientFactory и вызывают CreateClient для каждого запроса. Это просто для рефакторинга старого кода.Именованные клиенты настраивают по имени из конфига, с базовым URI и заголовками вроде User-Agent:
builder.Services.AddHttpClient("MyClient", client =>
{
client.BaseAddress = new Uri("https://api.example.com/");
client.DefaultRequestHeaders.UserAgent.ParseAdd("MyApp");
});Затем
CreateClient("MyClient").Типизированные удобны для конкретного API: класс принимает
HttpClient в конструкторе, фабрика регистрирует его через AddHttpClient<T>.Логика запросов инкапсулируется в методах класса, DI все подхватывает. IntelliSense работает, нет строковых ключей.
Не используйте в синглтонах: клиент должен быть короткоживущим, иначе DNS не обновится. Лучше именованные или SocketsHttpHandler:
public class ApiService(HttpClient client)
{
public async Task<Todo[]> GetTodos(int id) =>
await client.GetFromJsonAsync<Todo[]>($"todos/{id}");
}
В итоге фабрика делает HTTP-клиенты в .NET предсказуемыми и масштабируемыми. Для прода это как стандарт: меньше багов с соединениями, проще DI.
📍 Навигация: Вакансии • Задачи • Собесы
#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
🧑💻 Неявная проверка на null
В C# можно заставить любой класс вести себя в if как в JavaScript: просто if (myObject) и внутри проверка на null. Это работает благодаря перегрузке операторов.
Создайте класс с двумя статическими методами:
Теперь
Единственный минус: никто не ожидает такого, код становится загадкой для команды. Лучше стандартные
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view
В C# можно заставить любой класс вести себя в if как в JavaScript: просто if (myObject) и внутри проверка на null. Это работает благодаря перегрузке операторов.
Создайте класс с двумя статическими методами:
public class User
{
public string Name { get; set; }
public static bool operator true(User? user) => user?.Name != null;
public static bool operator false(User? user) => user?.Name == null;
}
Теперь
if (user) сработает если имя задано, иначе попадет в else. Компилятор автоматически вызывает нужный оператор при булевом контексте.Единственный минус: никто не ожидает такого, код становится загадкой для команды. Лучше стандартные
is not null или !ReferenceEquals(null, obj).📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15😢12😁6🌚2
Класс
Random в .NET генерирует псевдослучайные числа для игр, тестов или симуляций. Он работает на основе сида, обычно времени, и дает целые, дробные значения или байты.Основы класса Random
System.Random создает последовательности чисел через алгоритм. Для простого инта берут Next(min, max), где верхняя граница не включается.Переиспользуйте один экземпляр, иначе в цикле из-за одинаковых сидов выйдут повторения. Статический или инжектированный через DI вариант подходит для прода:
var rng = new Random();
int число = rng.Next(1, 101); // от 1 до 100
NextDouble возвращает от 0.0 до 1.0, умножьте и сдвиньте для нужного интервала. Байты через NextBytes заполняют массив. Это для тестовых файлов или симуляций.double температура = rng.NextDouble() * 50 - 10; // от -10 до 40
byte[] буфер = new byte[16];
rng.NextBytes(буфер);
Обычный
Random не годится для токенов или паролей, предсказуем при известном сиде. Берите RandomNumberGenerator из System.Security.Cryptography для криптографии.GetInt32(1, 101) или Fill для байт. В API для ключей всегда крипто-вариант.Random не потокобезопасен, общий экземпляр сломается. ThreadLocal<Random> создаст по инстансу на поток. Parallel.For с ним работает корректно, без гонок:var локальныйRng = new ThreadLocal<Random>(() => new Random());
Parallel.For(0, 100, i => {
int значение = локальныйRng.Value!.Next(100);
});
📍 Навигация: Вакансии • Задачи • Собесы
#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤5
📰 Дайджест недели
В .NET-среде штиль, новостей не так много, поэтому вспоминаем лучшее за неделю.
— IoT на .NET
— ExecuteUpdate и ExecuteDelete
— Коты вместо HTTP статусов
— 10 советов по обустройству вашего рабочего места
— Нестандартные форматы резюме
Делитесь в комментах своими инфоповодами недели 👇
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
В .NET-среде штиль, новостей не так много, поэтому вспоминаем лучшее за неделю.
— IoT на .NET
— ExecuteUpdate и ExecuteDelete
— Коты вместо HTTP статусов
— 10 советов по обустройству вашего рабочего места
— Нестандартные форматы резюме
Делитесь в комментах своими инфоповодами недели 👇
📍 Навигация: Вакансии • Задачи • Собесы
#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Anonymous Poll
8%
Боксинг в C#
4%
Паттерны не для облаков
7%
История про DLQ в PostgreSQL
7%
IOT на .NET
9%
Docker для быстрого развёртывания
4%
ExecuteUpdate и ExecuteDelete
6%
Фича флаги в .NET
9%
Фабрика HttpClient
35%
JS-стиль в C#
12%
Генерация случайных чисел
🥱4👾2
Semantic Kernel или LangGraph?
В мире .NET популярен
Это позволяет реализовывать сложные паттерны: Human-in-the-loop (человек подтверждает действие), Time Travel (откат состояния назад) и цикличное планирование. Понимание этих принципов пригодится любому разработчику, внедряющему AI.
Записаться на курс
Погружение в архитектуру агентов: Смотрите вводный урок бесплатно.
В мире .NET популярен
Semantic Kernel, но глобальный стандарт задаёт LangGraph. Его киллер-фича — явное управление графом выполнения и состоянием (Stateful Graph).Это позволяет реализовывать сложные паттерны: Human-in-the-loop (человек подтверждает действие), Time Travel (откат состояния назад) и цикличное планирование. Понимание этих принципов пригодится любому разработчику, внедряющему AI.
Записаться на курс
Погружение в архитектуру агентов: Смотрите вводный урок бесплатно.
❤5🤔1
Инлайнинг (Inlining) — замена вызова метода его телом напрямую в месте вызова. JIT-компилятор делает это автоматически для маленьких методов, которые весят меньше 32 байт.
Зачем это делается
• Убирает overhead вызова метода
• Улучшает локальность кода
• Даёт прирост в 5-7 раз для горячих путей
Пример
Без инлайнинга:
public int Calculate(int a, int b)
{
return Add(a, b) * 2;
}
private int Add(int a, int b) // JIT заинлайнит автоматически
{
return a + b;
}
Что делает JIT:
public int Calculate(int a, int b)
{
return (a + b) * 2; // тело Add() вставлено напрямую
}
Принудительный инлайнинг:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int Multiply(int a, int b)
{
return a * b;
}
Не гадайте — профилируйте. Иногда JIT делает лучше без вашей помощи.
📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤7🤔1🌚1
🆚 Namespace vs Assembly
Давайте разберёмся, чем отличается namespace от assembly.
Namespace — это логическая организация кода.
Assembly — это физический файл на диске.
Они существуют в разных измерениях и решают разные задачи.
Namespace (пространство имён) — это способ логической группировки классов, интерфейсов и других типов, чтобы избежать конфликтов имён:
Зачем нужны namespace
• Без namespace два класса с именем Logger конфликтуют. С namespace можно иметь
• Организация кода по доменам:
• Упрощённое использование кода с using
Можно объявить namespace один раз для всего проекта:
Что такое Assembly
Assembly (сборка) — это скомпилированный физический файл на диске .dll или .exe, который содержит IL-код и метаданные.
•
•
Как они связаны
Подключение сборки:
Это добавляет assembly в проект.
Использование namespace:
Один работает на уровне файлов, другой — на уровне кода.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#il_люминатор
Давайте разберёмся, чем отличается namespace от assembly.
Namespace — это логическая организация кода.
Assembly — это физический файл на диске.
Они существуют в разных измерениях и решают разные задачи.
Namespace (пространство имён) — это способ логической группировки классов, интерфейсов и других типов, чтобы избежать конфликтов имён:
namespace MyCompany.PaymentSystem
{
public class PaymentProcessor
{
// ...
}
}
namespace MyCompany.Logging
{
public class Logger
{
// ...
}
}
Зачем нужны namespace
• Без namespace два класса с именем Logger конфликтуют. С namespace можно иметь
MyApp.Logger и ThirdPartyLib.Logger одновременно.• Организация кода по доменам:
MyCompany.Ecommerce.Orders, MyCompany.Ecommerce.Products, MyCompany.Ecommerce.Payments.• Упрощённое использование кода с using
using MyCompany.Ecommerce.Orders;
var order = new Order(); // Вместо: new MyCompany.Ecommerce.Orders.Order()
Можно объявить namespace один раз для всего проекта:
// GlobalUsings.cs
global using System;
global using MyCompany.Core;
Что такое Assembly
Assembly (сборка) — это скомпилированный физический файл на диске .dll или .exe, который содержит IL-код и метаданные.
•
.exe — приложение, которое можно запустить.•
.dll — библиотека для подключения.Как они связаны
Подключение сборки:
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
Это добавляет assembly в проект.
Использование namespace:
using Newtonsoft.Json; // Импортируем namespace
var json = JsonConvert.SerializeObject(obj);
//или без using
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
Один работает на уровне файлов, другой — на уровне кода.
📍 Навигация: Вакансии • Задачи • Собесы
#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍8
🚀 Git v2.53
Вышла новая версия системы контроля версий Git v2.53. Разбираем ключевые изменения.
Новые команды
•
•
•
Улучшения существующих команд
•
•
•
И многие другие мелкие доработки.
➡️ Анонс
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#async_news
Вышла новая версия системы контроля версий Git v2.53. Разбираем ключевые изменения.
Новые команды
•
git maintenance is-needed — проверка, нужно ли выполнять задачи обслуживания репозитория.•
git repo info --all — показывает расширенную информацию о структуре репозитория.•
git blame --diff-algorithm=<algo> — теперь можно выбрать алгоритм сравнения при отслеживании изменений.Улучшения существующих команд
•
git replay — теперь выполняет обновление ссылок самостоятельно, не требуя дополнительных команд.•
git fast-import — новая опция --signed-commits=strip-if-invalid для удаления невалидных подписей.•
git apply и git diff — новый класс ошибок пробелов incomplete-line.И многие другие мелкие доработки.
📍 Навигация: Вакансии • Задачи • Собесы
#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Разберемся, как компилятор превращает понятный код в эффективный и почему лучше расписать «магическое число» на составляющие.
Самая простая оптимизация называется constant folding. Суть в том, что компилятор не будет заставлять процессор каждый раз высчитывать одно и то же. Если вы пишете
int result = 10 * 5 + 3 * 2, компилятор прекрасно понимает, что результат всегда будет 56, и именно это число окажется в скомпилированном коде.public void Example()
{
int result = 10 * 5 + 3 * 2; // Вы пишете это
// Компилятор превращает в:
int result = 56; // Уже посчитано
}
Более интересная оптимизация – constant propagation. Когда вы объявляете константу через const, компилятор запоминает её значение и подставляет его везде, где она используется.
public void ConstantPropagation()
{
const int multiplier = 100;
int value = 42;
int calculated = value * multiplier;
// Компилятор оптимизирует до:
int calculated = value * 100; // multiplier заменен значением
}
Оптимизация строк
С строками всё еще интереснее. Когда вы конкатенируете несколько строковых литералов, компилятор склеивает их в один. Код
string message = "Hello" + " " + "World"; превращается в string message = "Hello World";public void StringOptimization()
{
// Все литералы склеиваются в один
string message = "Hello" + " " + "World";
// Результат: string message = "Hello World";
// С константами тоже работает частично
const string greeting = "Hello";
string name = "Alice";
string message = greeting + " " + name;
// Результат: string message = "Hello " + name;
}
Используйте
const там, где это уместно, не бойтесь записывать формулы явно вместо магических чисел – компилятор сам посчитает результат.📍 Навигация: Вакансии • Задачи • Собесы
#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥3🥱2
Вы ищете заказы там, где их ищут все. А локальный бизнес даже не знает о существовании биржи. ИП пишут в чатах «посоветуйте программиста» или листает Авито. Будьте там, где нет толпы.
📍 Навигация: Вакансии • Задачи • Собесы
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰3❤2
Senior .NET Engineer — до 450 000₽ с удалёнкой.
C# разработчик на удалёнку с ЗП до 250 000 ₽
C#/.NET-разработчик — удалёнка.
📍 Навигация: Вакансии • Задачи • Собесы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤖 Миграция с GitHub
Если следите за IT-комьюнити, то наверняка замечали: всё больше программистов переезжают с GitHub. Недавно оттуда мигрировали язык программирования Zig и инструмент Leiningen, а за ними — сотни индивидуальных разработчиков.
В чём проблема
• GitHub стал хуже технически
После покупки Microsoft в 2018 платформа деградирует: интерфейс грузится дольше, GitHub Actions запускает джобы случайно и сам интерфейс раздут до безобразия.
• Copilot — это плагиат
GitHub Copilot буквально выдаёт куски кода дословно. Это нарушение лицензий и воровство чужого кода. Software Freedom Conservancy (те, кто поддерживают Wine, Git, QEMU) организовали кампанию «Give Up GitHub» именно из-за этого.
• Закрытая платформа для открытого кода
Парадокс: серверная часть GitHub — проприетарный софт. Вы размещаете open-source проекты на закрытой платформе, которую контролирует Microsoft.
В отличие от Instagram или Twitter, GitHub не контролирует дистрибуцию контента. Уход с GitHub — это небольшая неудобство для контрибьюторов, но не исчезновение из поля зрения.
Куда переезжать
Бесплатно и с хостингом:
• Codeberg (Forgejo) — некоммерческий проект, для FOSS
• SourceHut — платно $4-12/мес, но есть финпомощь
• GitLab — бесплатный тариф с ограничениями
Самохостинг:
• Gitea — простой и лёгкий
• Gogs — ещё проще
• Gerrit — если нужен продвинутый code review
Децентрализация:
• Radicle — p2p git
• Или просто свой скрипт, заливающий в S3
💬 Где вы держите свои проекты?
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#entry_point
Если следите за IT-комьюнити, то наверняка замечали: всё больше программистов переезжают с GitHub. Недавно оттуда мигрировали язык программирования Zig и инструмент Leiningen, а за ними — сотни индивидуальных разработчиков.
В чём проблема
• GitHub стал хуже технически
После покупки Microsoft в 2018 платформа деградирует: интерфейс грузится дольше, GitHub Actions запускает джобы случайно и сам интерфейс раздут до безобразия.
• Copilot — это плагиат
GitHub Copilot буквально выдаёт куски кода дословно. Это нарушение лицензий и воровство чужого кода. Software Freedom Conservancy (те, кто поддерживают Wine, Git, QEMU) организовали кампанию «Give Up GitHub» именно из-за этого.
• Закрытая платформа для открытого кода
Парадокс: серверная часть GitHub — проприетарный софт. Вы размещаете open-source проекты на закрытой платформе, которую контролирует Microsoft.
В отличие от Instagram или Twitter, GitHub не контролирует дистрибуцию контента. Уход с GitHub — это небольшая неудобство для контрибьюторов, но не исчезновение из поля зрения.
Куда переезжать
Бесплатно и с хостингом:
• Codeberg (Forgejo) — некоммерческий проект, для FOSS
• SourceHut — платно $4-12/мес, но есть финпомощь
• GitLab — бесплатный тариф с ограничениями
Самохостинг:
• Gitea — простой и лёгкий
• Gogs — ещё проще
• Gerrit — если нужен продвинутый code review
Децентрализация:
• Radicle — p2p git
• Или просто свой скрипт, заливающий в S3
💬 Где вы держите свои проекты?
📍 Навигация: Вакансии • Задачи • Собесы
#entry_point
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9😁7👍4
☝️ Не повторяйтесь
Принцип DRY (Don't Repeat Yourself) — один из самых известных в программировании. Но, как и любой принцип, его можно применять неправильно. Давайте разберёмся, когда следовать DRY, а когда от него отступить.
Признаки over-DRYing
• Функция с 5+ параметрами:
• Generic Repository:
Когда дублирование правильно
• Случайное совпадение:
• Разные контексты:
Повторите код три раза, прежде чем рефакторить:
Первый раз — пишите
Второй раз — терпите
Третий раз — рефакторьте
Дублирование в тестах — нормально:
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view
Принцип DRY (Don't Repeat Yourself) — один из самых известных в программировании. Но, как и любой принцип, его можно применять неправильно. Давайте разберёмся, когда следовать DRY, а когда от него отступить.
Признаки over-DRYing
• Функция с 5+ параметрами:
// Универсальная функция-монстр
public async Task<object> FetchDataAsync(
string entityType, int? id, string filter,
int pageSize, bool includeDeleted, params string[] includes) { }
// Специализированные методы
public async Task<List<User>> GetActiveUsersAsync(int page, int pageSize)
=> await _context.Users.Where(u => u.IsActive)
.Skip(page * pageSize).Take(pageSize).ToListAsync();
• Generic Repository:
// Кажется умным, но бесполезен
public interface IRepository<T> where T : class
{
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
}
// Специфичный и полезный
public interface IUserRepository
{
Task<User> GetByEmailAsync(string email);
Task<User> GetWithOrdersAsync(int id);
}
Когда дублирование правильно
• Случайное совпадение:
// НЕ объединяйте! Разные бизнес-концепции
public string FormatUserName(User u) => $"{u.FirstName} {u.LastName}";
public string FormatProductName(Product p) => $"{p.Brand} {p.Model}";
• Разные контексты:
// UI: простая проверка
public bool ValidateEmail(string email) => email.Contains("@");
// API: строгая проверка
public bool ValidateEmail(string email) =>
Regex.IsMatch(email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
Повторите код три раза, прежде чем рефакторить:
Первый раз — пишите
Второй раз — терпите
Третий раз — рефакторьте
Дублирование в тестах — нормально:
[Fact]
public void CreateUser_ShouldSucceed()
{
var user = new User { Name = "Alice", Age = 25 };
Assert.Equal("Alice", _service.CreateUser(user).Name);
}
[Fact]
public void UpdateUser_ShouldSucceed()
{
var user = new User { Name = "Alice", Age = 25 }; // OK
// Читаемость важнее DRY
}
📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔10👍6❤2😁1
Microsoft выпустили разбор про то, как работать с AI в .NET. Если вы думали, что интеграция LLM — это боль и каша из разных SDK, вот хорошие новости.
Microsoft.Extensions.AI — один API для всех
Работаете с OpenAI — один SDK. Решили попробовать Ollama — другой API. Захотели Azure OpenAI — третий подход. Microsoft решили эту проблему радикально: один интерфейс для всех провайдеров.
IChatClient client = ...; // любой провайдер
await foreach (var update in client.GetStreamingResponseAsync("How are you?"))
{
Console.Write(update);
}
Раньше, чтобы получить структурированный JSON, нужно было плясать с бубном и JSON Schema. Теперь:
record Family(List<Person> Parents, List<Person>? Children);
record Person(string Name, int Age);
var family = await client.GetResponseAsync<Family>(
[
new ChatMessage(ChatRole.System, "You are an AI assistant..."),
new ChatMessage(ChatRole.User, "Create a family with 2 parents...")
]);
Схему сгенерируют за вас, JSON распарсят, десериализуют.
Хотите отправить фото для анализа? Обойдёмся без сотни строк:
var image = new DataContent(File.ReadAllBytes(@"photo.jpg"), "image/jpeg");
var messages = new List<ChatMessage>
{
new(ChatRole.System, "You are a photo analyst..."),
new(ChatRole.User, [prompt, image])
};
record ImageAnalysis(string Description, string[] Tags);
var analysis = await client.GetResponseAsync<ImageAnalysis>(messages);
Работает с изображениями, аудио и видео.
Один API, middleware, типизация, телеметрия. Можно не изобретать велосипед при каждой смене провайдера.
📍 Навигация: Вакансии • Задачи • Собесы
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍38