.NET Разработчик
6.51K subscribers
427 photos
2 videos
14 files
2.04K links
Дневник сертифицированного .NET разработчика.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1649. #юмор
👍27
День 1650. #ЗаметкиНаПолях
Используем Дискриминатор в Entity Framework
Допустим вы создаёте систему управления школой, в которой есть разные типы сотрудников Учитель и Администратор. Они имеют как общие свойства (Id, Имя, Дата найма), так и уникальные (например, Предмет у учителя и Отдел у администратора).
public class Staff
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}

public class Teacher : Staff
{
public string Subject { get; set; }
}
public class Administrator : Staff
{
public string Department { get; set; }
}

Если вы хотите получить всех сотрудников, вам нужно сделать отдельные свойства контекста и запросы для учителей и администраторов:
var teachers = context.Teachers.ToList();
var admins = context.Administrators.ToList();

Это требует не только больше кода, но и ручного управления этими отношениями. Для общих операций придётся дважды написать один и тот же код для учителей и администраторов. Также может быть сложнее поддерживать согласованность данных, особенно если в будущем появится больше типов сотрудников.

Столбец-дискриминатор в используется в сценариях наследования Table-per-Hierarchy, для представления отношений наследования в реляционной БД. Он предполагает использование одной таблицы для представления всех различных типов в иерархии со специальным столбцом (дискриминатор) для различения типов.
public class SchoolContext : DbContext
{
public DbSet<Staff> StaffMembers { get; set; }

protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Staff>()
.HasDiscriminator<string>("StaffType")
.HasValue<Teacher>("Teacher")
.HasValue<Administrator>("Administrator");
}
}
В методе OnModelCreating мы вызываем HasDiscriminator для настройки столбца-дискриминатора, задавая ему имя (StaffType) и тип. Метод HasValue позволяет указать, какие значения следует использовать для представления каждого типа в иерархии.

Теперь в запросах StaffMembers EF Core будет использовать столбец-дискриминатор для правильного создания экземпляров Teacher или Administrator в зависимости от ситуации.
var staff = context.StaffMembers.ToList();
foreach (var s in staff)
{
switch (s)
{
case Teacher t:

case Administrator a:

}
}
Также можно добавлять экземпляры этих классов, и EF Core автоматически задаст нужное значение дискриминатора при вставке строки в БД.

Преимущества
1. Простота. Одна таблица для всей иерархии может упростить понимание и поддержку схемы БД.
2. Повторное использование кода. Общие операции для всех типов используют один и тот же код.
3. Производительность. Часто можно получить данные с меньшим числом обращений к БД.

Недостатки
1. Неиспользуемое пространство. В одной таблице должны быть столбцы для всех свойств всех типов в иерархии, даже если некоторые типы не используют определенные свойства.
2. Ограниченная гибкость. Подход может стать сложным, если у вас сложная иерархия наследования или если нужно смоделировать отношения «многие-ко-многим» между различными типами.
3. Целостность данных. С одной таблицей сложнее обеспечить целостность данных на уровне БД. Например, вы не можете запретить строке, которая должна представлять учителя, иметь значение в столбце «Отдел» (который должен быть специфичным для администраторов).

Источник: https://stefandjokic.tech/blog/
👍9
День 1651. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Начало
Возможность включать или отключать функции в приложениях без повторного развёртывания кода — мощный инструмент, который можно использовать для быстрой итерации новых функций.

Флаги функций — это метод разработки ПО, который позволяет заключать функции приложения в условный блок, предоставляя переключатель для включения или отключения функции. Главное – возможность переключать функции во время выполнения, т.е. не нужно повторно развёртывать приложение.

Преимущества
1. Возможность развёртывать новые функции в производственных средах в отключённом состоянии. Так мы можем гарантировать, что наша новая функция не повлияет на остальную часть приложения, прежде чем мы включим её для всех пользователей.
2. Канареечное развёртывание — возможность постепенно увеличивать использование новой функции, чтобы гарантировать отсутствие последствий для производительности или каких-либо других ошибок в коде.
3. A/B-тестирование — определение реакции пользователей на новую функцию. Например, новый UI предоставляется только определённой группе пользователей, чтобы увидеть, предпочтут ли они его старому UI.

Виды
1. Логический фильтр – функция включена/выключена.
2. Фильтр по времени - функция активна только между заданным временем начала и окончания.
3. Процентный фильтр - процент определяет вероятность того, что функция включена.
4. Фильтр таргетинга - определяет правила включения функций на основе целевой аудитории.
5. Собственные настраиваемые фильтры.

Использование флагов функций в ASP.NET Core
Для начала добавим пакет Microsoft.FeatureManagement.AspNetCore. Он под капотом управляет жизненным циклом флагов функций. Это даёт нам возможность изменять флаги функций во время выполнения без необходимости перезапуска приложения.

1. Логический фильтр
Добавим фильтр функций в appsettings.json:
{
"FeatureManagement": {
"BoolFeature": true
}
}
NuGet пакет будет по умолчанию искать секцию FeatureManagement. Мы добавили фильтр функции BoolFeature и задали ему значение «включено».

Добавим FeatureManagment в классе Program:
builder.Services.AddFeatureManagement();

Проверим, как это работает:
public class FeatureController : ControllerBase
{
private IFeatureManager featureMgr;
public FeatureController(IFeatureManager fm)
{
featureMgr = fm;
}

public async Task<IActionResult> BoolFeature()
{
if (await featureMgr.IsEnabledAsync("BoolFeature"))
return Ok("Enabled");
else
return BadRequest("Disabled");
}
}

Если перейти на /Feature/BoolFeature, мы увидим результат Ok. Теперь, пока приложение работает, изменим значение BoolFeature на false и повторим запрос. На этот раз мы получим 400 BadRequest.

