.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
День 1413. #ЗаметкиНаПолях #AsyncTips
Выполнение Кода с Помощью Планировщика. Окончание: Использование Планировщика

Задача:
требуется управлять выполнением отдельных фрагментов в параллельном коде.

Решение
После того как вы создадите экземпляр TaskScheduler (см. Создание Планировщика), можете включить его в набор параметров, передаваемых методу Parallel. Следующий код получает набор коллекций матриц, запускает несколько параллельных циклов и ограничивает общий параллелизм всех циклов одновременно независимо от количества матриц в каждом наборе:
void RotateMatrices(
IEnumerable<IEnumerable<Matrix>> collections,
float degrees)
{
var schPair = new ConcurrentExclusiveSchedulerPair(
TaskScheduler.Default,
maxConcurrencyLevel: 8);
var scheduler = schPair.ConcurrentScheduler;
var opts = new ParallelOptions {
TaskScheduler = scheduler };

Parallel.ForEach(
collections,
opts,
matrices => Parallel.ForEach(
matrices,
opts,
m => m.Rotate(degrees)));
}

Parallel.Invoke также получает экземпляр ParallelOptions, поэтому вы можете передать TaskScheduler при вызове Parallel.Invoke так же, как и для Parallel.ForEach. При выполнении динамического параллельного кода можно передать TaskScheduler непосредственно TaskFactory.StartNew или Task.ContinueWith.

Передать TaskScheduler коду Parallel LINQ (PLINQ) невозможно.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 13.
👍3
День 1414. #ЧтоНовенького
Новые Возможности MVC в .NET 7. Часть 1
В этой серии рассмотрим некоторые нововведения в ASP.NET Core в .NET 7.

1. IParseable/TryParse для привязки примитивных типов
MVC использует подход «поставщика привязки». Можно привязать параметры методов действий к значениям формы, строки запроса, заголовкам и т.п. По умолчанию MVC связывает некоторые простые типы или любые типы, имеющие TypeConverter из строки. Всё остальное рассматривается как сложный тип, т.е. либо привязывается к телу запроса, либо привязывается не сам тип, а каждое из отдельных свойств типа. Допустим, у нас есть тип:
public class Range
{
public int From { get; set; }
public int To { get; set; }
}
и привязка его в методе действия контроллера:
public class MyController : ControllerBase
{
public IEnumerable<MyClass> Get(Range days)
{ … }
}
В .NET 6 вам нужно либо написать TypeConverter для Range, либо привязать свойства From и To:
/MyController?from=1&to=3

В .NET 7 есть другой вариант. Можно реализовать интерфейс IParseable<T> и создать объект Range из любой строки. Например, мы хотим иметь такой URL:
/MyController/1-3

Формально реализовывать IParseable<T> не нужно, достаточно реализовать метод TryParse(). Пример реализации ниже. Детали не особенно важны, и здесь не учитывается множество пограничных случаев:
public readonly struct Range : IParsable<Range>
{
public int From { get; }
public int To { get; }

public Range(int from, int to)
{
From = from;
To = to;
}

public static bool TryParse(
string? value,
IFormatProvider? provider,
out Range result)
{
if (value != null)
{
var sep = value.IndexOf('-');
if (sep > 0 && sep < value.Length - 1)
{
var fromSpan = value.AsSpan().Slice(0, sep);
var toSpan = value.AsSpan(sep + 1);

if (int.TryParse(fromSpan,
out var from)
&& int.TryParse(toSpan,
out var to))
{
result = new Range(from, to);
return true;
}
}
}

result = default;
return false;
}

public static Range Parse(
string value,
IFormatProvider? provider)
{
if (!TryParse(value, provider, out var result))
throw new ArgumentException();

return result;
}
}

Затем можно просто добавить атрибут к методу контроллера:
[HttpGet("{days}")]
public IEnumerable<MyClass> Get(Range days)
{ … }

Проще ли реализовать IParseable<T>, чем написать свой связыватель модели? Вероятно. Проще, чем свой TypeConverter? Возможно. Однако при этом подходе вы можете использовать одни и те же типы в минимальных API и в контроллерах. Это должно упростить переход от минимальных API к контроллерам (и наоборот).

