Получи случайную криптовалюту за регистрацию!

codaza

Логотип телеграм канала @codaza — codaza C
Логотип телеграм канала @codaza — codaza
Адрес канала: @codaza
Категории: Технологии
Язык: Русский
Количество подписчиков: 5.10K
Описание канала:

Канал о разработке на платформе .NET с использованием языка программирования C#. Рассматриваются актуальные подходы и современные методологии разработки.
YouTube:
https://www.youtube.com/c/codaza-channel
Контакты:
codaza.channel@gmail.com

Рейтинги и Отзывы

4.00

2 отзыва

Оценить канал codaza и оставить отзыв — могут только зарегестрированные пользователи. Все отзывы проходят модерацию.

5 звезд

0

4 звезд

2

3 звезд

0

2 звезд

0

1 звезд

0


Последние сообщения 2

2022-06-22 19:09:12
#капитану_на_заметку

Всем привет!

Недавно мне довелось провести в аэропорту 9 часов из-за непредвиденной задержки рейса. Было весело Но примечательно другое - когда мне пришла SMS с напоминаем о вылете, я обратил вниманием что время было указано неправильно, оно выглядело так, как будто смещение GMT было сделано дважды. Не уверен что так должно быть , но я подумал, что это отличная идея чтобы рассказать подписчикам codaza о необходимости использования перечисляемого типа DateTimeKind.

При определении DateTime, по умолчанию используется DateTimeKind.Unspecified, из-за чего приложение не может понять, какой часовой пояс вы используете. Поэтому очень важно указать формат, с которым вы работаете, иначе это может привести к SMS, которую я получил.

В своих проектах я предпочитаю формат UTC. Таким образом, вся работа с датами идёт в базовом формате, и конвертация в локальный формат производится только при отдаче данных на уровень представления (сайт, SMS и пр.).

+1 к тонкостям работы со временем
1.1K views16:09
Открыть/Комментировать
2022-06-05 11:28:47 Всем привет!

Недавно на канале вышло короткое видео, где я рассказал о 10 лучших практиках, которые стоит применять при разработке приложений на ASP.NET. Одна из этих практик - Глобальная Обработка Исключений (Global Exceptions Handling). В сегодняшнем ролике я раскрываю эту тему более подробно. Наливайте чайку и присаживайтесь поудобнее. Воскресенье — отличный день, чтобы обрабатывать исключения глобально.

Приятного просмотра!



818 views08:28
Открыть/Комментировать
2022-05-27 11:00:10
#капитану_на_заметку

Всем привет!

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

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

Посмотрите на пример выше. Вам хочется установить ширину прямоугольника? Сделайте это через свойство Width. Вам хочется установить длину прямоугольника? Да просто сделайте это уже в конце концов! Не пытайтесь препятствовать собственным желаниям

Рефакторингов много, но начните применять этот принцип сегодня, и вы увидите, как радуга падает на ваш исходник

+1 к простым мудростям

Всем хороших выходных!
1.0K views08:00
Открыть/Комментировать
2022-05-20 11:03:11
#капитану_на_заметку

Всем привет!

Как здорово генерировать исключения в секции try и ловко ловить их в секции catch Одно удовольствие работать с синхронным кодом. Мрачнее дела обстоят при работе с асинхронным кодом. Это как классическая механика и квантовая физика: в асинхронном коде постоянно возникает "квантовая запутанность" и работает там всё по другим законам

Взгляните на два примера на картинке. В первом варианте мы не ожидаем (await) результата выполнения Task.FromException(), а сразу возвращаем Task, что приводит к несрабатыванию блока catch. Во втором примере мы решаем эту проблему ожидая результат выполнения Task.FromException().

Такая ситуация может приводить к аварийному завершению всего приложения и отыскать причины будет очень непросто. Будьте внимательны!

Поиграться с примером можно по ссылке: https://clck.ru/hcRSc

+1 к тонкостям работы с асинхронным кодом

Всем хороших выходных!
857 views08:03
Открыть/Комментировать
2022-05-13 11:00:26 Всем привет!

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

Уверен, что в самых разных источниках, вы читали, что в качестве параметра метода следует использовать IEnumerable, если не требуется функциональность IList или List. Кроме того, хорошей практикой всегда считается следование принципу: Принимай наиболее общее (generic), а возвращай наиболее частное (specific). Это важные принципы, которых стоит придерживаться в подавляющем большинстве случаев. Всё же, бывают ситуации, в которых от этих принципов приходится отступать.

Как вы думаете, есть ли разница в определении параметра метода как IEnumerable или List?

Короткий ответ: да, разница есть.

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

+1 к производительному коду

Всем хороших выходных!
644 viewsedited  08:00
Открыть/Комментировать
2022-05-13 11:00:22
#капитану_на_заметку
643 viewsedited  08:00
Открыть/Комментировать
2022-05-06 11:00:04
#капитану_на_заметку

Всем привет!

Спешу поделиться с вами интересным практическим случаем работы со строками. Недавно мне довелось работать с одним из австрийских сервисов обработки сообщений из различных мессенджеров (WhatsApp, Viber и пр). Ребята собирают аналитическую статистику по отправляемым сообщениям и столкнулись с тем, что данные в этой статистике, время от времени, искажались непонятным образом.

Я проанализировал исходный код сервиса и обнаружил, что проблема в подсчёте длины строки сообщений. Разработчик сервиса воспользовался свойством Length у экземпляра класса String. Это решение было логично и казалось единственно верным. Проблема в том, что люди часто используют Emoji в своих сообщениях и 1 символ Emoji не равен длине одного символа, так как для их кодировки используется Unicode.