Продолжение следует…

Источник:
https://code-maze.com/aspnetcore-feature-flags/
👍25👎1
День 1652. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Продолжение
Начало

2. Фильтр по времени
Если мы хотим, чтобы функция была включена только в течение определённого временного окна, используем TimeWindowFilter.
Сначала зарегистрируем фильтр:
builder.Services.AddFeatureManagement()
.AddFeatureFilter<TimeWindowFilter>();

В appsettings.json, определим конфигурацию:
"FeatureManagement": {
// …
"TimeFeature": {
"EnabledFor": [
{
"Name": "TimeWindow",
"Parameters": {
"Start": "2023-08-09T09:00:00+03:00",
"End": "2023-08-24T11:00:00+03:00"
}
}
]
}
}
Функция TimeFeature будет включена с 09:00 (Мск) 09.08.2023 до 11:00 (Мск) 24.08.2023. Проверка работы функции аналогична логическому фильтру.

3. Процентный фильтр
Аналогично фильтру по времени, нужно добавить его в сервисы:
 ….AddFeatureFilter<PercentageFilter>();
И в appsettings.json:
"FeatureManagement": {
"PercentFeature": {
"EnabledFor": [
{
"Name": "Percentage",
"Parameters": {
"Value": 50
}
}
]
}
}
Эта функция будет «включена» в 50% случаев.

4. Фильтр таргетинга
Фильтры таргетинга позволяют включить функцию для определённых пользователей или групп. Как обычно, нам нужно зарегистрировать фильтр таргетинга:
….AddFeatureFilter<TargetingFilter>();
И добавить настройку в appsettings.json:
"FeatureManagement": {
"TargetFeature": {
"EnabledFor": [
{
"Name": "Targeting",
"Parameters": {
"Audience": {
"Users": [],
"Groups": [
{
"Name": "Beta Testers",
"RolloutPercentage": 20
}
]
}
}
}
]
}
}
Здесь функция TargetFeature будет доступна для 20% пользователей из группы "Beta Testers". В Users можно задать список Id отдельных пользователей.

Также мы должны добавить логику определения аудитории. Для этого нужно создать сервис реализующий интерфейс ITargetingContextAccessor и зарегистрировать его в DI.
Интерфейс содержит один метод GetContextAsync(), возвращающий ValueTask<TargetingContext>. TargetingContext, в свою очередь, содержит свойства:
- UserId (строка) – сопоставляется со списком Users в appsettings,
- Groups (коллекция строк) – сопоставляется со списком Groups.
Для определения Id или группы для текущего пользователя, в сервис, реализующий ITargetingContextAccessor, можно внедрить IHttpContextAccessor (об этом завтра).

Продолжение следует…

Источник:
https://code-maze.com/aspnetcore-feature-flags/
👍8
День 1653.
MOQ-Гейт или Закрытый-Открытый Код

🔥 BRKNG!!!
🔥

Мы прерываем нашу программу… Короче, не мог пройти мимо. Вчера в интернетах разгорелся нешуточный срач вокруг популярнейшего пакета для создания фиктивных объектов в тестах Moq.

Один из пользователей Reddit написал следующий пост:
Я только что обновил Moq в одном из наших проектов и после сборки получил предупреждение о том, что я не установил приложение GitHub Sponsors.
После небольшого расследования выяснилось, что Moq, начиная с версии 4.20, включает в себя анализатор .NET, который сканирует вашу локальную конфигурацию git при сборке, получает ваш email и отправляет его в какой-то сервис в Azure, чтобы проверить, действительно ли вы спонсор.

Потом в GitHub проекта появилась новая ишью:
Похоже, начиная с версии 4.20 в проект добавлена зависимость SponsorLink. Это проект с закрытым кодом, представленный в виде dll с обфусцированным кодом (sic!), который, кажется, сканирует локальные данные (git config?) и отправляет хешированный адрес электронной почты текущего разработчика в облачный сервис. Сканирование предоставляется как инструмент анализатора .NET, который запускается во время сборки. Нет возможности его отключить.
Я могу понять причину этого, но, честно говоря, это довольно страшно с точки зрения конфиденциальности.

Насколько я понял, суть в следующем.
Спонсорство – это фича гитхаба по поддержке разработчиков проектов с открытым кодом. SponsorLink – отдельный пакет от разработчика Moq, работающий как анализатор кода в IDE и проверяющий при сборке проекта, являетесь ли вы спонсором используемого вами пакета с открытым кодом. Если нет, он выдаёт предупреждение компилятора с предложением стать спонсором и ссылкой на спонсорство. Если да, выдаётся благодарственное сообщение. При использовании в терминале или CI/CD, он не делает ничего, таким образом не мешая процессу.

Автор утверждает, что опросил знакомых разработчиков, и идею поддержали, однако лично у меня возникают вопросы по поводу того, так ли это надо. Если в теории за спонсорство анализатор будет «открывать» какие-то новые фишки в пакете (видимо, такая и была задумка на будущее). Впрочем, я отвлёкся.

Однако, как обычно, благими намерениями. Реализация этой проверки спонсорства, собственно, и вызвала бурление. Анализатор (без предупреждения) запускает фоновый процесс, который сканирует параметры вашего git репозитория, находит там email пользователя (по другим данным – все email адреса из истории проекта) и отправляет его по сети в облачный сервис для проверки спонсорства. Вот тут вопросов гораздо больше. В первую очередь это нарушает некоторые законы о защите персональных данных, ведь всё это происходит без согласия и даже без уведомления пользователя. Во-вторых, что там реально происходит, и действительно ли отправляется только email и туда ли, куда говорит автор, посмотреть нельзя, т.к. код самого SponsorLink закрыт. В-третьих, email в настройках git может быть корпоративным и не для публичного распространения. В-четвёртых, даже запретить пакету это делать нельзя.