Если же вы хотите отключить эту функцию, удалите TryParseModelBinderProvider из MvcOptions:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<MvcOptions>(opts => {
opts.ModelBinderProviders
.RemoveType<TryParseModelBinderProvider>();
});

Источник: https://andrewlock.net/5-new-mvc-features-in-dotnet-7/
👍8
День 1415. #ЧтоНовенького
Новые Возможности MVC в .NET 7. Часть 2
В этой серии рассмотрим некоторые нововведения в ASP.NET Core в .NET 7.
Часть 1

2. Контроллеры MVC могут автоматически определять сервисы
Контроллеры в .NET 7 автоматически определяют сервисы, зарегистрированные в контейнере внедрения зависимостей, не требуя явного атрибута [FromServices]. В минимальных API вы можете просто внедрять сервисы непосредственно в конечные точки API:
app.MapGet("/", (IGreeterService service)
=> service.SayHello();

Эквивалент в .NET 6 выглядел бы так:
public class SomeController : Controller
{
public void IActionResult Get(
[FromServices] IGreeterService service)
{
return service.SayHello();
}
}

В .NET 6, атрибут [FromServices] обязателен, иначе MVC попытается связять параметр service с телом запроса. В .NET 7 можно обойтись без него:
public class SomeController : Controller
{
public void IActionResult
Get(IGreeterService service)
{
return service.SayHello();
}
}

Эта функциональность основывается на сервисе IServiceProviderIsService, представленном в .NET 6, и должна «просто работать». Понятно, что [FromService] вряд ли будет использоваться с контроллерами, гораздо более предпочтительный вариант будет внедрение через конструктор, но тем не менее это потенциально удаляет немного шаблонного кода и снова идёт в ногу с минимальными API.

Кстати, о IServiceProviderIsService. Смысл в нём в том, что нужен способ узнать, что за параметр передаётся методу действия. Одним (плохим) решением было бы, чтобы API всегда предполагал, что это сервис, и пытался получить его из контейнера DI. Однако при этом будет предпринята попытка создать экземпляр сервиса, что может иметь непредвиденные последствия. Представьте, что контейнер записывает в журнал каждую попытку получить несуществующий сервис, чтобы вам было легче обнаруживать неверные настройки. Это может повлиять на производительность, если запись в журнал будет делаться для каждого отдельного запроса.

Итак, сервис IServiceProviderIsService:
public partial interface IServiceProviderIsService
{
bool IsService(Type serviceType);
}
Он предоставляет единственный метод, который можно вызвать, чтобы проверить, зарегистрирован ли данный тип сервиса в контейнере внедрения зависимостей. Сам сервис IServiceProviderIsService также можно получить из контейнера. Если вы используете пользовательский контейнер, в котором не добавлена поддержка этой функции, то вызов GetService<IServiceProviderIsService>() вернёт null.

Источники:
-
https://andrewlock.net/5-new-mvc-features-in-dotnet-7/
-
https://andrewlock.net/exploring-dotnet-6-part-10-new-dependency-injection-features-in-dotnet-6/
👍7
День 1416. #ЧтоНовенького
Новые Возможности MVC в .NET 7. Часть 3
В этой серии рассмотрим некоторые нововведения в ASP.NET Core в .NET 7.
Часть 1
Часть 2

3. Использование nullable-аннотаций
С каждым выпуском .NET поддержка ссылочных обнуляемых типов становится немного лучше. Для ASP.NET Core в .NET 7 она была добавлена в нескольких местах:

1) Обнуляемое тело запроса
В .NET 6 при привязке к телу запроса (независимо от того, используется ли явно [FromBody]), попытка привязки к запросу с пустым телом (где Content-Length == 0) завершится ошибкой "A non-empty request body is required." (Требуется непустое тело запроса).

Вы можете обойти это глобально в .NET 6 и разрешить null для параметра, настроив свойство MvcOptions.AllowEmptyInputInBodyModelBinding:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<MvcOptions>(opts =>
{
opts.AllowEmptyInputInBodyModelBinding = true;
});