Для правильного сбора статистки требовалась именно посимвольная длина строки. Свойство LengthInTextElements (класс StringInfo) решает именно эту задачу.

+1 к опыту работу со строками

Всем хороших выходных!
1.5K views08:00
Открыть/Комментировать
2022-04-29 11:00:34
#капитану_на_заметку

Я никогда не делаю исключений. Исключения опровергают правило.

Артур Конан Дойл

Всем привет!

Тема правильной работы с исключениями (exceptions) весьма холиварна и едва ли подлежит окончательному разрешению Но сегодня я хочу обратить вниманием на другое — на цену. Цену использования исключений. Работаете вы с ними правильно или неправильно, держите в голове что за это придётся заплатить цену. При работе с большими массивами данных это может привести к значительной деградации производительности вашего приложения. Я не говорю о том, что мы не должны генерировать исключения, но разработчик обязан понимать, что выбрасывать исключения без аргументированной необходимости — плохая идея.

Руководствуйтесь простым правилом: Исключения для исключительных ситуаций.

Вы знаете как обработать исключение? Просто сделайте это без лишних throw

+1 к исключительному коду

Всем хороших выходных!
700 views08:00
Открыть/Комментировать
2022-04-22 11:11:04
#капитану_на_заметку

Всем привет!

В прошлый раз мы поговорили об использовании метода расширения AsSpan(), который можно вызывать на объектах класса String и предотвратить ненужные аллокации в оперативной памяти. В продолжении темы, мне хотелось бы рассказать про похожую возможность, но уже для коллекции List.

Возникают ситуации, когда нам нужно получить некоторый диапазон значений из List. Как поступал разработчик на C# до появления .NET5? Очень просто, он вызывал метод GetRange() и получал желаемый диапазон значений. Такое действие неминуемо сопровождается выделениями в оперативной памяти. Сегодня мы можем этого избежать и значительно снизить нагрузку на оперативную память воспользовавшись статическим методом AsSpan(), который располагается в классе CollectionsMarshal. Этот метод вернёт нам Span представление данных в списке, после чего можно вызвать метод Slice() c такими же параметрами, как у GetRange().

+1 к производительному коду

Всем хороших выходных!
604 views08:11
Открыть/Комментировать
2022-04-17 19:29:22 #codaza_отвечает

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

Где же был зарыт "главный слон" ? Проблема, с которой данный код никак нельзя было допускать в production-среду. Проблема была на строках 12-13:

int keyWordIndex = dataSlice.Value.TextFraction.Substring(actualPosition).IndexOf(keyWord);

Вызов метода Substring() - вот основная проблема. Дело в том, что при каждом вызове этого метода, в памяти будет создаваться полная копия строки, содержащаяся в свойстве TextFraction. Это не проблема при нечастных вызовах на небольших строках и без использования циклов. Для нашей ситуации это совершенно не годится, так как методу предстоит работать с большим массивом данных. Только представьте что может произойти с оперативной памятью при частых вызовах метода ExtractStochasticDataAsync(). И первым проблему заметил Александр Максименко, указав на то что вместо вызова Substring() следует делать вызов метода расширения для класса String - AsSpan(). Такой подход позволит не создавать копию строки TextFraction в оперативной памяти, что существенно снизит нагрузку на неё.

Далее, Александр увидел возможность для параллельной обработки данных в словаре dataSlices. При параллельной обработке нужно учитывать проблемы совместного доступа, поэтому, для словаря indexes, вместо Dictionary, Александр взял потокобезопасную коллекцию ConcurrentDictionary.

Метод ExtractStochasticDataAsync() является асинхронным и хорошей практикой является предоставления возможности для остановки метода (тем более метод работает в цикле с большим объемом данных). На эту проблему обратил внимание Aleksandr Radchenko, предложив использование CancellationToken.

Итоговый вариант после рефакторинга стал выглядеть так:

public async Task> ExtractStochasticDataAsync(string keyWord, CancellationToken ct = default)
{
IDictionary dataSlices = await LoadAnalyticalDataSlicesAsync(ct);

ConcurrentDictionary indexes = new();

var tasks = dataSlices.Select(async ds =>
{
ct.ThrowIfCancellationRequested();

int actualPosition = await LoadActualPositionAsync(ct);

int keyWordIndex = ds.Value.TextFraction
.AsSpan(actualPosition).IndexOf(keyWord);

indexes.TryAdd(ds.Key, keyWordIndex + actualPosition);
});

await Task.WhenAll(tasks);

return indexes;
}

Кроме того, Aleksandr Radchenko предложил еще ряд важных улучшений с примерами листингов (за что ему отдельное спасибо). Например, использовать в качестве возвращаемого значения метода ExtractStochasticDataAsync() асинхронную реализацию интерфейса IAsyncEnumerable и оператор yield, что позволит организовать асинхронную обработку данных из вызываемого метода. Это потребует изменение выходного API у метода ExtractStochasticDataAsync(), но если это возможно по имеющимся бизнес-требованиям, сделать это точно стоит. Этот вариант будет выглядеть так:

public async IAsyncEnumerable<(int Key, int Position)> ExtractStochasticDataAsync01(string keyWord, [EnumeratorCancellation] CancellationToken ct = default)
{
IDictionary dataSlices = await LoadAnalyticalDataSlicesAsync(ct);

foreach(var dataSlice in dataSlices)
{
int actualPosition = await LoadActualPositionAsync(ct);

int keyWordIndex = dataSlice.Value.TextFraction
.AsSpan(actualPosition).IndexOf(keyWord);

ct.ThrowIfCancellationRequested();

yield return (dataSlice.Key, keyWordIndex + actualPosition);
};
}

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

Всем активным участникам огромное спасибо за вклад!
775 views16:29
Открыть/Комментировать