В общем, получить такую интересную закрытую зависимость, просто обновив широко известный пакет «с открытым исходным кодом» - то ещё удовольствие. Автору справедливо накидали полную панамку… ишьюсов и репортов в NuGet, и проблемная версия Moq 4.20.1 была удалена из репозитория NuGet. Вместо неё вчера появилась версия 4.20.2, в которой заявлено, что ссылка на зависимость от SponsorLink была удалена.

Можете также посмотреть, как Ник Чапсас довольно смешно бомбит с этого.

Источник: https://www.reddit.com/r/dotnet/comments/15ljdcc/does_moq_in_its_latest_version_extract_and_send/
👍32
День 1654. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Продолжение 2
Начало
Продолжение 1

5. Собственные фильтры
Если встроенных фильтров функций недостаточно, у нас есть возможность написать собственные фильтры, реализовав IFeatureFilter. Создадим фильтр, позволяющий использовать функцию только клиентам, у которых установлен определённый язык:
"FeatureManagement": {
"LangFeature": {
"EnabledFor": [
{
"Name": "LangFilter",
"Parameters": {
"AllowedLangs": [
"en-US", "ru-RU"
]
}
}
]
}
}

Мы определяем функцию LangFeature и фильтр LangFilter для неё, добавляя в параметры массив AllowedLangs с языками, для которых функция включена.

Создадим LangFilter:
[FilterAlias(nameof(LangFilter))]
public class LangFilter : IFeatureFilter
{
private IHttpContextAccessor _hCA;
public LangFilter(IHttpContextAccessor hCA)
{
_hCA = hCA;
}
public Task<bool> EvaluateAsync(
FeatureFilterEvaluationContext ctx)
{
var userLang = _hCA
.HttpContext
.Request
.Headers["Accept-Language"]
.ToString();
var settings = ctx
.Parameters
.Get<LangFilterSettings>();

return Task.FromResult(
settings.AllowedLangs
.Any(a => userLang.Contains(a)));
}
}
Сначала внедряем IHttpContextAccessor. Это позволит нам получить доступ к заголовку Accept-Language из запроса пользователя.
Мы реализуем интерфейс IFeatureFilter, который даёт нам метод EvaluateAsync(). В этом методе мы проверяем язык пользователя по параметрам (settings), определённым в appsettings.json, и возвращаем true, если язык есть в списке. Параметры фильтра в строго типизированном виде нам помогает получить класс FeatureFilterEvaluationContext. Создадим простой класс LangFilterSettings для хранения массива AllowedLangs:
public class LangFilterSettings
{
public string[] AllowedLangs { get; set; }
}

Прежде чем протестировать наш фильтр, нужно зарегистрировать в сервисах его и HttpContextAccessor:
builder.Services.AddFeatureManagement()
.AddFeatureFilter<LangFilter>();
builder.Services.AddHttpContextAccessor();

Проверка аналогична проверке логического фильтра:
public async Task<IActionResult> LangFeature()
{
if (await featureMgr.IsEnabledAsync("LangFeature"))
return Ok("Enabled");
else
return BadRequest("Disabled");
}

Окончание следует…

Источник:
https://code-maze.com/aspnetcore-feature-flags/
👍8
День 1655. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Окончание
Начало
Продолжение 1
Продолжение 2

Другие способы проверки флагов функций
Интерфейс IFeatureManager и блок if-else - не единственный метод проверки флагов функций. Вот несколько других.

1. Атрибут FeatureGate
В ASP.NET Core есть возможность помечать конечные точки или контроллеры атрибутом флага функции FeatureGate:
[FeatureGate("BoolFeature")]
public IActionResult BoolFeature()
{ … }
Здесь конечная точка BoolFeature помечена атрибутом флага функции BoolFeature (имена не обязательно должны совпадать). Если функция отключена, при обращении к этой конечной точке мы получим 404 NotFound. Это код ответа по умолчанию, но поведение можно настроить, создав обработчик отключённых функций, реализующий IDisabledFeaturesHandler.
Кроме того, в атрибуте можно указывать несколько функций через запятую, а также задать, должны ли они быть включены все либо хотя бы одна с помощью перечисления RequirementType.

2. Промежуточное ПО
Если наша функция более сложная и затрагивает промежуточное ПО приложения, мы можем условно добавить её с помощью флагов функций:
app.UseMiddlewareForFeature<MyMiddlewareFeature>(
"MyMiddlewareFeatureFlag");

При этом MyMiddlewareFeature будет добавлена в конвейер только в том случае, если MyMiddlewareFeatureFlag включен.

3. Представления MVC
Если в приложении MVC нам нужно условно показать или скрыть фрагмент пользовательского интерфейса в зависимости от состояния флага функции, ASP.NET Core предоставляет для этого простой способ:
<feature name="MyUIFeature">
<p>Отображается, если MyUIFeature включена.</p>
</feature>
<feature name="MyUIFeature" negate="true">
<p>Отображается, если MyUIFeature отключена.</p>
</feature>
<feature name="FeatureA, FeatureB" requirement="All">
<p>Отображается, если обе функции включены.</p>
</feature>

Для этого надо добавить тэг-хелпер в файл _ViewImports.cshtml:
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

4. Azure App Configuration
Когда мы развёртываем приложение, использовать appsettings.json - не самый идеальный сценарий. Вместо этого мы можем использовать что-то вроде Azure App Configuration для независимого управления флагами функций. Это предпочтительно, поскольку нам предоставляется пользовательский интерфейс для управления функциями, и это означает, что не нужно вручную изменять файл appsettings.json приложения.

Источник: https://code-maze.com/aspnetcore-feature-flags/
👍9
DotNext 2023 — крупнейшая в России конференция для .NET-разработчиков