Другой вариант - включить его отдельно для каждого метода действия, добавив явный атрибут [FromBody] и установив EmptyBodyBehavior, например:
public IActionResult Post(
[FromBody(EmptyBodyBehavior=EmptyBodyBehavior.Allow)]
MyBody? body)
{
// body будет null при пустом теле
}
Это работает, но это слишком длинно и уродливо…

В .NET 7 всё становится намного проще. Вы можете полагаться на nullable-аннотации. Обнуляемый параметр подразумевает EmptyBodyBehavior.Allow, а необнуляемый - EmptyBodyBehavior.Disallow:
public IActionResult Post(MyBody? body)
{
// body будет null при пустом теле
}

public IActionResult Post(MyBody body)
{
// При пустом теле будет ошибка 400
}

2) Определение необязательности сервиса
В .NET 6, если вы не зарегистрировали тип сервиса в контейнере внедрения зависимостей, то, даже если декорированный атрибутом [FromService] параметр помечен как обнуляемый, попытка вызова конечной точки API приводит к ошибке:
InvalidOperationException: No service for type 'SomeService' has been registered (Сервис типа 'SomeService' не был зарегистрирован)

В .NET 7 обнуляемый параметр с атрибутом [FromServices] будет null, если он недоступен в DI:
public IEnumerable<MyClass> Get(
[FromServices] SomeService? service)
{ … }

Вам может быть интересно, что произойдёт, если вы попытаетесь привязать обнуляемый сервис, который не зарегистрирован в DI, используя автоматическое определение сервиса, описанное в части 2?
Ответ: скорее всего, не то, чего вы хотите. Если тип параметра (SomeService выше) не зарегистрирован в DI, он не будет рассматриваться как сервис, он будет рассматриваться как любой другой сложный тип. Это означает, что MVC попытается привязать его свойства к любым доступным параметрам: телу запроса, строке запроса, заголовкам и т.п.

Источник: https://andrewlock.net/5-new-mvc-features-in-dotnet-7/
👍4
День 1417. #юмор
В тему хайпа про ChatGPT.
👍11
День 1418. #Оффтоп
Сегодня порекомендую вам видео с канала Computerphile, которое называется «Horrible, Helpful, http3 Hack» https://youtu.be/wV9FSyFB8tk

HTTP3 вышел летом этого года, но создание его было сопряжено с некоторыми трудностями. В том числе пришлось использовать довольно кривой костыль. Ричард Дж. Клегг из Университета Королевы Мэри в Лондоне сначала напоминает про некоторые уровни сетевого взаимодействия, объясняет, что такое QUIC, и почему он не может определиться, любит он HTTP3 или ненавидит его.

Видео на английском, но доступны автоматические русские субтитры.
👍7
День 1419. #ЧтоНовенького
Новые Возможности MVC в .NET 7. Часть 4
В этой серии рассмотрим некоторые нововведения в ASP.NET Core в .NET 7.
Часть 1
Часть 2
Часть 3

4. Поддержка IResult
MVC имеет IActionResult и ActionResult<T>; минимальные API имеют IResult и IValueHttpResult<TValue>. И не стоит их путать!

К сожалению, это легче сказать, чем сделать. Если вы пишете много минимальных API, а затем погружаетесь в MVC, вы можете случайно написать что-то вроде этого:
[HttpGet]
public IResult Get()
{
return Results.Ok(
new { Name = "My name" });
}

К сожалению, технически это не ошибка: нет предупреждения во время компиляции об использовании IResult с MVC и нет ошибки во время выполнения. Вместо этого MVC сериализует объект IResult в JSON, что похоже на то, что вы хотите, пока вы не увидите вывод:
{
"value": {
"name" : "My name"
},
"statusCode" : 200,
"contentType" : null
}

Как видите, MVC не просто сериализует объект, который мы передали в Ok(), он сериализует весь объект Results. Это напоминает некоторые ужасные API, которые возвращают код состояния 200, но содержат в теле statusCode: 400!

В .NET 7 MVC добавили ограниченную поддержку сериализации объектов IResult, и, как и следовало ожидать, вместо результата выше вы получаете следующий вывод:
{
"name" : "My name"
}

Когда вы возвращаете IResult из метода действия MVC, вы не получаете никаких функций MVC, таких как согласование содержимого и средства форматирования вывода; вы всегда получаете JSON. Тем не менее, если вы создаёте API только с JSON, этот вариант имеет преимущество в том, что вы потенциально можете совместно использовать больше компонентов в ваших минимальных API и контроллерах MVC, просто возвращая IResult, вместо того чтобы реализовывать обработку как для IActionResult, так и для IResult.

Источник: https://andrewlock.net/5-new-mvc-features-in-dotnet-7/
👍8
День 1420. #Debugging
Я Исправил Ошибку. Что Дальше?
Чем больше кода вы пишете, тем больше ошибок создаёте. Т.е. как разработчик ПО вы должны тратить часть своего времени на отладку.

Есть несколько общих шагов при отладке приложения:
1. Получение всей необходимой информации для понимания проблемы (этапы воспроизведения, стек вызовов, журналы и т. д.)
2. Воспроизведение проблемы и отладка кода
3. Исправление кода

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

1. Легко ли было получить информацию, необходимую для воспроизведения ошибки?
- Какую версию приложения запускает пользователь?
- Какова конфигурация среды? (ОС, версия .NET, текущая культура, разрешение экрана, ОЗУ, загрузка ЦП и т. д.)
- Какая конфигурация приложения? (Пользовательские настройки)
- В случае сбоя доступен ли стек вызовов и понятно ли сообщение об ошибке?
- Есть ли доступ к логам? Легко ли их получить и прочитать? Предоставляют ли они достаточно информации и контекста?
- Есть ли доступ к данным телеметрии?
На этом этапе у вас должно быть хорошее представление о проблеме, не глядя на код.

2. Легко ли воспроизвести проблему в среде разработки?
- Легко ли начать работу над проектом? (Получить код/Открыть проект в IDE/Начать отладку)
- Правильно ли задокументирован процесс?
- Нужно ли вручную настраивать секреты для подключения к внешним службам?
- Требуется ли дополнительное ПО на машине и как его получить?
- Легко ли настроить ту же среду, что и в рабочей среде (Azure Web App, Docker, Kubernetes)? Легко ли отлаживать эту среду?
- Можно ли получить анонимизированные живые данные, когда это необходимо?
- Если нельзя воспроизвести проблему в своей среде, можно ли вы отладить промежуточную/производственную версию или получить дамп? Будьте очень осторожны, когда делаете это, чтобы не заблокировать работающий сервис из-за достижения точки останова и не раскрыть важные данные.

3. Легко ли работать над кодовой базой?
- Хорошо ли организован код? Находите ли вы то, что ищете?
- Код легко читается? Соблюдается ли соглашение об именовании и стиль написания кода?
- Есть ли в коде неявные зависимости?
- Насколько быстро вы можете вносить изменения и наблюдать за их результатами в приложении?
- Можете ли вы воспользоваться своей IDE для отладки?
- Можете ли использовать точки останова и просматривать локальные значения или вычислять выражения?
- Ваши типы переопределяют ToString или отмечены атрибутом [DebuggerDisplay], чтобы вы могли быстро увидеть значения во время отладки?