Вас ждут два дня офлайна и возможность подключиться к онлайн-трансляции. В программе — несколько десятков докладов о практике .NET-разработки, воркшоп и fail-митап, на котором спикеры расскажут о неудачах компаний — без записи и без комплексов.

Кроме этого, DotNext — это живые дискуссии, возможность познакомиться со спикерами и другими участниками, а также обсудить .NET-разработку и другие рабочие вопросы в неформальной обстановке.

Поскольку я решил посетить конференцию офлайн, разыграю среди желающих онлайн-билет. Условия простые: подписка на канал и комментарий "хочу билет" к этому посту.
Единственное условие - не просите ради прикола, а реально используйте (посмотрите хотя бы в записи).
Победителя выберу рандомом через несколько дней.
👍7
День 1656. #PostgresTips
Советы по Postgres для Начинающих

4. Ведение журнала: настройте параметры как можно раньше
Как и во многих других системах, в Postgres журналы — это кладезь информации, дающий вам подробное представление о работе системы и потенциальных проблемах. Включив всестороннее ведение журналов, вы сможете избежать проблем, оптимизировать производительность и обеспечить общую работоспособность вашей базы данных.

Что логировать
Ключ к эффективному ведению журнала — это знать, что записывать, не перегружая систему. Установив такие параметры, как
log_checkpoints = on,
log_autovacuum_min_duration = 0,
log_temp_files = 0,
log_lock_waits = on
вы получаете видимость контрольных точек, операций автоочистки, создания временных файлов и ожидания блокировки. Это некоторые из наиболее распространённых областей, в которых могут возникнуть проблемы, что делает их крайне важными для мониторинга.

Баланс между информативностью и избыточностью
Важно отметить, что, хотя детальное ведение журнала может предоставить ценную информацию, оно также может привести к накладным расходам. Это особенно верно, если вы установите log_min_duration_statement на очень низкое значение. Например, если установить его на 200мс, запрос будет логироваться дольше, чем выполняться, что может как повысить информативность, так и потенциально снизить производительность. Всегда будьте осторожны и помните об «эффекте наблюдателя» — влиянии процесса мониторинга на наблюдаемую систему. Но без детальной информации из журналов диагностика проблем была бы намного сложнее.

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

5. Улучшите наблюдаемость с помощью расширений
Когда вы стремитесь поддерживать производительность и работоспособность Postgres, расширения могут серьёзно помочь. Среди них pg_stat_statements выделяется как обязательный элемент, который не подлежит обсуждению.

pg_stat_statements предоставляет средства для отслеживания статистики выполнения всех операторов SQL, успешно выполненных сервером. Проще говоря, это помогает отслеживать, какие запросы выполняются часто, какие занимают больше времени, а какие могут нуждаться в оптимизации. С помощью этого расширения вы можете посмотреть на работу вашей базы данных, обнаруживать и исправлять неэффективности.

Существуют и другие примечательные расширения, которые могут предложить более глубокое понимание:
- pg_stat_kcache
Помогает понять фактическое использование дискового ввода-вывода и ЦП. С помощью него вы можете определить запрос, который отвечает за высокую загрузку ЦП или дисковый ввод-вывод.

- pg_wait_sampling или pgsentinel
Дают более чёткое представление о том, где запросы тратят время на ожидание, обеспечивая так называемый анализ событий ожидания, также известный как анализ истории активных сеансов.

- auto_explain
Автоматически регистрирует планы выполнения медленных операторов, что упрощает их понимание и оптимизацию.

Помните, что эти расширения требуют начальной установки и настройки, чтобы получить наилучшие результаты и снизить накладные расходы. И, к сожалению, большинство провайдеров Postgres не предоставляют pg_stat_kcache или pg_wait_sampling/pgsentinel.

Источник: https://postgres.ai/blog/20230722-10-postgres-tips-for-beginners
👍8
День 1657. #ЧтоНовенького
Улучшения Работы с Git в Visual Studio 2022 17.8 Превью 1
Вышла первая превью версия VS 17.8, в которую добавили пару интересных улучшений для работы с Git.

1. Добавление рецензентов в пул-реквесты
Теперь вы можете добавлять рецензентов в свои пул-реквесты в Visual Studio как для Azure DevOps, так и для GitHub.
Нажмите на ссылку Create a Pull Request (Создать Пул-Реквест), которая появляется после коммита или выберите Git > GitHub или Azure DevOps > New Pull Request в меню. Перейдите в раздел Reviewers (Рецензенты) и найдите рецензентов, которых вы хотите добавить.

2. Саммари изменений
Позволяет вам видеть только изменения в файле с несколькими строками контекста сверху и снизу, что делает просмотр изменений в коммите или сравнение между двумя файлами намного более эффективным.

Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-8-preview-1-has-arrived/
👍10👎1
День 1658. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#

20. Какие типы делегатов существуют в C#?

Делегаты в C# можно разделить на три основных типа:
1) Обычные
Ссылаются на один метод с соответствующей сигнатурой. Когда делегат вызывается, он вызывает указанный метод.
public delegate void DisplayMessage(string message);

DisplayMessage display = ShowMessage;
display("Hello, delegate!");

void ShowMessage(string message)
=> Console.WriteLine(message);

2) Многоадресные (Multicast)
Могут ссылаться на несколько методов с совпадающей сигнатурой. Когда делегат вызывается, он вызывает все указанные методы в том порядке, в котором они были добавлены. Многоадресные делегаты создаются из обычных с помощью операторов += или -=.
DisplayMessage display = ShowMessage1;
display += ShowMessage2;
display("Hello, Multicast delegate!");

void ShowMessage1(string msg)
=> Console.WriteLine($"Message 1: {msg}");
void ShowMessage2(string msg)
=> Console.WriteLine($"Message 2: {msg}");

3) Обобщённые
Используют параметры типа, что позволяет им работать с несколькими типами без приведения или упаковки/распаковки. C# предоставляет три встроенных обобщённых делегата: Func, Action и Predicate.
- Func<TResult>: представляет функцию с возвращаемым типом.
- Action: представляет метод, возвращающий void, без параметров.
- Predicate<T>: представляет метод, который принимает входной параметр и возвращает логическое значение.
Func и Action имеют перегрузки, принимающие большее количество аргументов.

Func<int, int, int> add = 
(x, y) => x + y;
int sum = add(10, 20);

Action<string> display =
msg => Console.WriteLine(msg);
display($"Sum: {sum}");

Predicate<string> startsWithHello =
x => x.StartsWith("Hello, ");
bool checkHello = startsWithHello("Hello, delegate");

См. также:
- Управление цепочками делегатов
- Анонимные методы
- Лямбда-выражения

Источник: https://dev.to/bytehide/20-c-interview-questions-for-experienced-2023-1hl6
👍28
День 1659. #МоиИнструменты
Веб-Инструменты для Каждого Разработчика
Сегодня поделюсь с вами подборкой веб-сайтов с инструментами, которые пригодятся каждому разработчику вне зависимости от области и языка программирования.

1. Transform.tools
Позволяет преобразовывать почти всё, например, HTML в JSX, JavaScript в JSON, CSS в объекты JS и многое другое. Действительно экономит время. К сожалению, отсутствует поддержка C#, поэтому JSON можно преобразовать разве что в объект Java, но с парочкой изменений руками (когда уже в Java человеческие свойства завезут?) потянет.

2. Convertio
Простой инструмент для конвертации файлов онлайн. Более 309 различных документов, изображений, электронных таблиц, электронных книг, архивов, презентаций, аудио и видео форматов. Например, PNG в JPEG, SVG в PNG, PNG в ICO и многие другие. Попробовал конвертнуть PDF книгу в DOCX. Очень даже неплохо. У бесплатной версии есть ограничение на общее время конвертации в день, но сколько это, я не нашёл. Думаю, для конвертации парочки файлов время от времени хватит.

3. Code Beautify
Онлайн версия программ Code Beautifier и Code Formatter, позволяющая форматировать исходный код. Но, кроме этого, также поддерживает некоторые преобразователи, такие как изображение в base64, CSV в Excel и т.п., минификаторы и обфускаторы кода для многих языков и много чего ещё.

4. Removebg
Мы программисты чаще всего плохо умеем в фотошоп, поэтому ловите инструмент, который позволяет легко удалить фон любого изображения. RemoveBG мгновенно определяет объект изображения и удаляет фон, оставляя изображение объекта на прозрачном фоне, которое вы можете легко использовать в своих проектах. Я попробовал его на паре фоток и должен отметить, что работает отлично. Потом результат можно перенести визуальный редактор canva.com и добавить фон, эффекты и даже создать видео.

5. ray.so
ray.so преобразует ваш фрагмент кода в визуально привлекательное изображение в пару кликов! Вы можете настроить иллюстрацию, выбрав из множества подсветок синтаксиса, добавить фон или выбрать тёмную или светлую тему. Это идеальный способ продемонстрировать свой код в посте или презентации по-настоящему стильно.

Источник: https://dev.to/j471n/top-10-websites-every-developer-needs-to-know-about-f5j
👍19👎1
День 1660. #ЗаметкиНаПолях
Неявные Операторы — Секрет Чистого Кода или Источник Ошибок?
Неявные операторы — мощная функция языка C#, которая позволяет сделать код более читаемым и выразительным. Они позволяют определять пользовательские преобразования, которые происходят без явного приведения, и, таким образом, устранять неуклюжий синтаксис.

Неявные операторы определяются с помощью ключевого слова implicit и могут использоваться для создания метода, преобразующего один тип в другой:
public readonly record struct Money
{
public decimal Amount { get; init; }

public static implicit operator Money(
decimal amount)
{
return new Money { Amount = amount };
}

public static implicit operator decimal(
Money money)
{
return money.Amount;
}
}

// Использование
Money money = 10.0m;
decimal amount = money;

Здесь мы определили неявный оператор, который позволяет нам преобразовать значение double в объект Money и наоборот. Компилятор автоматически применяет оператор, когда это необходимо. Согласитесь, код использования выше выглядит проще и понятнее, чем
Money m = new Money(10.0m);
decimal amount = m.Amount;

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

Два ключевых правила неявных операторов:
1. они не должны генерировать исключения,
2. они не должны терять информацию, поскольку преобразование выполняется автоматически компилятором.

Однако чрезмерное использование неявных операторов может привести к тому, что код будет труден для понимания и сопровождения. Одной из основных вещей, которых следует избегать, является создание неявных операторов, которые могут привести к потере данных или вызвать исключения. Поскольку неявные операторы применяются компилятором автоматически, любые исключения, которые они вызывают, может быть трудно отследить. Например, когда у нас возникает исключение InvalidCastException из-за неправильной операции преобразования типа, мы привыкли видеть строку кода с явной операцией приведения: мы видим в скобках тип, в который пытаемся преобразовать, применяемый к переменной или значению, и сразу знаем, что существует какая-то несовместимость, о чем свидетельствует исключение, указывающее на этот номер строки. С неявными операторами преобразование происходит «волшебным образом, под капотом». Поэтому, если в результате выполнения оператора возникает какая-либо ошибка, нам нужно не только сделать паузу, чтобы понять, что применяется неявный оператор (например, «Секундочку, как может double присваиваться к этому типу, который не является double?!»). Придётся также изучить код этого типа (будем надеяться, что у нас есть его исходный код!), а затем диагностировать, что не так с логикой.

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

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