4. Почему разработчик внёс эту ошибку в код?
На этом этапе вы должны найти причины, по которым разработчик допустил ошибку. Сделайте шаг назад и проанализируйте проблему.
- Код слишком сложный?
- Методы слишком длинные и слишком сложные?
- Используете ли вы правильный инструмент для выполнения работы?
- Возможна ли путаница? Например, два типа с одинаковым именем в разных пространствах имен.
- Ясно ли объясняются пред- и пост-условия метода (возможно ли передать/вернуть null, дату локальную/UTC, относительный/абсолютный путь?
- Отсутствует или неясна документация/комментарии?
- Влияет ли изменение части приложения на другую часть?
- Надёжны ли тесты?
- Есть ли хотя бы один сквозной тест для основного сценария приложения?

Источник: https://www.meziantou.net/how-to-correctly-fix-a-bug.htm
👍6
This media is not supported in your browser
VIEW IN TELEGRAM
День 1421. #ЧтоНовенького
Превью «Липкого» Скроллинга в VS 17.5
Писать длинные классы с многоуровневой вложенностью кода стало ещё приятнее в превью 2 Visual Studio 17.5. А всё благодаря новой функции «липкого скроллинга» (Sticky Scroll).

Она поддерживает контекст для кода, с которым вы работаете, сохраняя соответствующие заголовки. Когда вы прокручиваете код, пространства имён, классы и методы будут прилипать к верхней части редактора. См. видео. Помимо этого, нажатие мыши на заголовок приведёт к этой строке кода. Sticky Scroll поддерживает несколько форматов кода, включая C#, C++, XAML и JSON.

Sticky Scroll можно включить в меню Tools > Options > Text Editor > General > Sticky Scroll (Инструменты > Параметры > Текстовый редактор > Основные > Sticky Scroll). Там же вы можете установить максимальное количество строк, которые будут «прилипать».

Источник: https://devblogs.microsoft.com/visualstudio/sticky-scroll-now-in-preview/
👍20
День 1422. #BestPractices
Хеширование Паролей в C#. Начало
В системе, которая хранит учётные данные пользователей, нужно уделить особое внимание тому, как хранить пароли. Рассмотрим, как использовать методы хэширования в C# для безопасного хранения паролей пользователей.

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

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

По мере того, как всё больше вычислительной мощности становится доступной для широкой публики, алгоритмы хеширования, которые в прошлом считались достаточно безопасными (например, MD5 и SHA), стали небезопасными. Их нельзя использовать их для хеширования паролей. Следующие алгоритмы безопасны.
1. PBKDF2 — стандарт формирования ключа на основе пароля, изначально доступный в среде .NET. В отличие от MD5 или SHA, PBKDF2 повышает защиту пароля от метода грубой силы, добавляя дополнительную сложность.

2. Семейство алгоритмов BCrypt/SCrypt спроектировано так, чтобы интенсивно использовать ЦП и память, особенно новый SCrypt, который очень устойчив к атакам методом грубой силы.

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

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

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

Лучшие практики
1. Использовать разные соли для каждого пароля. Общая на всех соль делает этот метод намного менее эффективным.
2. Если возможно, хранить соли паролей отдельно.
3. Соль пароля должна быть трудной для угадывания
злоумышленником. Рекомендуется использовать криптографический генератор случайных чисел, такой как RandomNumberGenerator в пакете System.Security.Cryptography.
4. Соль должна быть достаточно длинной. Хорошее эмпирическое правило — сделать её того же размера, что и выходной хэш.

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

Источник:
https://code-maze.com/csharp-hashing-salting-passwords-best-practices/
👍20
День 1423. #BestPractices
Хеширование Паролей в C#. Окончание
Начало

Пример хеширования с помощью PBKDF2
Мы будем использовать статический метод Rfc2898DeriveBytes.Pbkdf2(). Он принимает несколько параметров, включая соль. Чтобы сгенерировать правильную случайную соль, воспользуемся статическим методом RandomNumberGenerator.GetBytes():
const int keySize = 64;
const int iterations = 350000;
var hashAlgorithm = HashAlgorithmName.SHA512;
string HashPasword(string password, out byte[] salt)
{
salt = RandomNumberGenerator.GetBytes(keySize);
var hash = Rfc2898DeriveBytes.Pbkdf2(
Encoding.UTF8.GetBytes(password),
salt,
iterations,
hashAlgorithm,
keySize);
return Convert.ToHexString(hash);
}

Функция HashPassword() принимает пароль в виде открытого текста и возвращает его хешированную версию. Мы получаем случайную соль, сгенерированную в процессе, через выходной параметр salt. Важно получить и сохранить эту часть данных, так как она необходима для последующей проверки пароля.

keySize - желаемый размер в байтах результирующего хэша и размер случайной соли. Мы должны согласовать это значение с размером хэша, который производит базовый алгоритм хеширования.
PBKDF2 можно применять несколько раз к заданному входному значению для усиления результирующего хэша, поэтому добавим константу iterations. Считается, что безопасные значения для производственных сред исчисляются сотнями тысяч.
Наконец, в переменной hashAlgorithm определяем базовый метод хеширования, который PBKDF2 будет использовать для вывода, в данном случае SHA512.

Пример использования:
var hash = 
HashPasword("clear_password", out var salt);
Console.WriteLine($"Hash: {hash}");
Console.WriteLine($"Salt: {Convert.ToHexString(salt)}");

Проверка пароля
Т.к. мы не можем расшифровать хеш-алгоритмы, нужно снова хешировать входящий пароль и сравнивать результат с сохранённой хешированной версией:
bool VerifyPassword(
string password,
string hash,
byte[] salt)
{
var hashToCompare =
Rfc2898DeriveBytes.Pbkdf2(
password, salt, iterations,
hashAlgorithm, keySize);

return hashToCompare.SequenceEqual(
Convert.FromHexString(hash));
}

Функция VerifyPassword() принимает чистый пароль, сохранённый хэш пароля и связанную с ним соль. Она вернет true, если предоставленный чистый пароль сгенерирует тот же хэш. Очень важно предоставить те же значения для iterations, hashAlgorithm и keySize, что и при начальном хешировании.

Другие классы и библиотеки
BCrypt.Net-Next — сторонняя библиотека для хеширования паролей, основанная на алгоритме BCrypt.

Класс PasswordHasher<TUser> является частью пакета Microsoft.AspNetCore.Identity, который реализует хеширование и проверку паролей на основе PBKDF2 со случайными значениями соли и итераций.

Источник: https://code-maze.com/csharp-hashing-salting-passwords-best-practices/
👍19
День 1424. #Оффтоп #ЗадачиНаСобеседовании
Больше недели думал, писать ли что-нибудь про ChatGPT. Если кто не знает, что это, вот описание из русской Википедии:
«ChatGPT — это прототип чат-бота с искусственным интеллектом, разработанный OpenAI и специализирующийся на диалогах. ChatGPT — большая языковая модель, отлаженная как с помощью методов обучения с учителем, так и с подкреплением. Базовой моделью, которая была доработана, была языковая модель от OpenAI GPT-3.5, улучшенная версия GPT-3.
ChatGPT был запущен 30 ноября 2022 года и привлёк внимание своими подробными ответами и четкими формулировками, хотя его фактическая точность подверглась критике.»

Сам его пока не ковырял, не было времени, а отзывы в программистской среде пока самые разнообразные от восторженно-панических «программисты больше не нужны» до скептически-злорадных «да там косяк на косяке». Но сегодня всё-таки поделюсь пока самым впечатляющим из того что я видел. Видео от Клемента Михайлеску, создателя платформы AlgoExpert.io, которая предлагает задачи для собеседований на кодирование.

Клемент задал боту задачи «как есть», так, как они описаны на его сайте, предварительно дав ему контекст: «Ты проходишь собеседование в Google с написанием кода». Всего было 3 алгоритмических задачи разного уровня: простой, посложнее и самый сложный. Как сказал Клемент, если первые две задачи довольно стандартные и решения можно найти в сети, то третья (опять же, по его словам) в сети не встречается.

В общем, что из этого вышло, смотрите в новом видео от Клемента Михайлеску https://youtu.be/gOf2SQVMUL0

PS: Кстати, кому интересно, можете запаузить видео и попробовать решить сами.
👍10
День 1425. #юмор
👍18
День 1426. #ЗаметкиНаПолях
Добавляем Все Проекты в Решение с Помощью CLI
Допустим, по какой-то причине вам нужно быстро создать файл решения Visual Studio, включающий все проекты во всех подпапках. Как вариант, может быть нужно быстро рассчитать метрики кода для всего репозитория GitHub или вы просто хотите увидеть все проекты в одном месте. Может быть утомительно находить и добавлять каждый файл csproj в каждой подпапке вручную, особенно в кодовой базе, с которой вы не знакомы.

Команда dotnet sln
Файлы решений .NET можно создавать из командной строки. Синтаксис довольно прост:
dotnet new sln -n Everything

В приведённом выше примере флаг -n позволяет указать имя; в противном случае по умолчанию будет использоваться текущее имя папки. Результатом этой команды является пустой файл решения с именем Everything.sln.

Далее вам просто нужно добавить все файлы проекта. К сожалению, нет встроенного способа сделать это с помощью команды dotnet sln, но вы можете легко написать это в сценарии. Следующая команда должна работать из Powershell или в Linux:
dotnet sln add (ls -r **/*.csproj)

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

Если у вас уже есть файл решения в папке, из которой вы запускаете команду, вам просто нужно указать имя файла решения в команде. Например, если файл решения называется Everything.sln, запустите следующую команду:
dotnet sln ./Everything.sln add (ls -r **/*.csproj)

Источник: https://ardalis.com/add-all-projects-to-solution/
👍15
День 1427. #УправлениеПроектом
Как Ускорить Конвейер Разработки ПО
Приоритетом в конвейере разработки ПО является скорость. Независимо от типа ПО, над которым вы работаете, скорость работы команды будет превыше всего. При этом необходимо знать некоторые стратегии, чтобы ускорить работу команды без ущерба для качества или безопасности кода. Вот советы, призванные помочь командам работать максимально быстро и эффективно.

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

2. Установите лимиты незавершенной работы
Сейчас большинство конвейеров разработки ПО соответствуют методологиям управления проектами Kanban или Scrum для отслеживания задач проекта на различных стадиях завершения. Эти элементы незавершенной работы (Work-In-Progress) помогают следить за прогрессом команды и её способностью выполнять больше работы.
Проблема в том, что часто этот список разрастается и выходит из-под контроля. Тогда члены команды пытаются работать в режиме многозадачности, переключаясь между различными элементами, чтобы попытаться избавиться от невыполненной работы. При этом темп работы команды обычно замедляется, а ошибки начинают проникать в код.
Люди плохо справляются с многозадачностью. Решение в том, чтобы не дать им этого сделать. Установка жёстких ограничений на количество элементов WIP, на каждом этапе рабочего процесса гарантирует, что члены команды не откусят больше, чем могут прожевать, и выполнят больше задач за меньшее время.

3. Централизуйте и автоматизируйте управление секретами
Большинство групп назначает одного человека для управления доступом ко всем необходимым системам и данным. Однако это создает узкое место, поскольку все запросы на доступ должны проходить через этого человека. Решение проблемы в централизации и автоматизации предоставления и отзыва доступа. Существует множество инструментов, которые могут помочь в этом, а также множество облачных решений для управления секретами.

4. Не срезайте углы, чтобы обойти проблемы с кодом
Во многих случаях команды разработчиков прибегают к быстрым и грязным исправлениям для решения проблем, чтобы двигаться дальше. Так ваш проект может накопить гору технического долга, и это дорого будет стоить вам в долгосрочной перспективе. Лучше потратить время на поиск реальных решений проблем по мере их возникновения. Даже если для этого придётся приостановить разработку, в долгосрочной перспективе вы сэкономите больше времени, т.к. истинные последствия срезанного угла могут стать очевидными только на более поздних этапах разработки, когда исправить это может быть практически невозможно.

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

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

Источник: https://www.freecodecamp.org/news/how-to-speed-up-your-software-development-pipeline/
👍4
День 1428. #ЧтоНовенького
Пишем Markdown в Visual Studio
Markdown — отличное решение для форматирования кода. GitHub использует его для файлов readme, a Microsoft - в качестве стандарта для документации Visual Studio.

Редактор Markdown должен быть включен и доступен, если вы обновились до последней превью версии VS 17.5. Его можно включить и отключить в меню Tools > Options > Preview Features (Инструменты > Параметры > Функции предварительного просмотра), отметив или сняв флажок “Markdown language service” (Сервис языка Markdown).

Вот некоторые функции редактора Markdown:
- Семантическая подсветка синтаксиса в редакторе.
- Форматирование текста применяется прямо в редакторе.
- Окно предварительного просмотра, которое можно вызвать по Shift+F7.
- Большинство стандартных элементов управления редактора Visual Studio работают и в редакторе Markdown.

Источник: https://devblogs.microsoft.com/visualstudio/write-markdown-without-leaving-visual-studio/
👍4
День 1429. #ЗаметкиНаПолях
Создание Дампа при Зависании Тестов на CI-машине
Когда на вашем компьютере возникают проблемы, отлаживать их просто, так как вы можете легко подключить отладчик и посмотреть, что происходит. Но если тесты зависают в CI/CD конвейере подключить отладчик не так просто. Приходится искать альтернативный способ отладки проблемы.

dotnet test имеет много полезных опций. Одной из них является --blame-hang, которая позволяет сделать дамп процесса и всех дочерних процессов, когда тест зависает. Вы можете настроить желаемый тайм-аут и тип дампа, который хотите сделать. Затем можно загрузить дамп в артефакты сборки и проанализировать его локально:
dotnet test 
--blame-hang-timeout 5m
--blame-hang-dump-type full

Если тест зависает, он завершается с ошибкой и выводит как минимум два файла: файл дампа для каждого процесса и файл последовательности. Файл последовательности содержит список тестов, которые выполнялись до зависания.

Если вы используете CI, например GitHub Actions, вы можете загрузить файл дампа как артефакт:
name: sample
on:
workflow_dispatch:
push:
branches:
- '*'

jobs:
run_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: dotnet test a.sln --configuration Debug --blame-hang-timeout 30s

- uses: actions/upload-artifact@v3
if: always()
with:
name: results
retention-days: 1
path: TestResults/**/*

Источник: https://www.meziantou.net/generating-a-dump-file-when-tests-hang-on-a-ci-machine.htm
👍5
День 1430. #Карьера
Улучшаем Эмоциональный Интеллект. Часть 1
Эмоциональный интеллект – это способность понимать эмоции и управлять ими, бесценное качество, которое поможет стать более продуктивными и улучшить отношения с другими. Вот простые правила, которые помогут развить ваш эмоциональный интеллект.

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

Для этого используется трехэтапный метод:
1. Мотивация
Если вы хотите изменить привычку, вы должны быть должным образом мотивированы, т.е. полностью убеждены в том, что привычку нужно изменить, и искренне хотеть её изменить.
Для этого нужно найти своё «почему». Почему вы хотите (и должны) изменить эту привычку? Какие преимущества вы получите, если добьётесь успеха?
Например, вы хотите проводить больше времени с семьей и укреплять важные отношения вне работы. А также улучшить здоровье, если сможете снизить уровень стресса, больше спать и с удовольствием проводить выходные.
Для этого нужно перестать брать на себя чрезмерные обязательства и установить чёткие границы между работой и остальной жизнью.

2. Практика
Чтобы овладеть любым новым навыком, нужно практиковать его много-много раз, пока он полностью не усвоится. И прежде, чем вы сможете изменить плохое поведение, вы должны сначала понять, почему вы реагируете определённым образом.
Это требует саморефлексии. Найти время для этого может быть непросто, поэтому выделите время в своём календаре на встречу с самим собой. Затем подумайте о том, когда вы в последний раз поддались дурной привычке или сказали или сделали что-то, о чем сожалеете.
Задайте себе такие вопросы:
- Почему я так отреагировал?
- Моя реакция помогла мне или навредила?
- Что бы я изменил, если бы мог сделать это снова?
- Что я мог бы сказать себе в следующий раз, что помогло бы мне мыслить более ясно?
После такого размышления вы понимаете, что ваша неспособность сказать «нет» проистекает из глубоко укоренившегося страха перед неудачей. Однако вы также понимаете, что ваша склонность к трудоголизму будет иметь негативные последствия для здоровья, а также для счастья вашей семьи.
Имея это в виду, вы можете установить реалистичные границы и стремиться к более здоровому балансу между работой и личной жизнью. Затем мысленно отрепетируйте — даже вслух — свою реакцию на следующий раз, когда клиент попросит о встрече в субботу или у вас возникнет искушение провести прекрасное воскресенье в своем домашнем офисе.

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

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

Источник:
https://www.inc.com/justin-bariso/how-to-increase-emotional-intelligence.html
👍10
День 1431.
Подводим итоги года. Поиграем в бинго? Присылайте свои ответы.

PS: Win+Shift+S для снимка экрана, потом в уведомлениях Snip & Sketch для рисования на нём.
👍5
День 1432.
Это был трудный год. Ой, это не оттуда.
Дорогие подписчики. От всей души поздравляю вас с новым годом! Чистого вам кода без багов, зелёных тестов, адекватных и щедрых заказчиков. Пусть всё у вас получается и удаётся.
👍62👎2