Источник: https://www.devleader.ca/2023/08/04/implicit-operators-clean-code-secrets-or-buggy-nightmare/
👍16
День 1661. #PostgresTips
Советы по Postgres для Начинающих

6. Используйте ветки БД для разработки
Процесс разработки и тестирования в базах данных часто требует копии базы, что может быть ресурсоёмким, медленным и громоздким. Однако тонкое клонирование и ветвление БД предоставляют более удобный способ.

Что такое тонкое клонирование?
Инструменты тонкого клонирования обеспечивают легковесные, доступные для записи клоны вашей базы данных. Эти клоны используют те же базовые блоки данных, что и источник, но отображаются для пользователя как независимые базы данных. Когда в клон вносятся изменения, только эти изменения потребляют дополнительное место на диске — это достигается с помощью копирования при записи (copy-on-write, CoW), аналогично тому, что есть в контейнерах или Git, но на уровне блоков, а не на уровне файлов. Это позволяет невероятно быстро и эффективно создавать несколько копий для разработки, тестирования или анализа.

Преимущества ветвления БД
Ветвление базы данных — это тонкое клонирование, расширенное возможностью сохранения изменений и разрешения дальнейшего создания клонов на основе нового состояния. Как и в случае контроля версий кода, ветвление в контексте базы данных позволяет разработчикам создавать ответвления от основного набора данных. Это означает, что вы можете протестировать новую функцию или изменение в изолированной среде, не затрагивая первичные данные.

Database Lab
Такие инструменты, как Database Lab (DBLab), предоставляют мощные возможности тонкого клонирования и ветвления. Более того, в сочетании с решениями ИИ, такими как ChatGPT, разработчики могут даже получать мгновенные результаты своих экспериментов с SQL-запросами, не влияя на производственную среду или работу коллег. У ChatGPT часто возникают проблемы с «галлюцинациями», и всегда важно проверять советы, сгенерированные ИИ, на клоне базы данных. Ветвление даёт наиболее эффективный с точки зрения затрат и времени способ сделать это.

По сути, использование тонкого клонирования и ветвления базы данных означает более быстрые циклы разработки, снижение затрат на хранение и возможность экспериментировать без риска. Это новый подход к тому, как мы обрабатываем данные в средах разработки.

Самый быстрый способ начать работу с тонкими клонами и ветвлением БД — установить DBLab SE в несколько кликов с помощью консоли Postgres.ai (поддерживаются: AWS, GCP, DigitalOcean и Hetzner Cloud, а также любые другие локации, в том числе on-premise).

Источник: https://postgres.ai/blog/20230722-10-postgres-tips-for-beginners
👍9👎2
День 1662. #Карьера
Управляем Вверх: Руководство Разработчика по Карьерному Росту
Управление «вверх» (Managing up), по сути, является стратегией активной работы с вашим начальством для достижения общих целей. Речь идет о понимании ожиданий вашего руководителя, согласовании их с вашими целями и обеспечении того, чтобы вы оба слаженно работали над достижением общих побед. Для разработчиков это означает нечто большее, чем просто достижение целей спринта; это стремление продемонстрировать свою ценность и помочь вашему менеджеру добиться успеха в своей роли.

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

2. Инициатива: вы обнаружили технический долг, который замедляет работу команды. Вместо того, чтобы ждать ежегодной проверки, чтобы обсудить его, назначьте встречу со своим руководителем, чтобы представить проблему и возможные решения.

3. Цикл обратной связи: после завершения проекта попросите своего руководителя оставить отзыв, демонстрируя своё стремление расти и соответствовать ожиданиям команды.

Советы и рекомендации
1. Поймите цели руководителя: узнайте, что движет вашим менеджером. Чего от него ожидает его начальство? Есть ли у него определённые KPI, которых нужно достичь? Поняв это, вы можете согласовать свой вклад, чтобы напрямую повлиять на его успех. В конце концов, какую бы роль вы ни занимали, ваша работа в основном состоит в том, чтобы ваш босс выглядел хорошо. Если у вас есть возможность взаимодействовать с людьми ещё на уровень выше, вы можете применить тот же принцип и к ним.

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

3. Будьте ориентированы на решение: одно дело — определить проблему, а другое — предложить решение. При обсуждении проблем всегда старайтесь предлагать возможные решения, даже если это решения, которые вы не в состоянии реализовать. Это демонстрирует вашу инициативу и умение решать проблемы.

4. Ищите обратную связь: покажите, что вы стремитесь расти и совершенствоваться. Регулярно запрашивайте обратную связь и действуйте в соответствии с ней. Если возможно, спросите об одной конкретной вещи, которую вы можете улучшить, а затем поработайте над ней. Если вы запросите слишком много отзывов, возможно, вы не сможете отреагировать на все и можете перегрузить своего руководителя.

5. Управляйте ожиданиями: чётко сообщайте о сроках, потенциальных препятствиях и потребностях. Это помогает предотвратить любые неожиданности в последнюю минуту. Лучший способ превзойти ожидания — правильно их установить.

Почему менеджеры тоже выигрывают
Менеджеры получают огромную выгоду от управления вверх: прозрачную коммуникацию, упреждающие решения и члена команды, искренне заинтересованного в общем успехе. Это не только помогает в достижении командных целей, но и способствует созданию позитивной рабочей атмосферы, в которой выигрывают обе стороны.

Источник: https://ardalis.com/managing-up-developers-guide-career-advancement/
👍9
День 1663.
Результаты розыгрыша онлайн-билета на DotNext 2023

Победителя я определил простым рандомом из всех прокомментировавших исходный пост. Весь процесс в видео в первом комментарии.

Победил Stas Horoshavcev, поздравляю! В скором времени с вами свяжутся представители конференции и передадут билет.

Для всех остальных промокод канала netdeveloper поможет купить билет «Для частных лиц» со скидкой. Также билет на конференцию вам может оплатить работодатель.

Я лично буду на конференции офлайн. Если тоже будете, можем пересечься.

Узнать подробности о DotNext 2023, почитать программу и купить билеты можно на сайте.
👍5
День 1664. #ЧтоНовенького
Конкурентный Запуск и Остановка Hosted-Сервисов в .NET 8
Библиотека Microsoft.Extensions.Hosting, используемая как в шаблоне проекта ASP.NET Core, так и в шаблоне Worker Service, обеспечивает возможность запуска долго работающего консольного приложения. В .NET 8 в ней появилась новая функциональность, влияющая на размещённые (hosted) сервисы.

В ASP.NET Core приложение запускает веб-сервер Kestrel и работает до тех пор, пока процесс не будет остановлен. Шаблон Worker Service идеально подходит для создания легковесных приложений обработки, которые работают постоянно. Например, это могут быть микросервисы, которые запрашивают сообщения из очереди и обрабатывают их.

Размещённые сервисы — это фоновые задачи, запускаемые хостом, которые выполняют работу приложения. Приложения могут определять один или несколько размещённых сервисов, регистрируя реализацию интерфейса IHostedService в DI-контейнере. Microsoft предоставляет общую реализацию этого интерфейса в абстрактном классе BackgroundService. Разработчики наследуют от этого класса и предоставляют реализацию абстрактного метода ExecuteAsync. Когда платформа размещения запускается, она запускает задачу, определённую в методе ExecuteAsync.

До .NET 8 код, который запускает и останавливает размещённые сервисы, делал это последовательно. Каждый IHostedService запускался последовательно через ожидание вызова StartAsync экземпляра. Т.е. каждая задача StartAsync должна была быть завершена до запуска следующей. Это не оказывало существенного влияния на большинство приложений, но это поведение по умолчанию всё же может вызывать проблемы. Несмотря на то, что внутри StartAsync рекомендуется выполнять небольшую работу, медленный размещённая сервис может задерживать запуск оставшейся части приложения.

При остановке приложений сервисы так же останавливались в обратном порядке через ожидание StopAsync. Это может быть более проблематичным, т.к. настроен тайм-аут (ShutdownTimeout), ограничивающий продолжительность корректного завершения работы. Т.е. тайм-аут должен учитывать время, необходимое для корректного закрытия всех размещённых сервисов. В некоторых ситуациях при сбросе текущих незавершённых работ это может привести к тому, что некоторые сервисы будут использовать большую часть тайм-аута.

В .NET 8 добавлены две новые опции, которые позволяют переключаться на параллельный запуск и/или остановку:
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(svc =>
{
svc.Configure<HostOptions>(o =>
{
o.ServicesStartConcurrently = true;
o.ServicesStopConcurrently = true;
});

svc.AddHostedService<WorkerOne>();
svc.AddHostedService<WorkerTwo>();
})
.Build();

В примере выше регистрируются два размещённых сервиса, которые будут запускаться и останавливаться одновременно, не задерживая друг друга. Внутри .NET это достигается путём добавления всех сервисов в группу задач и ожидания завершения этой группы через Task.WhenAll. Для конкурентного останова это позволяет каждому размещённому сервису завершить свою работу в течение всего времени тайм-аута.

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

Источник: https://www.stevejgordon.co.uk/concurrent-hosted-service-start-and-stop-in-dotnet-8
👍20
День 1665. #ЧтоНовенького
Новый Интерфейс IHostedLifecycleService в .NET 8
Вчера я писал про конкурентный запуск и остановку hosted-сервисов в .NET 8, однако этим нововведения для размещённых сервисов не ограничиваются.

В пространство имён Microsoft.Extensions.Hosting добавлен интерфейс IHostedLifecycleService. Он наследуется от IHostedService, расширяя его методами для новых событий жизненного цикла, которые происходят до или после существующих методов StartAsync и StopAsync соответственно:
- StartingAsync,
- StartedAsync,
- StoppingAsync,
- StoppedAsync.

Метод StartingAsync будет выполняться очень рано в жизненном цикле приложения, прежде чем StartAsync будет вызван для любого зарегистрированного размещённого сервиса. Это может использоваться для выполнения некоторых очень ранних проверок перед запуском приложения, таких как проверка критических требований или наличия зависимостей. Это позволит приложению потенциально завершаться сбоем при запуске до того, как какие-либо размещённые сервисы начнут выполнять свою основную рабочую нагрузку. Другие варианты использования включают «предварительный нагрев» и инициализацию синглтонов и других состояний, используемых приложением.

StartedAsync будет вызываться в реализациях после завершения всех методов StartAsync для зарегистрированных размещённых сервисов. Его можно использовать для проверки состояния или условий приложения непосредственно перед пометкой приложения как успешно запущенного.

StoppingAsync и StoppedAsync работают аналогично во время завершения работы приложения и предоставляют расширенные перехватчики для проверок до и после завершения работы.

Кроме того, в HostOptions добавлена новая опция StartupTimeout, позволяющая предоставить TimeSpan, который будет контролировать максимальное время, разрешённое для запуска всех размещённых сервисов. При установке в небесконечное (по умолчанию) значение токен отмены, передаваемый в события жизненного цикла запуска, будет отменяться по заданному тайм-ауту.

Использование интерфейса
Довольно распространённая работа перед запуском приложения — инициализация БД. В таких средах, как CI, нам может потребоваться создавать фиктивную БД и заполнить её тестовыми данными. Одним из возможных вариантов решения является использование размещённых сервисов. В .NET 8, если сервисы запускаются конкурентно, может возникнуть проблема, когда один сервис зависит от результатов работы другого (например, от наличия инициализированной БД). Поэтому мы можем использовать IHostedLifecycleService, чтобы инициализировать базу до того, как она будет использована каким-либо другим сервисом:
public class ServiceA : IHostedService,
IHostedLifecycleService
{
public Task StartingAsync(CancellationToken ct)
{
// инициализация БД
return Task.CompletedTask;
}

// реализация других методов
}

public class ServiceB : BackgroundService
{
protected override Task ExecuteAsync(
CancellationToken stoppingToken)
{
// использование БД
return Task.CompletedTask;
}
}

Здесь ServiceA реализует IHostedLifecycleService и инициализирует БД на самом раннем этапе жизненного цикла приложения, до любой из основных рабочих нагрузок. ServiceB, производный от BackgroundService, теперь может безопасно использовать БД, т.к. ExecuteAsync вызывается базовой реализацией StartAsync. Т.е. он не вызывается до тех пор, пока не будут завершены все методы StartingAsync для зарегистрированных сервисов. Также теперь не имеет значения, в каком порядке сервисы регистрируются в DI-контейнере:
builder.Services.AddHostedService<ServiceB>();
builder.Services.AddHostedService<ServiceA>();

Источник: https://www.stevejgordon.co.uk/introducing-the-new-ihostedlifecycleservice-interface-in-dotnet-8
👍13
День 1666. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#

21. Что такое слабые ссылки и когда их использовать в C#?
В C# слабые ссылки — это ссылки на объекты, которые недостаточно надёжны, чтобы предотвратить сборку мусора для этих объектов. Они позволяют поддерживать ссылку на объект до тех пор, пока объект жив в памяти, но не препятствуя сборщику мусора (GC) освобождать объект при увеличении нагрузки на память. Со слабыми ссылками вы можете получить доступ к объекту, пока он всё ещё находится в памяти, но это не помешает GC удалить объект, если это необходимо.

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

Чтобы использовать слабую ссылку в C#, создайте экземпляр класса WeakReference или WeakReference<T>:
WeakReference<MyLargeObject> wr 
= new(new MyLargeObject());

MyLargeObject lo;
if (wr.TryGetTarget(out largeObject))
{
// объект всё ещё в памяти, используем его
Console.WriteLine("Используем объект.");
}
else
{
// объект удалён сборщиком мусора
Console.WriteLine("Объект удалён.");
largeObject = new MyLargeObject();
}

class MyLargeObject
{
private byte[] _data = new byte[1000000];
}

В этом примере, если GC решит освободить память, используемую экземпляром MyLargeObject, вызов weakReference.TryGetTarget возвратит значение false. В противном случае largeObject останется доступным через слабую ссылку.

Источник: https://dev.to/bytehide/20-senior-developer-c-interview-questions-and-answers-2023-3bjc
👍42
День 1667. #ЗаметкиНаПолях #Debugging
Отладка с Разных Точек Зрения
Отладка — это процесс выявления основной причины ошибки и её исправления.

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

Мышление
Кэрол Дуэк, известный психолог, представила концепции «мышления на рост» и «фиксированного мышления». Люди с мышлением на рост считают, что их способности и интеллект можно развить с помощью усилий, обучения и настойчивости. Люди с фиксированным мышлением считают, что их качества являются врождёнными и неизменными, что приводит к страху неудачи и нежеланию принимать вызовы. Дуэк подчёркивает важность воспитания мышления на рост для повышения устойчивости, обучения и личного развития.

Прежде чем приступить к отладке, важно принять соответствующий образ мышления. Это влечёт за собой отказ от защиты своего эго, игнорирование любого давления проекта и обеспечение личного комфорта. Помните первое правило отладки: НЕ ПАНИКУЙТЕ.

Это возможность
Отладку следует воспринимать как ценную возможность:
- Лучше понять программу, над которой вы работаете.
- Распознать типы ошибок, которые вы обычно совершаете.
- Оценить качество вашего кода с точки зрения того, кто должен его читать и понимать.
- Узнать, как вы подходите к решению проблем.

Правильное отношение
При правильном отношении отладка может быть весёлой, как решение головоломки. Вот некоторые ключевые аспекты правильного отношения к эффективной отладке:
- Любознательность: будьте готовы исследовать и понять основную причину проблемы.
- Терпение: отладка может занять много времени. Будьте терпеливы и настойчивы.
- Открытость к обучению: рассматривайте отладку как возможность учиться и улучшать свои навыки.
- Смирение: признайте, что все совершают ошибки. Отладка — это поиск и исправление этих ошибок, а не отражение вашей ценности или интеллекта.
- Системный подход: используйте системный подход для выявления и изоляции проблемы. Избегайте поспешных предположений и тщательно исследуйте код или систему.
- Сотрудничество: не стесняйтесь обращаться за помощью.
- Внимание к деталям: обратите внимание на мельчайшие детали, поскольку они часто могут содержать ключ к разгадке источника проблемы.
- Оптимизм: вера в свою способность успешно решить проблему может помочь сохранить концентрацию и мотивацию.
- Документация: отслеживайте процесс отладки, предпринятые шаги и решения. Эта документация может оказаться полезной для будущих справок и обучения.

Отладка в два раза сложнее, чем написание кода. Следовательно, если вы пишете код максимально умно, вы по определению недостаточно умны, чтобы его отлаживать.
Брайан В. Керниган

Это искусство
Отладку можно рассматривать как форму искусства, поскольку она требует творческого и интуитивного подхода к решению сложных проблем с ПО. Опытный отладчик должен обладать терпением, вниманием к деталям и способностью мыслить нестандартно.

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

Источник: https://dev.to/rajasegar/debugging-from-different-viewpoints-46k0
👍4👎1