День 2142. #ЗаметкиНаПолях
Пакеты NuGet: Риски Безопасности и Лучшие Практики. Начало
NuGet-пакеты предлагают удобный способ обмена кодом, но многие разработчики загружают их, не просматривая содержимое или не проверяя обновления при выпуске новых версий.
Когда вы устанавливаете NuGet-пакет, вы:
- Загружаете код неизвестных авторов, который, не обязательно был тщательно проверен другими;
- Запускаете его с полными правами на локальном компьютере, что потенциально раскрывает ваши персональные данные;
- Выполняете его с полным доступом на машинах непрерывной интеграции (CI), что подвергает риску ваши секреты и среду.
Рассмотрим, что может пойти не так.
Что может сделать NuGet-пакет?
1. props и targets в MSBuild
NuGet-пакет может содержать файлы MSBuild, которые автоматически импортируются при сборке проекта. Эти файлы могут изменить процесс сборки вашего приложения. Может быть запущен target, выполняющий команды, или динамический код C#. Также может изменяться код вашего приложения перед его сборкой.
Вы можете проверить содержимое файлов в папках build, buildMultitargeting и buildTransitive NuGet-пакета.
2. Анализаторы и генераторы исходного кода Roslyn
NuGet-пакеты могут содержать анализаторы Roslyn. Они выполняются во время проектирования в IDE и во время сборки и могут делать всё, что угодно на вашем компьютере. Хотя анализаторы предназначены для анализа кода, на самом деле они работают внутри процесса компиляции и могут делать всё (песочницы нет): писать файлы, обновлять двоичные файлы после компиляции и т.д.
Генераторы исходного кода Roslyn очень похожи на анализаторы, поэтому к ним применяются те же проблемы безопасности. Они также могут добавлять или обновлять код вашего приложения при его сборке.
Обратите внимание, что вы можете запретить загрузку анализаторов из пакета, используя свойства IncludeAssets или ExcludeAssets в файле .csproj. Например, вы можете использовать следующий код, чтобы загрузить только библиотеки из пакета:
См. подробнее об управлении ресурсами зависимостей.
3. Библиотеки
Вы уверены, что DLL в NuGet-пакете — те, которые вам нужны? Даже если код находится на GitHub, вы уверены, что DLL собраны из этого кода? Вы можете проверить содержимое DLL, декомпилировав его. Если символы (PDB) предоставлены и содержат правильную информацию, вы можете автоматически проверить, что код построен из предоставленного исходного кода.
4. Выполнение кода при установке/удалении пакета
NuGet-пакеты могут содержать скрипты PowerShell, которые выполняются при установке или удалении пакета. Обратите внимание, что эти скрипты выполняются только для проектов, которые не используют <PackageReference>. Поэтому для большинства современных проектов это не проблема.
Перед установкой пакета обязательно проверьте содержимое пакета. Вы можете сделать это, загрузив пакет и распаковав его. Обязательно проверьте следующие файлы:
Окончание следует…
Источник: https://meziantou.net/nuget-packages-security-risks-and-best-practices.htm
Пакеты NuGet: Риски Безопасности и Лучшие Практики. Начало
NuGet-пакеты предлагают удобный способ обмена кодом, но многие разработчики загружают их, не просматривая содержимое или не проверяя обновления при выпуске новых версий.
Когда вы устанавливаете NuGet-пакет, вы:
- Загружаете код неизвестных авторов, который, не обязательно был тщательно проверен другими;
- Запускаете его с полными правами на локальном компьютере, что потенциально раскрывает ваши персональные данные;
- Выполняете его с полным доступом на машинах непрерывной интеграции (CI), что подвергает риску ваши секреты и среду.
Рассмотрим, что может пойти не так.
Что может сделать NuGet-пакет?
1. props и targets в MSBuild
NuGet-пакет может содержать файлы MSBuild, которые автоматически импортируются при сборке проекта. Эти файлы могут изменить процесс сборки вашего приложения. Может быть запущен target, выполняющий команды, или динамический код C#. Также может изменяться код вашего приложения перед его сборкой.
Вы можете проверить содержимое файлов в папках build, buildMultitargeting и buildTransitive NuGet-пакета.
2. Анализаторы и генераторы исходного кода Roslyn
NuGet-пакеты могут содержать анализаторы Roslyn. Они выполняются во время проектирования в IDE и во время сборки и могут делать всё, что угодно на вашем компьютере. Хотя анализаторы предназначены для анализа кода, на самом деле они работают внутри процесса компиляции и могут делать всё (песочницы нет): писать файлы, обновлять двоичные файлы после компиляции и т.д.
Генераторы исходного кода Roslyn очень похожи на анализаторы, поэтому к ним применяются те же проблемы безопасности. Они также могут добавлять или обновлять код вашего приложения при его сборке.
Обратите внимание, что вы можете запретить загрузку анализаторов из пакета, используя свойства IncludeAssets или ExcludeAssets в файле .csproj. Например, вы можете использовать следующий код, чтобы загрузить только библиотеки из пакета:
<PackageReference Include="Some.Package" Version="3.2.1">
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
См. подробнее об управлении ресурсами зависимостей.
3. Библиотеки
Вы уверены, что DLL в NuGet-пакете — те, которые вам нужны? Даже если код находится на GitHub, вы уверены, что DLL собраны из этого кода? Вы можете проверить содержимое DLL, декомпилировав его. Если символы (PDB) предоставлены и содержат правильную информацию, вы можете автоматически проверить, что код построен из предоставленного исходного кода.
4. Выполнение кода при установке/удалении пакета
NuGet-пакеты могут содержать скрипты PowerShell, которые выполняются при установке или удалении пакета. Обратите внимание, что эти скрипты выполняются только для проектов, которые не используют <PackageReference>. Поэтому для большинства современных проектов это не проблема.
Перед установкой пакета обязательно проверьте содержимое пакета. Вы можете сделать это, загрузив пакет и распаковав его. Обязательно проверьте следующие файлы:
tools/init.ps1
tools/install.ps1
tools/uninstall.ps1
Окончание следует…
Источник: https://meziantou.net/nuget-packages-security-risks-and-best-practices.htm
👍14
День 2143. #ЗаметкиНаПолях
Пакеты NuGet: Риски Безопасности и Передовой Опыт. Окончание
Начало
Другие векторы атаки
1. Тайпсквоттинг
Злоумышленник может создать пакет с именем похожим на популярный пакет. Например, Newtonsoft.Json можно заменить на Newtomsoft.Json или Newtomsoft-Json. Это называется тайпсквоттинг (атака через опечатки). Обязательно проверьте имя пакета перед его установкой.
Обратите внимание, что nuget.org позволяет резервировать префикс для предотвращения такого рода атак. Например, Newtonsoft – единственный автор, кто может создать пакет с префиксом Newtonsoft. Все его пакеты имеют галочку, указывающую на то, что они из зарезервированного префикса.
2. Тот же пакет, что и приватный пакет
Если у вас есть пакет, опубликованный во внутреннем канале, таком как Azure Packages, с тем же именем, что и у публичного пакета, публичный пакет можно использовать вместо приватного. Это проблема безопасности, поскольку вы не знаете содержимое публичного пакета. Вы можете использовать сопоставление источников пакетов, чтобы предотвратить эту проблему.
3. Удалённый пакет
Даже если вы проверили пакет и установили его, вы можете быть не в безопасности. На nuget.org вы не можете удалить пакет. Вы можете только пометить его как исключённый из списка (unlisted). Unlisted-пакет не отображается на веб-сайте или при разрешении графа пакетов. Но когда пакет обновляется, вы автоматически получаете новую версию. Это означает, что ваше приложение может использовать новую версию пакета, которую вы не проверили.
Чтобы предотвратить эту проблему, вы можете использовать файл блокировки (Lock-файл). Он содержит точную версию используемых вами пакетов. При восстановлении пакетов вы получаете точную версию, которую использовали ранее.
Лучшие практики
1. Проверяйте содержимое NuGet-пакета перед его установкой с помощью такого инструмента, как NuGet Package Explorer.
2. Используйте файл блокировки, чтобы предотвратить использование версии пакета, отличной от проверенной.
3. Используйте сопоставление источников пакетов, если ваш источник отличается от nuget.org.
4. Используйте IncludedAssets или ExcludedAssets для управления ресурсами, загруженными из пакета.
5. Проверяйте использование зарезервированного префикса, чтобы предотвратить тайпсквоттинг из-за опечаток
Итого
NuGet-пакет может:
- Выполнять код на вашем компьютере с разрешениями текущего пользователя.
- Выполнять код на CI-машинах с разрешениями пользователя CI.
- Изменять код вашего приложения и потенциально добавлять вредоносный код. Так он может выполнять код на ваших производственных компьютерах.
- Большинство пакетов безопасны, но вы не знаете, что может произойти в будущем. Взлом аккаунта NuGet или GitHub — это не редкость. Поэтому обязательно проверяйте содержимое пакетов, которые вы устанавливаете или обновляете.
И последнее, но не менее важное: другие менеджеры пакетов имеют похожие проблемы. Будьте бдительны при использовании любого пакета!
Источник: https://meziantou.net/nuget-packages-security-risks-and-best-practices.htm
Пакеты NuGet: Риски Безопасности и Передовой Опыт. Окончание
Начало
Другие векторы атаки
1. Тайпсквоттинг
Злоумышленник может создать пакет с именем похожим на популярный пакет. Например, Newtonsoft.Json можно заменить на Newtomsoft.Json или Newtomsoft-Json. Это называется тайпсквоттинг (атака через опечатки). Обязательно проверьте имя пакета перед его установкой.
Обратите внимание, что nuget.org позволяет резервировать префикс для предотвращения такого рода атак. Например, Newtonsoft – единственный автор, кто может создать пакет с префиксом Newtonsoft. Все его пакеты имеют галочку, указывающую на то, что они из зарезервированного префикса.
2. Тот же пакет, что и приватный пакет
Если у вас есть пакет, опубликованный во внутреннем канале, таком как Azure Packages, с тем же именем, что и у публичного пакета, публичный пакет можно использовать вместо приватного. Это проблема безопасности, поскольку вы не знаете содержимое публичного пакета. Вы можете использовать сопоставление источников пакетов, чтобы предотвратить эту проблему.
3. Удалённый пакет
Даже если вы проверили пакет и установили его, вы можете быть не в безопасности. На nuget.org вы не можете удалить пакет. Вы можете только пометить его как исключённый из списка (unlisted). Unlisted-пакет не отображается на веб-сайте или при разрешении графа пакетов. Но когда пакет обновляется, вы автоматически получаете новую версию. Это означает, что ваше приложение может использовать новую версию пакета, которую вы не проверили.
Чтобы предотвратить эту проблему, вы можете использовать файл блокировки (Lock-файл). Он содержит точную версию используемых вами пакетов. При восстановлении пакетов вы получаете точную версию, которую использовали ранее.
Лучшие практики
1. Проверяйте содержимое NuGet-пакета перед его установкой с помощью такого инструмента, как NuGet Package Explorer.
2. Используйте файл блокировки, чтобы предотвратить использование версии пакета, отличной от проверенной.
3. Используйте сопоставление источников пакетов, если ваш источник отличается от nuget.org.
4. Используйте IncludedAssets или ExcludedAssets для управления ресурсами, загруженными из пакета.
5. Проверяйте использование зарезервированного префикса, чтобы предотвратить тайпсквоттинг из-за опечаток
Итого
NuGet-пакет может:
- Выполнять код на вашем компьютере с разрешениями текущего пользователя.
- Выполнять код на CI-машинах с разрешениями пользователя CI.
- Изменять код вашего приложения и потенциально добавлять вредоносный код. Так он может выполнять код на ваших производственных компьютерах.
- Большинство пакетов безопасны, но вы не знаете, что может произойти в будущем. Взлом аккаунта NuGet или GitHub — это не редкость. Поэтому обязательно проверяйте содержимое пакетов, которые вы устанавливаете или обновляете.
И последнее, но не менее важное: другие менеджеры пакетов имеют похожие проблемы. Будьте бдительны при использовании любого пакета!
Источник: https://meziantou.net/nuget-packages-security-risks-and-best-practices.htm
👍14
День 2144. #Оффтоп
Развлекаемся с ValueTuple
Этот пост, скорее всего, не принесёт вам никакой пользы в вашей повседневной жизни — ну, разве что улыбку. Сегодня мы доведём ValueTuple до крайности!
Тип ValueTuple — это приятный синтаксический сахар. Если у вас есть следующий код, даже если вы назвали элементы кортежа:
Это будет преобразовано компилятором в:
Итак, компилятор генерирует список элементов, пронумерованных от 1 до любого количества элементов, которые у вас есть. Но происходит что-то интересное, если вы добавляете больше 7 элементов:
Это преобразовывается компилятором в:
После 7го элемента компилятор генерирует новое свойство Rest для хранения… ну, остального. Поэтому, если мы немного посходим с ума:
И используем это так:
То мы получим что-то вроде
Если хотите поиграть с этим, заходите на sharblap.io.
Источник: https://steven-giesel.com/blogPost/0a3db64c-e514-45fc-a1a1-2b79cc42f797/having-fun-with-valuetuple
Развлекаемся с ValueTuple
Этот пост, скорее всего, не принесёт вам никакой пользы в вашей повседневной жизни — ну, разве что улыбку. Сегодня мы доведём ValueTuple до крайности!
Тип ValueTuple — это приятный синтаксический сахар. Если у вас есть следующий код, даже если вы назвали элементы кортежа:
(var one, var two) = MyFunc();
Console.WriteLine(one + two);
(int ANumber, int AnotherNumber)
MyFunc() => (1,2);
Это будет преобразовано компилятором в:
[CompilerGenerated]
internal class Program
{
private static void <Main>$(string[] args)
{
ValueTuple<int, int> valueTuple = <<Main>$>g__MyFunc|0_0();
int item = valueTuple.Item1;
int item2 = valueTuple.Item2;
Console.WriteLine(item + item2);
}
[CompilerGenerated]
[return: TupleElementNames(new string[] { "ANumber", "AnotherNumber" })]
internal static ValueTuple<int, int> <<Main>$>g__MyFunc|0_0()
{
return new ValueTuple<int, int>(1, 2);
}
}
Итак, компилятор генерирует список элементов, пронумерованных от 1 до любого количества элементов, которые у вас есть. Но происходит что-то интересное, если вы добавляете больше 7 элементов:
var (a,b,c,d,e,f,g,h) = MyFunc();
Console.WriteLine(a+b+c+d+e+f+g+h);
(int a, int b, int c, int d, int e, int f, int g, int h) MyFunc()
=> (1,2,3,4,5,6,7,8);
Это преобразовывается компилятором в:
ValueTuple<int, int, int, int, int, int, int, ValueTuple<int>> valueTuple = <<Main>$>g__MyFunc|0_0();
int item = valueTuple.Item1;
int item2 = valueTuple.Item2;
int item3 = valueTuple.Item3;
int item4 = valueTuple.Item4;
int item5 = valueTuple.Item5;
int item6 = valueTuple.Item6;
int item7 = valueTuple.Item7;
int item8 = valueTuple.Rest.Item1;
Console.WriteLine(item + item2 + item3 + item4 + item5 + item6 + item7 + item8);
После 7го элемента компилятор генерирует новое свойство Rest для хранения… ну, остального. Поэтому, если мы немного посходим с ума:
(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s, int t, int u, int v, int w, int x, int y, int z, int aa, int bb, int cc, int dd, int ee, int ff, int gg, int hh, int ii, int jj, int kk, int ll, int mm, int nn, int oo, int pp, int qq, int rr, int ss, int tt, int uu, int vv, int ww, int xx) MyFunc()
{
return (1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50);
}
И используем это так:
var (a,b,c,…,xx) = MyFunc();
То мы получим что-то вроде
valueTuple.Rest.Rest.Rest.Rest.Item1
.Если хотите поиграть с этим, заходите на sharblap.io.
Источник: https://steven-giesel.com/blogPost/0a3db64c-e514-45fc-a1a1-2b79cc42f797/having-fun-with-valuetuple
👍22👎1
День 2145. #Карьера
Метрика Улучшения
В аэропорту при проходе через службу безопасности можно наблюдать интересный момент. Используем эту аналогию, чтобы поразмышлять о том, что люди делают с кодом.
Вы складываете вещи в контейнеры, отправляете их по ленте, и проходите через рамку. Дальше все стоят и ждут свои вещи. Телефонов в руках нет, поэтому их ничто не отвлекает. Контейнеры приезжают по ленте, и люди забирают свои вещи. И часто нет специально выделенного человека, который бы убирал контейнеры. Так можно выделить несколько групп людей.
Группа A
Большинство берут свои вещи, но оставляют контейнеры на ленте, по сути, создавая кучу пустых контейнеров, что в итоге заставляет кого-то другого убрать их с ленты, чтобы освободить место для своего контейнера. Эти люди выполнили свои задачи, но оставили технический долг для уборки другими.
Группа B
Другие берут свои вещи и снимают контейнер с ленты, приложив дополнительные усилия, чтобы не оставлять окружающую среду хуже, чем она была.
Группа C
Небольшая группа складывает все контейнеры и очищает ленту, но только когда лента заполнена, то есть они действуют так только для того, чтобы освободить место для своего контейнера.
Группа D
Наконец, несколько человек (меньшинство) используют своё время ожидания, чтобы улучшить систему для всех. Они убирают все оставшиеся контейнеры, чтобы очистить ленту, даже когда лента не заполнена.
Одной из метрик оценки качества программиста, которую можно использовать, является «Улучшение» (Betterment). Может ли программист определять области для улучшения и делает ли он их лучше без подсказок?
Некоторым может быть сложно представить, как они могут улучшить работу. Этот небольшой пример служит отличной аналогией для применения показателя улучшения.
Группа A: ниже ожиданий
Эта группа сосредоточилась только на достижении собственных целей, непреднамеренно ухудшая систему, оставляя больше работы другим.
Группа B: соответствуют ожиданиям
Эта группа не только сосредоточилась на своих целях, но и позаботилась о том, чтобы оставить систему нетронутой.
Группа C: соответствуют ожиданиям
Хотя эта группа действительно улучшила систему, их усилия были ситуативными и реактивными, и происходили только тогда, когда препятствие мешало им достичь своей цели.
Группа D: превышают ожидания
Эта группа последовательно действовала, чтобы очистить ленту и улучшить систему, обеспечивая бесперебойную работу для всех, даже когда это не было их работой или напрямую не влияло на них.
Будь то проход через службу безопасности в аэропорту или ваша кодовая база, вопрос в том, к какой группе вы хотите принадлежать?
Источник: https://angiejones.tech/the-betterment-metric/
Метрика Улучшения
В аэропорту при проходе через службу безопасности можно наблюдать интересный момент. Используем эту аналогию, чтобы поразмышлять о том, что люди делают с кодом.
Вы складываете вещи в контейнеры, отправляете их по ленте, и проходите через рамку. Дальше все стоят и ждут свои вещи. Телефонов в руках нет, поэтому их ничто не отвлекает. Контейнеры приезжают по ленте, и люди забирают свои вещи. И часто нет специально выделенного человека, который бы убирал контейнеры. Так можно выделить несколько групп людей.
Группа A
Большинство берут свои вещи, но оставляют контейнеры на ленте, по сути, создавая кучу пустых контейнеров, что в итоге заставляет кого-то другого убрать их с ленты, чтобы освободить место для своего контейнера. Эти люди выполнили свои задачи, но оставили технический долг для уборки другими.
Группа B
Другие берут свои вещи и снимают контейнер с ленты, приложив дополнительные усилия, чтобы не оставлять окружающую среду хуже, чем она была.
Группа C
Небольшая группа складывает все контейнеры и очищает ленту, но только когда лента заполнена, то есть они действуют так только для того, чтобы освободить место для своего контейнера.
Группа D
Наконец, несколько человек (меньшинство) используют своё время ожидания, чтобы улучшить систему для всех. Они убирают все оставшиеся контейнеры, чтобы очистить ленту, даже когда лента не заполнена.
Одной из метрик оценки качества программиста, которую можно использовать, является «Улучшение» (Betterment). Может ли программист определять области для улучшения и делает ли он их лучше без подсказок?
Некоторым может быть сложно представить, как они могут улучшить работу. Этот небольшой пример служит отличной аналогией для применения показателя улучшения.
Группа A: ниже ожиданий
Эта группа сосредоточилась только на достижении собственных целей, непреднамеренно ухудшая систему, оставляя больше работы другим.
Группа B: соответствуют ожиданиям
Эта группа не только сосредоточилась на своих целях, но и позаботилась о том, чтобы оставить систему нетронутой.
Группа C: соответствуют ожиданиям
Хотя эта группа действительно улучшила систему, их усилия были ситуативными и реактивными, и происходили только тогда, когда препятствие мешало им достичь своей цели.
Группа D: превышают ожидания
Эта группа последовательно действовала, чтобы очистить ленту и улучшить систему, обеспечивая бесперебойную работу для всех, даже когда это не было их работой или напрямую не влияло на них.
Будь то проход через службу безопасности в аэропорту или ваша кодовая база, вопрос в том, к какой группе вы хотите принадлежать?
Источник: https://angiejones.tech/the-betterment-metric/
👍12
День 2146. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 35. От передачи знаний выигрывают все
Знания не похожи на материальные предметы. Если у меня есть 3 штуки чего-то, и я дам вам 1, то у меня останется 2. Я должен потерять часть, чтобы вы что-то приобрели. Но со знаниями дело обстоит иначе: если я передам вам часть своих знаний, то не потеряю их. Я могу поделиться ими с другими людьми, как и вы. Этот расширяющийся круг знаний приносит пользу всем.
Пожиратели знаний
Некоторые неохотно передают свои знания из-за неуверенности. Они опасаются, что, поделившись с другими своими знаниями, добытыми с таким трудом, станут менее конкурентоспособными. Некоторые тщательно охраняют свои знания, стремясь получить гарантии своей востребованности. Если никто другой не знает того, что знают они, то компания не сможет их уволить, поскольку потеряет слишком много специфических знаний.
Люди, скрывающие организационные знания, представляют опасность. Они создают среду, которая может помешать работе других людей. Сокрытие информации является отличной практикой для проектирования ПО, но плохо подходит для команд разработчиков.
Исправление невежества
Здоровая организация способствует культуре свободного обмена знаниями и непрерывного обучения. Обмен знаниями повышает продуктивность каждого, поэтому руководство должно вознаграждать тех, кто свободно передаёт свои знания, а не тех, кто держит их при себе. В организации, поощряющей обучение, члены команды уверены, что могут без опаски задавать вопросы.
Опытные сотрудники могут передавать свой опыт разными путями. Помимо простых ответов на вопросы, эксперты могут делиться своими мыслями о том, как применять знания в конкретных ситуациях. Они должны быть доступными для коллег, особенно новичков, и быть вдумчивыми и терпеливыми, когда кто-то донимает их расспросами.
В некоторых организациях существуют официальные программы наставничества, помогающие ускорить адаптацию новых сотрудников. Закрепление новых сотрудников за опытными коллегами-наставниками значительно ускоряет обучение.
Расширение масштабов передачи знаний
Для развития культуры обмена знаниями есть несколько вариантов, кроме общения 1 на 1.
1. Технические беседы
Можно обсуждать прочитанные книги или статьи с коллегами за обедом. Это способствует формированию общего понимания материала и общего словарного запаса.
2. Презентации и обучение
Если вы создаёте внутреннюю программу обучения, подберите несколько квалифицированных инструкторов, чтобы одному человеку не приходилось всё время читать одни и те же курсы.
3. Документация
Письменная документация — очень эффективный организационный актив при условии, что члены команды воспринимают его как полезный ресурс. Все члены организации должны иметь возможность обновлять такие документы, чтобы они оставались ценными источниками коллективного опыта.
4. Готовые шаблоны и примеры
Можно создать репозиторий кода с примерами шаблонов и лучших практик, используемых в компании.
5. Технические обзоры
Обзоры кода тоже могут служить неформальным механизмом обмена техническими знаниями. Это отличный способ посмотреть, как работает другой человек, и позволить ему понаблюдать за вашей работой.
6. Дискуссионные группы
Можно опубликовать вопрос в групповом чате компании. Признаваться в незнании перед большим сообществом может быть неудобно. Поэтому важно развивать культуру, в которой поощряется желание задавать вопросы и вознаграждаются те, кто помогает получить на них ответ. Не стыдно не знать, стыдно не учиться.
Здоровая информационная культура
Необязательно быть экспертом в какой-то теме, чтобы быть полезным. Нужен лишь какой-то ценный блок знаний и готовность поделиться ими. В мире технологий, если вы на неделю опережаете другого человека в какой-либо области, то вы волшебник. Кто-то другой, несомненно, опережает вас в других областях, поэтому воспользуйтесь его знаниями. Люди в здоровой культуре обучения делятся тем, что они знают, а также признают, что кто-то другой может знать способ лучше.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
Уроки 50 Лет Разработки ПО
Урок 35. От передачи знаний выигрывают все
Знания не похожи на материальные предметы. Если у меня есть 3 штуки чего-то, и я дам вам 1, то у меня останется 2. Я должен потерять часть, чтобы вы что-то приобрели. Но со знаниями дело обстоит иначе: если я передам вам часть своих знаний, то не потеряю их. Я могу поделиться ими с другими людьми, как и вы. Этот расширяющийся круг знаний приносит пользу всем.
Пожиратели знаний
Некоторые неохотно передают свои знания из-за неуверенности. Они опасаются, что, поделившись с другими своими знаниями, добытыми с таким трудом, станут менее конкурентоспособными. Некоторые тщательно охраняют свои знания, стремясь получить гарантии своей востребованности. Если никто другой не знает того, что знают они, то компания не сможет их уволить, поскольку потеряет слишком много специфических знаний.
Люди, скрывающие организационные знания, представляют опасность. Они создают среду, которая может помешать работе других людей. Сокрытие информации является отличной практикой для проектирования ПО, но плохо подходит для команд разработчиков.
Исправление невежества
Здоровая организация способствует культуре свободного обмена знаниями и непрерывного обучения. Обмен знаниями повышает продуктивность каждого, поэтому руководство должно вознаграждать тех, кто свободно передаёт свои знания, а не тех, кто держит их при себе. В организации, поощряющей обучение, члены команды уверены, что могут без опаски задавать вопросы.
Опытные сотрудники могут передавать свой опыт разными путями. Помимо простых ответов на вопросы, эксперты могут делиться своими мыслями о том, как применять знания в конкретных ситуациях. Они должны быть доступными для коллег, особенно новичков, и быть вдумчивыми и терпеливыми, когда кто-то донимает их расспросами.
В некоторых организациях существуют официальные программы наставничества, помогающие ускорить адаптацию новых сотрудников. Закрепление новых сотрудников за опытными коллегами-наставниками значительно ускоряет обучение.
Расширение масштабов передачи знаний
Для развития культуры обмена знаниями есть несколько вариантов, кроме общения 1 на 1.
1. Технические беседы
Можно обсуждать прочитанные книги или статьи с коллегами за обедом. Это способствует формированию общего понимания материала и общего словарного запаса.
2. Презентации и обучение
Если вы создаёте внутреннюю программу обучения, подберите несколько квалифицированных инструкторов, чтобы одному человеку не приходилось всё время читать одни и те же курсы.
3. Документация
Письменная документация — очень эффективный организационный актив при условии, что члены команды воспринимают его как полезный ресурс. Все члены организации должны иметь возможность обновлять такие документы, чтобы они оставались ценными источниками коллективного опыта.
4. Готовые шаблоны и примеры
Можно создать репозиторий кода с примерами шаблонов и лучших практик, используемых в компании.
5. Технические обзоры
Обзоры кода тоже могут служить неформальным механизмом обмена техническими знаниями. Это отличный способ посмотреть, как работает другой человек, и позволить ему понаблюдать за вашей работой.
6. Дискуссионные группы
Можно опубликовать вопрос в групповом чате компании. Признаваться в незнании перед большим сообществом может быть неудобно. Поэтому важно развивать культуру, в которой поощряется желание задавать вопросы и вознаграждаются те, кто помогает получить на них ответ. Не стыдно не знать, стыдно не учиться.
Здоровая информационная культура
Необязательно быть экспертом в какой-то теме, чтобы быть полезным. Нужен лишь какой-то ценный блок знаний и готовность поделиться ими. В мире технологий, если вы на неделю опережаете другого человека в какой-либо области, то вы волшебник. Кто-то другой, несомненно, опережает вас в других областях, поэтому воспользуйтесь его знаниями. Люди в здоровой культуре обучения делятся тем, что они знают, а также признают, что кто-то другой может знать способ лучше.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
10👍12
День 2147. #ЧтоНовенького
Новинки Visual Studio 17.12
В новой версии Visual Studio 2022 (17.12) представлено несколько интересных новинок.
1. Уведомление о переименовании файла
Часто возникает путаница в том, как работает Git при переименовании файлов. Git не хранит никакой информации для отслеживания переименований. Даже когда вы запускаете операцию git mv, это всего лишь сокращение для выполнения git rm, а затем git add для файла. Иногда Git запускает обнаружение переименования и может отображать удаление+добавление как переименование, но под капотом он использует эвристику, основанную на сходстве двух файлов, чтобы назвать это переименованием — и иногда он ошибается!
Когда вы переименовываете файл в Solution Explorer и смотрите на список изменённых файлов, это отображается как удаление+добавление. После того как вы сделаете Stage изменений, Git запустит обнаружение переименования, и вы сможете увидеть, как он заменит удаление+добавление на переименование в разделе Stage. Чтобы напоминать вам об этом, и добавлено новое уведомление.
2. Постоянная ссылка на код
Если вам нужно поделиться фрагментом кода с коллегами, вы знаете, как сложно сохранить контекст. С новой функцией Copy Git Permalink (Копировать Постоянную Ссылку на Git) вы теперь можете создать постоянную ссылку непосредственно из VS на удалённый репозиторий. Просто выберите нужный код, щёлкните правой кнопкой мыши и выберите Git > Copy Permalink. Ваш коллега сможет открыть ссылку, которой вы поделились, чтобы перейти к этой строке кода в интернет. Функция поддерживает репозитории Azure DevOps и GitHub (требуется вход в систему).
3. Подсказка о возвращаемых значениях
Вы когда-нибудь создавали временные переменные, только чтобы проверить возвращаемые значения функций? Эта новая функция позволит просматривать возвращаемые значения непосредственно в коде.
Раньше можно было посмотреть возвращаемые значения в окнах Autos или Locals. Они появляются после выхода из функции и возврата вызывающей стороне. Новая функция показывает эту информацию до выхода из функции и непосредственно в редакторе. Когда вы достигаете точки останова или проходите по коду, VS 2022 автоматически отображает значение, которое будет возвращено, в строке рядом с закрывающей скобкой метода.
Чтобы подробнее изучить возвращаемые значения, наведите указатель мыши это него и щёлкните значок Ask Copilot (Спросить Copilot) на подсказке по данным. Откроется новое окно чата Copilot, отладчик соберёт соответствующий контекст и передаст его Copilot для анализа. Copilot объяснит, почему вы видите это значение, предоставит информацию о потенциальных проблемах и даже сможет предложить исправления кода.
4. Неблокирующая очистка кода
Традиционный процесс Code Cleanup в VS может занимать некоторое время и заблокировать всю IDE, что делало его нецелесообразным для запуска при каждом сохранении. Теперь, когда вы сохраняете свою работу, Code Cleanup может работать в фоновом режиме, не прерывая ваш рабочий процесс. Больше не нужно ждать завершения очистки, прежде чем возобновить работу. Если вам нужно внести изменения, то, когда редактор обнаруживает пользовательский ввод, процесс очистки останавливается. Сохранитесь ещё раз, чтобы перезапустить очистку обновленного кода.
Включить очистку кода при сохранении можно в меню Tools > Options > Text Editor > Code Cleanup (Инструменты > Опции > Текстовый Редактор > Очистка Кода).
Источники:
- https://devblogs.microsoft.com/visualstudio/boost-your-git-confidence-with-the-new-file-rename-notification/
- https://devblogs.microsoft.com/visualstudio/introducing-the-copy-git-permalink-feature-in-visual-studio-17-12/
- https://devblogs.microsoft.com/visualstudio/how-inline-return-values-simplify-debugging-in-visual-studio-2022/
- https://devblogs.microsoft.com/visualstudio/keep-working-with-non-blocking-code-cleanup/
Новинки Visual Studio 17.12
В новой версии Visual Studio 2022 (17.12) представлено несколько интересных новинок.
1. Уведомление о переименовании файла
Часто возникает путаница в том, как работает Git при переименовании файлов. Git не хранит никакой информации для отслеживания переименований. Даже когда вы запускаете операцию git mv, это всего лишь сокращение для выполнения git rm, а затем git add для файла. Иногда Git запускает обнаружение переименования и может отображать удаление+добавление как переименование, но под капотом он использует эвристику, основанную на сходстве двух файлов, чтобы назвать это переименованием — и иногда он ошибается!
Когда вы переименовываете файл в Solution Explorer и смотрите на список изменённых файлов, это отображается как удаление+добавление. После того как вы сделаете Stage изменений, Git запустит обнаружение переименования, и вы сможете увидеть, как он заменит удаление+добавление на переименование в разделе Stage. Чтобы напоминать вам об этом, и добавлено новое уведомление.
2. Постоянная ссылка на код
Если вам нужно поделиться фрагментом кода с коллегами, вы знаете, как сложно сохранить контекст. С новой функцией Copy Git Permalink (Копировать Постоянную Ссылку на Git) вы теперь можете создать постоянную ссылку непосредственно из VS на удалённый репозиторий. Просто выберите нужный код, щёлкните правой кнопкой мыши и выберите Git > Copy Permalink. Ваш коллега сможет открыть ссылку, которой вы поделились, чтобы перейти к этой строке кода в интернет. Функция поддерживает репозитории Azure DevOps и GitHub (требуется вход в систему).
3. Подсказка о возвращаемых значениях
Вы когда-нибудь создавали временные переменные, только чтобы проверить возвращаемые значения функций? Эта новая функция позволит просматривать возвращаемые значения непосредственно в коде.
Раньше можно было посмотреть возвращаемые значения в окнах Autos или Locals. Они появляются после выхода из функции и возврата вызывающей стороне. Новая функция показывает эту информацию до выхода из функции и непосредственно в редакторе. Когда вы достигаете точки останова или проходите по коду, VS 2022 автоматически отображает значение, которое будет возвращено, в строке рядом с закрывающей скобкой метода.
Чтобы подробнее изучить возвращаемые значения, наведите указатель мыши это него и щёлкните значок Ask Copilot (Спросить Copilot) на подсказке по данным. Откроется новое окно чата Copilot, отладчик соберёт соответствующий контекст и передаст его Copilot для анализа. Copilot объяснит, почему вы видите это значение, предоставит информацию о потенциальных проблемах и даже сможет предложить исправления кода.
4. Неблокирующая очистка кода
Традиционный процесс Code Cleanup в VS может занимать некоторое время и заблокировать всю IDE, что делало его нецелесообразным для запуска при каждом сохранении. Теперь, когда вы сохраняете свою работу, Code Cleanup может работать в фоновом режиме, не прерывая ваш рабочий процесс. Больше не нужно ждать завершения очистки, прежде чем возобновить работу. Если вам нужно внести изменения, то, когда редактор обнаруживает пользовательский ввод, процесс очистки останавливается. Сохранитесь ещё раз, чтобы перезапустить очистку обновленного кода.
Включить очистку кода при сохранении можно в меню Tools > Options > Text Editor > Code Cleanup (Инструменты > Опции > Текстовый Редактор > Очистка Кода).
Источники:
- https://devblogs.microsoft.com/visualstudio/boost-your-git-confidence-with-the-new-file-rename-notification/
- https://devblogs.microsoft.com/visualstudio/introducing-the-copy-git-permalink-feature-in-visual-studio-17-12/
- https://devblogs.microsoft.com/visualstudio/how-inline-return-values-simplify-debugging-in-visual-studio-2022/
- https://devblogs.microsoft.com/visualstudio/keep-working-with-non-blocking-code-cleanup/
👍10
День 2148. #ЗаметкиНаПолях
Гибридный Кэш в ASP.NET Core 9. Начало
В .NET 9 представлен гибридный кэш (HybridCache), механизм кэширования, который сочетает скорость кэширования в памяти с масштабируемостью распределённого кэширования. Я уже писал о новинке тут. Теперь рассмотрим его подробнее.
Что это?
HybridCache — это абстрактный класс с реализацией по умолчанию, который обрабатывает большинство аспектов сохранения в кэш и извлечения из кэша. HybridCache также включает в себя некоторые важные функции, относящиеся к процессу кэширования:
- Двухуровневое кэширование (L1/L2)
Использует быстрый кэш в памяти (L1) для быстрого извлечения данных и распределённый кэш (L2) для согласованности данных в нескольких экземплярах приложения.
- Защита от паники в кэше
Предотвращает панику в кэше при нескольких параллельных запросах, гарантируя, что только один запрос извлекает данные, а другие ждут, что снижает ненужную нагрузку.
- Инвалидация на основе тегов
Позволяет группировать записи кэша тегами, что обеспечивает эффективное удаление связанных элементов кэша одновременно.
- Настраиваемая сериализация
Позволяет настраивать методы сериализации данных, поддерживая различные форматы, такие как JSON, Protobuf или XML, в соответствии с потребностями конкретного приложения.
Добавляем гибридный кэш в .NET 9
1. Установим NuGet-пакет
2. Зарегистрируем сервис
Cвойства HybridCacheOptions позволяют настраивать ограничения, применяемые ко всем записям кэша:
- MaximumPayloadBytes — максимальный размер записи кэша. Значение по умолчанию — 1 МБ.
- MaximumKeyLength — максимальная длина ключа. Значение по умолчанию — 1024 символа.
Попытки сохранить значения, превышающие эти размеры, записываются в лог, но значение не сохраняется в кэше.
- DefaultEntryOptions – настраивает время хранения элементов в кэше: Expiration – общее время хранения элемента, LocalCacheExpiration – время хранения элемента в кэше L1.
3. Настроим распределённый кэш (не обязательно)
Например, используем Redis:
Это делать не обязательно, т.к. HybridCache может работать и как кэш только в памяти.
Окончание следует…
Источник: https://thecodeman.net/posts/hybrid-cache-in-aspnet-core
Гибридный Кэш в ASP.NET Core 9. Начало
В .NET 9 представлен гибридный кэш (HybridCache), механизм кэширования, который сочетает скорость кэширования в памяти с масштабируемостью распределённого кэширования. Я уже писал о новинке тут. Теперь рассмотрим его подробнее.
Что это?
HybridCache — это абстрактный класс с реализацией по умолчанию, который обрабатывает большинство аспектов сохранения в кэш и извлечения из кэша. HybridCache также включает в себя некоторые важные функции, относящиеся к процессу кэширования:
- Двухуровневое кэширование (L1/L2)
Использует быстрый кэш в памяти (L1) для быстрого извлечения данных и распределённый кэш (L2) для согласованности данных в нескольких экземплярах приложения.
- Защита от паники в кэше
Предотвращает панику в кэше при нескольких параллельных запросах, гарантируя, что только один запрос извлекает данные, а другие ждут, что снижает ненужную нагрузку.
- Инвалидация на основе тегов
Позволяет группировать записи кэша тегами, что обеспечивает эффективное удаление связанных элементов кэша одновременно.
- Настраиваемая сериализация
Позволяет настраивать методы сериализации данных, поддерживая различные форматы, такие как JSON, Protobuf или XML, в соответствии с потребностями конкретного приложения.
Добавляем гибридный кэш в .NET 9
1. Установим NuGet-пакет
dotnet add package Microsoft.Extensions.Caching.Hybrid
2. Зарегистрируем сервис
builder.Services.AddHybridCache(opts =>
{
opts.MaximumPayloadBytes = 1024 * 1024; // 1 MB
opts.MaximumKeyLength = 512;
opts.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(30),
LocalCacheExpiration = TimeSpan.FromMinutes(30)
};
});
Cвойства HybridCacheOptions позволяют настраивать ограничения, применяемые ко всем записям кэша:
- MaximumPayloadBytes — максимальный размер записи кэша. Значение по умолчанию — 1 МБ.
- MaximumKeyLength — максимальная длина ключа. Значение по умолчанию — 1024 символа.
Попытки сохранить значения, превышающие эти размеры, записываются в лог, но значение не сохраняется в кэше.
- DefaultEntryOptions – настраивает время хранения элементов в кэше: Expiration – общее время хранения элемента, LocalCacheExpiration – время хранения элемента в кэше L1.
3. Настроим распределённый кэш (не обязательно)
Например, используем Redis:
builder.Services
.AddStackExchangeRedisCache(opts =>
{
opts.Configuration = "connectionString";
});
Это делать не обязательно, т.к. HybridCache может работать и как кэш только в памяти.
Окончание следует…
Источник: https://thecodeman.net/posts/hybrid-cache-in-aspnet-core
👍22
День 2149. #ЗаметкиНаПолях
Гибридный Кэш в ASP.NET Core 9. Окончание
Начало
Используем HybridCache
Допустим, у нас есть API, предоставляющий информацию о продукте. Часто используемые данные будут кэшироваться для повышения производительности:
1. L1 (в памяти) - для обслуживания быстрых чтений из локального кэша.
2. L2 (Redis) - для обеспечения согласованности данных в распределённых экземплярах.
Как это работает
1. Метод проверяет, существует ли key в HybridCache. Если да, возвращаются кэшированные данные (из L1, если доступно; в противном случае из L2).
2. Если данные отсутствуют в кэшах L1 и L2, вызывается делегат (FetchFromDB) для извлечения данных из базы данных.
3. После извлечения данных они сохраняются в кэшах L1 и L2 с указанными политиками истечения срока действия (HybridCacheEntryOptions - их можно задать для всех элементов при регистрации кэша, либо в перегруженной версии GetOrCreateAsync).
4. Метод возвращает список продуктов либо из кэша, либо после извлечения из базы данных.
Удаление данных из кэша
Можно использовать метод RemoveAsync:
Запись удаляется из кэшей L1 и L2. Если ключ не существует, метод не делает ничего.
Добавление элементов с тегами
При сохранении записей в кэше вы можете назначать теги для их логической группировки. Для этого используется перегрузка GetOrCreateAsync:
Здесь мы задаём другие параметры истечения срока действия, а также тег для элементов.
Чтобы удалить все элементы, имеющие определённый тэг, используется метод RemoveByTagAsync:
Источник: https://thecodeman.net/posts/hybrid-cache-in-aspnet-core
Гибридный Кэш в ASP.NET Core 9. Окончание
Начало
Используем HybridCache
Допустим, у нас есть API, предоставляющий информацию о продукте. Часто используемые данные будут кэшироваться для повышения производительности:
1. L1 (в памяти) - для обслуживания быстрых чтений из локального кэша.
2. L2 (Redis) - для обеспечения согласованности данных в распределённых экземплярах.
public class ProductService(
HybridCache cache)
{
public async Task<List<Product>>
GetProductsByCategoryAsync(
string category,
CancellationToken ct = default)
{
var key = $"products:category:{category}";
return await cache.GetOrCreateAsync(
key,
async token =>
await FetchFromDB(category, token),
ct
);
}
}
Как это работает
1. Метод проверяет, существует ли key в HybridCache. Если да, возвращаются кэшированные данные (из L1, если доступно; в противном случае из L2).
2. Если данные отсутствуют в кэшах L1 и L2, вызывается делегат (FetchFromDB) для извлечения данных из базы данных.
3. После извлечения данных они сохраняются в кэшах L1 и L2 с указанными политиками истечения срока действия (HybridCacheEntryOptions - их можно задать для всех элементов при регистрации кэша, либо в перегруженной версии GetOrCreateAsync).
4. Метод возвращает список продуктов либо из кэша, либо после извлечения из базы данных.
Удаление данных из кэша
Можно использовать метод RemoveAsync:
public async Task RemoveFromCache(
string category,
CancellationToken ct = default)
{
var key = $"products:category:{category}";
await cache.RemoveAsync(key, ct);
}
Запись удаляется из кэшей L1 и L2. Если ключ не существует, метод не делает ничего.
Добавление элементов с тегами
При сохранении записей в кэше вы можете назначать теги для их логической группировки. Для этого используется перегрузка GetOrCreateAsync:
// …
return await cache.GetOrCreateAsync(
key,
async token =>
await FetchFromDB(category, token),
new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(10),
LocalCacheExpiration = TimeSpan.FromMinutes(5),
Tags = new List<string> { $"category:{category}" }
},
ct
);
Здесь мы задаём другие параметры истечения срока действия, а также тег для элементов.
Чтобы удалить все элементы, имеющие определённый тэг, используется метод RemoveByTagAsync:
public async Task InvalidateByTag(
string tag,
CancellationToken ct = default
)
{
await _cache.RemoveByTagAsync(tag, ct);
}
Источник: https://thecodeman.net/posts/hybrid-cache-in-aspnet-core
👍13
День 2150. #ЧтоНовенького #NET10
Заглядываем в .NET 10
9я версия .NET вышла всего месяц назад, а уже появляются предложения того, что может появиться через год в юбилейной 10й версии.
1. «Левое объединение» в LINQ
В LINQ есть оператор Join, который чаще всего в SQL преобразуется во что-то вроде INNER JOIN. В LINQ нет встроенного оператора для LEFT JOIN, но вы можете достичь того же результата, используя комбинацию GroupJoin, SelectMany и DefaultIfEmpty:
Имейте в виду, если вы хотите объединить несколько столбцов, они должны иметь одинаковые имена и типы данных.
Теперь появилось предложение добавить оператор LeftJoin в .NET 10. Тогда запрос выше будет выглядеть так:
На данный момент неясно, будет ли в синтаксисе запроса новое ключевое слово, представляющее оператор LeftJoin. Но вполне вероятно, что оно будет добавлено в синтаксис методов.
2. Неблокирующий старт фоновых сервисов
Небольшое изменение в способе запуска BackgroundService в .NET 10. Вы могли заметить, что запуск фонового сервиса блокирует запуск приложения до тех пор, пока не будет запущен сервис. Это происходит из-за того, что метод StartAsync вызывается синхронно в реализации IHostedService. Вы можете использовать следующий трюк, чтобы обойти это:
Или обернуть всё в Task.Run. Но это не очень хорошо и нелегко обнаружить. В .NET 10 это поведение будет заменено на реально асинхронное, и приложение не будет блокироваться при запуске.
3. Новый компаратор строк
Представьте, что вы хотите отсортировать следующие две строки: Windows 10 и Windows 7. Если рассматривать их исключительно как строки, Windows 10 будет идти перед Windows 7, потому что символ 1 идет перед 7. Но есть контексты, в которых вам нужно рассматривать некоторую часть строки как число и сортировать строки соответствующим образом. Вот тут и пригодится новый StringComparer. Он позволит вам сортировать строки как числа, поэтому Windows 10 будет идти после Windows 7.
Другой пример, упомянутый в предложении, - сортировка IP адресов.
Источники:
- https://steven-giesel.com/blogPost/82ebfd51-23c0-44b7-9602-628d1aba5f3c/linq-might-get-a-left-join-operator-in-net-10
- https://steven-giesel.com/blogPost/3a8c29a3-750a-40f0-aa43-c236b855813e/some-news-about-net-10-backgroundservices-and-new-string-comparer
Заглядываем в .NET 10
9я версия .NET вышла всего месяц назад, а уже появляются предложения того, что может появиться через год в юбилейной 10й версии.
1. «Левое объединение» в LINQ
В LINQ есть оператор Join, который чаще всего в SQL преобразуется во что-то вроде INNER JOIN. В LINQ нет встроенного оператора для LEFT JOIN, но вы можете достичь того же результата, используя комбинацию GroupJoin, SelectMany и DefaultIfEmpty:
var query =
_dbctx.Table1
.GroupJoin(
_dbctx.Table2,
t1 => t1.T2Id,
t2 => t2.Id,
(t1, t2) => new { t1, t2 }
)
.SelectMany(
t => t.t2.DefaultIfEmpty(),
(t, t2) => new { t1 = @t.t1, t2 }
);
Имейте в виду, если вы хотите объединить несколько столбцов, они должны иметь одинаковые имена и типы данных.
Теперь появилось предложение добавить оператор LeftJoin в .NET 10. Тогда запрос выше будет выглядеть так:
var query = _dbctx.Table1
.LeftJoin(
_dbctx.Table2,
t1 => t1.T2Id,
t2 => t2.Id,
(t1, t2) => new { t1, t2 }
);
На данный момент неясно, будет ли в синтаксисе запроса новое ключевое слово, представляющее оператор LeftJoin. Но вполне вероятно, что оно будет добавлено в синтаксис методов.
2. Неблокирующий старт фоновых сервисов
Небольшое изменение в способе запуска BackgroundService в .NET 10. Вы могли заметить, что запуск фонового сервиса блокирует запуск приложения до тех пор, пока не будет запущен сервис. Это происходит из-за того, что метод StartAsync вызывается синхронно в реализации IHostedService. Вы можете использовать следующий трюк, чтобы обойти это:
public class MyService : BackgroundService
{
private IHostApplicationLifetime _lt;
public MyService(IHostApplicationLifetime lt)
{
_lt = lt;
}
protected override async Task
ExecuteAsync(CancellationToken ct)
{
await Task.Yield();
// Вся работа здесь
}
}
Или обернуть всё в Task.Run. Но это не очень хорошо и нелегко обнаружить. В .NET 10 это поведение будет заменено на реально асинхронное, и приложение не будет блокироваться при запуске.
3. Новый компаратор строк
Представьте, что вы хотите отсортировать следующие две строки: Windows 10 и Windows 7. Если рассматривать их исключительно как строки, Windows 10 будет идти перед Windows 7, потому что символ 1 идет перед 7. Но есть контексты, в которых вам нужно рассматривать некоторую часть строки как число и сортировать строки соответствующим образом. Вот тут и пригодится новый StringComparer. Он позволит вам сортировать строки как числа, поэтому Windows 10 будет идти после Windows 7.
var list = new List<string> { "Windows 10", "Windows 7" };
list.Sort(StringComparer.NumericOrdering);
Другой пример, упомянутый в предложении, - сортировка IP адресов.
Источники:
- https://steven-giesel.com/blogPost/82ebfd51-23c0-44b7-9602-628d1aba5f3c/linq-might-get-a-left-join-operator-in-net-10
- https://steven-giesel.com/blogPost/3a8c29a3-750a-40f0-aa43-c236b855813e/some-news-about-net-10-backgroundservices-and-new-string-comparer
👍29
День 2151. #ЗаметкиНаПолях
Публичные API в Модульных Монолитах. Начало
В каждой статье о модульных монолитах говорится, что нужно использовать публичные API между модулями. Но редко говорится, почему эти API существуют или как их правильно проектировать.
Модульный монолит организует приложение в независимые модули с чёткими границами. Границы модулей логичны и группируют связанные бизнес-возможности. Публичные API между ними — это не просто чистый код, это контроль хаоса. Они представляют собой преднамеренные точки связанности. Публичные API не устраняют связанность, они делают её явной и контролируемой.
Когда модулю A что-то нужно от модуля B, у вас есть три варианта:
1) Позволить модулю A читать напрямую из базы данных модуля B,
2) Позволить модулю A получать доступ к внутренним сервисам модуля B,
3) Создать публичный API, который явно определяет, что может делать модуль A.
Первые два варианта приводят к хаосу. Вся система может стать неподдерживаемой, если каждый модуль свободно обращается к данным и сервисам других модулей.
Публичные API служат следующим критически важным целям:
1) Определение контракта: они явно указывают, что могут и не могут делать другие модули,
2) Управление зависимостями: они заставляют вас думать о зависимостях модулей,
3) Управление изменениями: они предоставляют стабильный интерфейс, допуская при этом внутренние изменения.
Вот практический пример. Представьте, что у вас есть модули Orders и Shipping.
Этого мы хотели бы избежать:
А вот, чего бы мы хотели добиться вместо этого:
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/internal-vs-public-apis-in-modular-monoliths
Публичные API в Модульных Монолитах. Начало
В каждой статье о модульных монолитах говорится, что нужно использовать публичные API между модулями. Но редко говорится, почему эти API существуют или как их правильно проектировать.
Модульный монолит организует приложение в независимые модули с чёткими границами. Границы модулей логичны и группируют связанные бизнес-возможности. Публичные API между ними — это не просто чистый код, это контроль хаоса. Они представляют собой преднамеренные точки связанности. Публичные API не устраняют связанность, они делают её явной и контролируемой.
Когда модулю A что-то нужно от модуля B, у вас есть три варианта:
1) Позволить модулю A читать напрямую из базы данных модуля B,
2) Позволить модулю A получать доступ к внутренним сервисам модуля B,
3) Создать публичный API, который явно определяет, что может делать модуль A.
Первые два варианта приводят к хаосу. Вся система может стать неподдерживаемой, если каждый модуль свободно обращается к данным и сервисам других модулей.
Публичные API служат следующим критически важным целям:
1) Определение контракта: они явно указывают, что могут и не могут делать другие модули,
2) Управление зависимостями: они заставляют вас думать о зависимостях модулей,
3) Управление изменениями: они предоставляют стабильный интерфейс, допуская при этом внутренние изменения.
Вот практический пример. Представьте, что у вас есть модули Orders и Shipping.
Этого мы хотели бы избежать:
public class ShippingService
{
// Прямой доступ к БД
private OrdersDbContext _ordersDb;
public async Task ShipOrder(string id)
{
// Напрямую обращаемся к БД другого модуля
var order = await _ordersDb.Orders
.Include(o => o.Lines)
.FirstOrDefaultAsync(o => o.Id == id);
// Что, если модуль Orders изменит схему данных?
}
}
А вот, чего бы мы хотели добиться вместо этого:
public class ShippingService
{
// Доступ к публичному API
private IOrdersModule _orders;
public async Task ShipOrder(string id)
{
// Используем публичный API
var order = await
_orders.GetShippingOrder(id);
// Модуль Orders может изменять внутреннюю
// структуру, сохраняя внешний контракт
}
}
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/internal-vs-public-apis-in-modular-monoliths
👍16👎1
День 2152. #ЗаметкиНаПолях
Внутренние и Публичные API в Модульных Монолитах. Окончание
Начало
Раскрытие информации
Самая сложная часть проектирования публичных API — решить, что раскрывать:
1) Начните с того, что нет ничего публичного,
2) Открывайте только то, что другим модулям действительно нужно,
3) Проектируйте API вокруг вариантов использования, а не данных.
Вот как это выглядит на практике:
Защита данных модуля
Также нужно защитить данные модуля. Вот несколько советов.
1. Отдельные схемы: каждый модуль получает свою схему БД.
Также мы блокируем доступ пользователя к изменению схемы, разрешив только чтение и запись данных.
2. Различные строки подключения: каждый модуль получает своего пользователя БД с соответствующей строкой подключения.
См. также «Использование Нескольких Контекстов EF Core»
3. Модели для чтения: специальная модель только для чтения для использования из других модулей.
Итого
Открытые API в модульных монолитах предназначены не для предотвращения связанности, а для её контроля. Каждый открытый API — это контракт, который гласит: «Да, эти модули связаны, и именно так они зависят друг от друга».
Цель не в том, чтобы устранить зависимости между модулями. Цель в том, чтобы сделать их явными, контролируемыми и поддерживаемыми.
Источник: https://www.milanjovanovic.tech/blog/internal-vs-public-apis-in-modular-monoliths
Внутренние и Публичные API в Модульных Монолитах. Окончание
Начало
Раскрытие информации
Самая сложная часть проектирования публичных API — решить, что раскрывать:
1) Начните с того, что нет ничего публичного,
2) Открывайте только то, что другим модулям действительно нужно,
3) Проектируйте API вокруг вариантов использования, а не данных.
Вот как это выглядит на практике:
public interface IOrdersModule
{
// Не раскрываем CRUD-операции
// Раскрываем варианты использования
Task<ShippingOrder> GetShippingOrder(string id);
Task<PaymentOrder> GetPaymentOrder(string id);
Task<OrderSummary> GetOrderSummary(string id);
}
Защита данных модуля
Также нужно защитить данные модуля. Вот несколько советов.
1. Отдельные схемы: каждый модуль получает свою схему БД.
CREATE SCHEMA Orders;
CREATE SCHEMA Shipping;
-- Каждый модуль имеет доступ только к своей схеме
CREATE USER OrdersUser WITH DEFAULT_SCHEMA = Orders;
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA Orders TO OrdersUser;
-- … Аналогично для схемы Shipping
Также мы блокируем доступ пользователя к изменению схемы, разрешив только чтение и запись данных.
2. Различные строки подключения: каждый модуль получает своего пользователя БД с соответствующей строкой подключения.
builder.Services.AddDbContext<OrdersDbContext>(
opts =>
opts.UseSqlServer(
builder.Configuration
.GetConnectionString("OrdersConnection")));
builder.Services.AddDbContext<ShippingDbContext>(
opts =>
opts.UseSqlServer(
builder.Configuration
.GetConnectionString("ShippingConnection")));
См. также «Использование Нескольких Контекстов EF Core»
3. Модели для чтения: специальная модель только для чтения для использования из других модулей.
internal class Order
{
// Полная внутренняя модель
}
public class ShippingOrder
{
// Публичное DTO для модуля Shipping
public string Id { get; init; }
public Address ShippingAddress { get; init; }
public List<ShippingItem> Items { get; init; }
}
Итого
Открытые API в модульных монолитах предназначены не для предотвращения связанности, а для её контроля. Каждый открытый API — это контракт, который гласит: «Да, эти модули связаны, и именно так они зависят друг от друга».
Цель не в том, чтобы устранить зависимости между модулями. Цель в том, чтобы сделать их явными, контролируемыми и поддерживаемыми.
Источник: https://www.milanjovanovic.tech/blog/internal-vs-public-apis-in-modular-monoliths
👍15
День 2153. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 36. Как бы сильно на вас ни давили, не берите на себя обязательства, которые не сможете выполнить
Люди редко со всей серьёзностью относятся к обязательствам, которые им пришлось взять на себя под принуждением. Они также не берут на себя серьёзных обязательств, которые кто-то другой берет на себя от их имени без консультаций и переговоров. Если сотруднику навязать невыполнимое обязательство, это вызовет у него стресс, а не приведёт к чуду. Более того, люди могут даже снизить свои старания, зная, что всё равно не смогут достичь поставленной цели. Зачем убиваться, если дело и так обречено на провал?
Обязательство — это обещание выполнить некое действие или часть работы на определённом уровне за определённое время. Управление обязательствами — это компонент управления проектами. Идея не брать на себя обязательств, которые невозможно выполнить, — вопрос личной этики. Она также отражает правильное управление проектами и людьми.
Обязательства накапливаются в цепочках зависимостей, как показано на рисунке. Получивший обещание зависит от тех, кто взял на себя обязательства по его выполнению. Если все честно договариваются о достижимых обязательствах, то смогут с уверенностью положиться друг на друга. В противном случае цепочка обязательств рушится как карточный домик. Любые обязательства, невыполненные на нижних уровнях, рушат обязательства на верхних.
Обещайте меньше, а делайте больше. Возможно, из-за этого вы будете выглядеть чрезмерно осторожным, но это же делает вас надёжным. Один из способов не выбиться из графика — заложить в свои обязательства резерв времени на случай непредвиденных обстоятельств, чтобы учесть неопределённость оценок, изменения в требованиях и другие неожиданности. Наличие такого резерва страхует вас, если что-то пойдёт не так, как планировалось. Но перед собой лично ставьте более трудные цели, чем обязательства, которые даёте другим. Прикладывайте все силы, чтобы достичь своей внутренней цели, осознавая, однако, что если не добьётесь её, то всё равно не нарушите данного внешнего обязательства. Чаще всего вы будете достигать цели раньше, чем обязались. Такой результат всем нравится.
В жизни случается всякое
Люди берут на себя обязательства из лучших побуждений. Потом что-то происходит, и всё меняется. Может появиться новое задание или новая возможность, на которые приходится отвлекаться, или объём работы может превышать предполагаемый. Человек может просто потерять интерес к первоначальному обязательству и позволить ему отойти на второй план, надеясь, что никто не заметит. Но это замечают.
Поняв, что по какой-то причине вы не можете выполнить взятое на себя обязательство, как можно скорее сообщите об этом тем, кого это затрагивает, чтобы они могли скорректировать свои планы. Когда кто-то даёт мне обещание, я рассчитываю, что он его выполнит. Если мои первоначальные предположения не оправдались или что-то изменилось, то я предлагаю поговорить. Возможно, мы сможем достичь взаимоприемлемого соглашения. Но я также понимаю, что другой человек может не согласиться по разным причинам.
Если я говорю, что собираюсь что-то сделать, то либо делаю, либо объясняю, почему не могу или не успеваю это сделать, и приношу извинения. Этого же ожидаю от других. Все мы знаем, что ситуации и приоритеты могут меняться. Но, взяв на себя обязательство, человек должен сообщить, если не может выполнить его.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
Уроки 50 Лет Разработки ПО
Урок 36. Как бы сильно на вас ни давили, не берите на себя обязательства, которые не сможете выполнить
Люди редко со всей серьёзностью относятся к обязательствам, которые им пришлось взять на себя под принуждением. Они также не берут на себя серьёзных обязательств, которые кто-то другой берет на себя от их имени без консультаций и переговоров. Если сотруднику навязать невыполнимое обязательство, это вызовет у него стресс, а не приведёт к чуду. Более того, люди могут даже снизить свои старания, зная, что всё равно не смогут достичь поставленной цели. Зачем убиваться, если дело и так обречено на провал?
Обязательство — это обещание выполнить некое действие или часть работы на определённом уровне за определённое время. Управление обязательствами — это компонент управления проектами. Идея не брать на себя обязательств, которые невозможно выполнить, — вопрос личной этики. Она также отражает правильное управление проектами и людьми.
Обязательства накапливаются в цепочках зависимостей, как показано на рисунке. Получивший обещание зависит от тех, кто взял на себя обязательства по его выполнению. Если все честно договариваются о достижимых обязательствах, то смогут с уверенностью положиться друг на друга. В противном случае цепочка обязательств рушится как карточный домик. Любые обязательства, невыполненные на нижних уровнях, рушат обязательства на верхних.
Обещайте меньше, а делайте больше. Возможно, из-за этого вы будете выглядеть чрезмерно осторожным, но это же делает вас надёжным. Один из способов не выбиться из графика — заложить в свои обязательства резерв времени на случай непредвиденных обстоятельств, чтобы учесть неопределённость оценок, изменения в требованиях и другие неожиданности. Наличие такого резерва страхует вас, если что-то пойдёт не так, как планировалось. Но перед собой лично ставьте более трудные цели, чем обязательства, которые даёте другим. Прикладывайте все силы, чтобы достичь своей внутренней цели, осознавая, однако, что если не добьётесь её, то всё равно не нарушите данного внешнего обязательства. Чаще всего вы будете достигать цели раньше, чем обязались. Такой результат всем нравится.
В жизни случается всякое
Люди берут на себя обязательства из лучших побуждений. Потом что-то происходит, и всё меняется. Может появиться новое задание или новая возможность, на которые приходится отвлекаться, или объём работы может превышать предполагаемый. Человек может просто потерять интерес к первоначальному обязательству и позволить ему отойти на второй план, надеясь, что никто не заметит. Но это замечают.
Поняв, что по какой-то причине вы не можете выполнить взятое на себя обязательство, как можно скорее сообщите об этом тем, кого это затрагивает, чтобы они могли скорректировать свои планы. Когда кто-то даёт мне обещание, я рассчитываю, что он его выполнит. Если мои первоначальные предположения не оправдались или что-то изменилось, то я предлагаю поговорить. Возможно, мы сможем достичь взаимоприемлемого соглашения. Но я также понимаю, что другой человек может не согласиться по разным причинам.
Если я говорю, что собираюсь что-то сделать, то либо делаю, либо объясняю, почему не могу или не успеваю это сделать, и приношу извинения. Этого же ожидаю от других. Все мы знаем, что ситуации и приоритеты могут меняться. Но, взяв на себя обязательство, человек должен сообщить, если не может выполнить его.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
👍12
День 2154. #ЧтоНовенького
Бесплатный GitHub Copilot в Visual Studio
Если вы ещё не слышали, GitHub анонсировал бесплатный план Copilot! И вы уже можете начать использовать Copilot прямо сейчас в Visual Studio и VS Code.
Copilot предлагает инструменты на базе ИИ, такие как умная отладка, сообщения о коммитах, сгенерированные ИИ, размещение точек останова с помощью ИИ, ИИ-завершения кода, чат и многое другое. Разработчики увидели увеличение продуктивности до 25% при использовании Copilot.
Чтобы попробовать, войдите в свой аккаунт на GitHub, и перейдите в настройки Copilot.
Бесплатная версия включает:
- 2000 интеллектуальных автодополнений кода в месяц: контекстно-зависимые предложения кода, которые черпают контекст из ваших проектов GitHub и рабочего пространства.
- 50 сообщений в чате Copilot в месяц: попросите Copilot помочь вам понять код, выполнить рефакторинг, написать тесты для класса или отладить проблему.
- Выбор модели ИИ Claude 3.5 Sonnet или OpenAI GPT-4o.
- Внесение изменений в несколько файлов с помощью Copilot Edits.
- Поддержка экосистемы Copilot Extensions: доступ к сторонним агентам, разработанным для таких задач, как запросы к Stack Overflow или поиск с помощью Perplexity.
На данный момент вы не получите уведомления, когда достигнете лимитов использования в месяц. Но это обещают исправить в новых версиях Visual Studio в январе, поэтому следите за обновлениями.
Источник: https://devblogs.microsoft.com/visualstudio/github-copilot-free-is-here-in-visual-studio/
Бесплатный GitHub Copilot в Visual Studio
Если вы ещё не слышали, GitHub анонсировал бесплатный план Copilot! И вы уже можете начать использовать Copilot прямо сейчас в Visual Studio и VS Code.
Copilot предлагает инструменты на базе ИИ, такие как умная отладка, сообщения о коммитах, сгенерированные ИИ, размещение точек останова с помощью ИИ, ИИ-завершения кода, чат и многое другое. Разработчики увидели увеличение продуктивности до 25% при использовании Copilot.
Чтобы попробовать, войдите в свой аккаунт на GitHub, и перейдите в настройки Copilot.
Бесплатная версия включает:
- 2000 интеллектуальных автодополнений кода в месяц: контекстно-зависимые предложения кода, которые черпают контекст из ваших проектов GitHub и рабочего пространства.
- 50 сообщений в чате Copilot в месяц: попросите Copilot помочь вам понять код, выполнить рефакторинг, написать тесты для класса или отладить проблему.
- Выбор модели ИИ Claude 3.5 Sonnet или OpenAI GPT-4o.
- Внесение изменений в несколько файлов с помощью Copilot Edits.
- Поддержка экосистемы Copilot Extensions: доступ к сторонним агентам, разработанным для таких задач, как запросы к Stack Overflow или поиск с помощью Perplexity.
На данный момент вы не получите уведомления, когда достигнете лимитов использования в месяц. Но это обещают исправить в новых версиях Visual Studio в январе, поэтому следите за обновлениями.
Источник: https://devblogs.microsoft.com/visualstudio/github-copilot-free-is-here-in-visual-studio/
👍9
День 2155. #ЗаметкиНаПолях
3 Основных Способа Управления Транзакциями в EF Core. Начало
Транзакции помогают безопасно обновлять связанные данные, не оставляя состояние БД несогласованным. Рассмотрим, как EF Core предоставляет механизм упаковки операций с БД в транзакции.
Транзакция — это набор операций с БД, рассматриваемых как единица работы. Если одна из операций завершается неудачей, вся транзакция завершается неудачей, и все предыдущие успешные операции откатываются, чтобы сохранить согласованность базы.
Вот основные способы работы с транзакциями в EF Core:
1. Автоматически. Метод SaveChangesAsync() класса DbContext фиксирует все изменения в транзакции.
2. Вручную. Использование команд begin, commit и rollback для транзакций.
3. Стратегия выполнения транзакций. Может иметь несколько вызовов SaveChangesAsync, но они не фиксируются, пока транзакция не фиксирует их с помощью метода transaction.CommitAsync().
1. Автоматические транзакции
Предположим, что нам нужно добавить несколько зданий.
Каждый вызов SaveChangesAsync автоматически запускает новую транзакцию, если она ещё не запущена. Т.е. все изменения, внесённые в контекст до этого момента, сохраняются в БД как единое целое, что обеспечивает согласованность данных.
Плюсы
- Самый простой способ, не требуется никаких дополнительных методов.
- Выполняет транзакции асинхронно, улучшая отзывчивость приложения.
Минусы
- Имеет ограниченную область действия транзакции, поскольку обрабатывает каждую операцию как транзакцию.
- Нет контроля над транзакциями.
- Не может применяться для взаимозависимых операций.
2. Ручные транзакции
Здесь каждый вызов SaveChangesAsync рассматривается как завершение одной операции. Несколько вызовов заключены в транзакцию, которая начинается с Database.BeginTransaction. После успешного выполнения всех операций метод transaction.Commit() фиксирует все изменения как одну транзакцию.
Плюсы
- Полный контроль над транзакцией. Можно вручную фиксировать и откатывать транзакцию.
- Лучше обработка ошибок с перехватом исключений и свободой обрабатывать различные ошибки по-разному.
- Подходит для сложных сценариев, где необходимо выполнять разные операции с БД.
Минусы
- Усложняет код из-за дополнительного кода обработки транзакций.
Окончание следует…
Источник: https://blog.elmah.io/3-essential-techniques-for-managing-transactions-in-ef-core/
3 Основных Способа Управления Транзакциями в EF Core. Начало
Транзакции помогают безопасно обновлять связанные данные, не оставляя состояние БД несогласованным. Рассмотрим, как EF Core предоставляет механизм упаковки операций с БД в транзакции.
Транзакция — это набор операций с БД, рассматриваемых как единица работы. Если одна из операций завершается неудачей, вся транзакция завершается неудачей, и все предыдущие успешные операции откатываются, чтобы сохранить согласованность базы.
Вот основные способы работы с транзакциями в EF Core:
1. Автоматически. Метод SaveChangesAsync() класса DbContext фиксирует все изменения в транзакции.
2. Вручную. Использование команд begin, commit и rollback для транзакций.
3. Стратегия выполнения транзакций. Может иметь несколько вызовов SaveChangesAsync, но они не фиксируются, пока транзакция не фиксирует их с помощью метода transaction.CommitAsync().
1. Автоматические транзакции
Предположим, что нам нужно добавить несколько зданий.
csharp
public record Building(int Id, string Name, string Address);
using var ctx = new ApplicationDbContext();
var bld1 = new
Building(1, "First", "1st Street, 42");
ctx.Buildings.Add(bld1);
// Транзакция используется автоматически
ctx.SaveChangesAsync();
var bld2 = new
Building(2, "Second", "2nd Street, 69");
ctx.Buildings.Add(bld2);
// Транзакция используется автоматически
ctx.SaveChangesAsync();
Каждый вызов SaveChangesAsync автоматически запускает новую транзакцию, если она ещё не запущена. Т.е. все изменения, внесённые в контекст до этого момента, сохраняются в БД как единое целое, что обеспечивает согласованность данных.
Плюсы
- Самый простой способ, не требуется никаких дополнительных методов.
- Выполняет транзакции асинхронно, улучшая отзывчивость приложения.
Минусы
- Имеет ограниченную область действия транзакции, поскольку обрабатывает каждую операцию как транзакцию.
- Нет контроля над транзакциями.
- Не может применяться для взаимозависимых операций.
2. Ручные транзакции
Здесь каждый вызов SaveChangesAsync рассматривается как завершение одной операции. Несколько вызовов заключены в транзакцию, которая начинается с Database.BeginTransaction. После успешного выполнения всех операций метод transaction.Commit() фиксирует все изменения как одну транзакцию.
public class BuildingRepo: IBuildingRepo
{
private AppDbContext _context;
public BuildingRepo(AppDbContext ctx)
{
_ctx = ctx;
}
public async Task<bool> CreateAsync(
List<Building> buildings)
{
using (var trans = ctx.Database.BeginTransaction())
{
try
{
foreach (var bld in buildings)
{
_ctx.Buildings.Add(bld);
_ctx.SaveChangesAsync();
}
// Если всё ОК, фиксируем транзакцию
trans.Commit();
return true;
}
catch (Exception ex)
{
// В случае ошибки, откатываем
trans.Rollback();
// Обработка исключения…
return false;
}
}
}
}
Плюсы
- Полный контроль над транзакцией. Можно вручную фиксировать и откатывать транзакцию.
- Лучше обработка ошибок с перехватом исключений и свободой обрабатывать различные ошибки по-разному.
- Подходит для сложных сценариев, где необходимо выполнять разные операции с БД.
Минусы
- Усложняет код из-за дополнительного кода обработки транзакций.
Окончание следует…
Источник: https://blog.elmah.io/3-essential-techniques-for-managing-transactions-in-ef-core/
👍16
День 2156. #ЗаметкиНаПолях
3 Основных Способа Управления Транзакциями в EF Core. Окончание
Начало
3. Стратегия выполнения транзакций
В этом способе создаётся стратегия выполнения, в которой управляются транзакции. Она продолжает пытаться выполнить операции с БД указанное количество раз, если транзакция не удаётся из-за временной ошибки. Это итеративное поведение гарантирует, что незначительные проблемы не повлияют на фактические операции.
Добавим к зданиям различные помещения в зданиях:
Создадим DTO:
И, наконец, сценарий обработки:
Весь блок работает как транзакция. При временном сбое стратегия выполнения повторяет всю операцию в ExecuteAsync.
Плюсы
- Стратегия может обрабатывать временные сбои, что повышает отзывчивость и надёжность приложения.
- Идеально подходит для сложных сценариев и взаимозависимых операций.
- Предлагает настройку транзакции вместе с устойчивостью к сбоям сети.
Минусы
- Ещё больше усложняет код. Множество блоков и областей влияют на читаемость кода.
- Транзакция на основе стратегии может снизить производительность приложения, если она неправильно настроена.
Источник: https://blog.elmah.io/3-essential-techniques-for-managing-transactions-in-ef-core/
3 Основных Способа Управления Транзакциями в EF Core. Окончание
Начало
3. Стратегия выполнения транзакций
В этом способе создаётся стратегия выполнения, в которой управляются транзакции. Она продолжает пытаться выполнить операции с БД указанное количество раз, если транзакция не удаётся из-за временной ошибки. Это итеративное поведение гарантирует, что незначительные проблемы не повлияют на фактические операции.
Добавим к зданиям различные помещения в зданиях:
public class Unit
{
public int Id { get; set; }
public string Number { get; set; }
// Office, Apartment, Storage, и т.п.
public UnitType Type { get; set; }
public int Floor { get; set; }
public int BuildingId { get; set; }
public Building Building { get; set; }
}
Создадим DTO:
public record UnitDto(
string Number, UnitType Type, int Floor);
public class BuildingDto
{
public string Name { get; set; }
public string Address { get; set; }
public List<UnitDto> Units { get; set; }
= new List<UnitDto>();
}
И, наконец, сценарий обработки:
public class BuildingRepo: IBuildingRepo
{
private AppDbContext _ctx;
public BuildingRepo(AppDbContext ctx)
{
_ctx = ctx;
}
public async Task<bool> CreateAsync(BuildingDto input)
{
// Создаём стратегию
var strategy = _ctx.Database
.CreateExecutionStrategy();
return await strategy.ExecuteAsync(async () =>
{
// Запускаем транзакцию
using (var trans =
await _ctx.Database.BeginTransactionAsync())
{
try
{
var bld = new Building()
{
Name = input.Name,
Address = input.Address
};
// Сохраняем Building
_ctx.Buildings.Add(bld);
await _ctx.SaveChangesAsync();
foreach (var unit in input.Units)
{
_ctx.Add(new Unit()
{
// Добавляем внешний ключ здания
BuildingId = bld.Id,
Number = unit.Number,
Type = unit.Type,
Floor = unit.Floor
});
}
await _ctx.SaveChangesAsync();
await trans.CommitAsync();
return true;
}
catch (Exception ex)
{
// Откатываем, транзакцию при ошибке
await trans.RollbackAsync();
// Выбрасываем исключение,
// чтобы стратегия его обработала
throw;
}
}
}
});
}
Весь блок работает как транзакция. При временном сбое стратегия выполнения повторяет всю операцию в ExecuteAsync.
Плюсы
- Стратегия может обрабатывать временные сбои, что повышает отзывчивость и надёжность приложения.
- Идеально подходит для сложных сценариев и взаимозависимых операций.
- Предлагает настройку транзакции вместе с устойчивостью к сбоям сети.
Минусы
- Ещё больше усложняет код. Множество блоков и областей влияют на читаемость кода.
- Транзакция на основе стратегии может снизить производительность приложения, если она неправильно настроена.
Источник: https://blog.elmah.io/3-essential-techniques-for-managing-transactions-in-ef-core/
👍13
День 2157. #ЧтоНовенького
Используем Testing.Platform в .NET 9
.NET 9.0 представляет новую платформу тестирования Testing.Platform. Сегодня рассмотрим, что это и как её использовать.
Testing.Platform, как предполагается, станет заменой VSTest в качестве основной платформы для запуска тестов. С появлением .NET Core VSTest был скорректирован только для того, чтобы «заставить его работать», но не получил надлежащего редизайна с нуля. Теперь это изменилось, и команды Microsoft перестраивают среду тестирования для достижения следующих целей в будущем:
- Переносимость. Тесты должны выполняться везде одинаково, будь то разные компьютеры, агенты CI или в облаке.
- Поддержка NativeAOT-компиляции.
- Производительность. В Microsoft утверждают, что видят 30% увеличение производительности только за счёт миграции на Testing.Platform.
- Безопасность. Особенно когда речь идет о внешних зависимостях, которые должны быть сведены к минимуму.
Testing.Platform — это консольное приложение. Основная идея – всё, что вы можете сделать с консольным приложением, вы можете сделать с выводом Testing.Platform: запускать, отлаживать, даже использовать HotReload и видеть вывод тестов во время его работы. В то же время сохраняется обратная совместимость, так что можно запускать dotnet test для выполнения тестов, даже если вы уже перешли на Testing.Platform.
Перенос тестов XUnit на Testing.Platform
Допустим, у вас есть тесты XUnit в приложении. Типичный файл проекта csproj для этого будет выглядеть примерно так:
Чтобы использовать Testing.Platform, изменим файл:
По сути, нужно:
- Обновить версию платформы на net9.0
- Добавить декларацию UseMicrosoftTestingPlatformRunner
- Использовать недавно вышедший XUnit v3
Теперь, если вы выполните
Тот же вывод вы увидите, выполнив
Переход для NUnit выглядит немного иначе. Можете посмотреть это видео, чтобы узнать подробности.
Также существует TUnit, который предположительно создан поверх Testing.Platform, что, возможно, сделает его основным тестовым фреймворком в будущем.
Visual Studio, и Rider уже поддерживают запуск тестов на Testing.Platform в своих последних версиях.
Источник: https://dateo-software.de/blog/testing-platform
Используем Testing.Platform в .NET 9
.NET 9.0 представляет новую платформу тестирования Testing.Platform. Сегодня рассмотрим, что это и как её использовать.
Testing.Platform, как предполагается, станет заменой VSTest в качестве основной платформы для запуска тестов. С появлением .NET Core VSTest был скорректирован только для того, чтобы «заставить его работать», но не получил надлежащего редизайна с нуля. Теперь это изменилось, и команды Microsoft перестраивают среду тестирования для достижения следующих целей в будущем:
- Переносимость. Тесты должны выполняться везде одинаково, будь то разные компьютеры, агенты CI или в облаке.
- Поддержка NativeAOT-компиляции.
- Производительность. В Microsoft утверждают, что видят 30% увеличение производительности только за счёт миграции на Testing.Platform.
- Безопасность. Особенно когда речь идет о внешних зависимостях, которые должны быть сведены к минимуму.
Testing.Platform — это консольное приложение. Основная идея – всё, что вы можете сделать с консольным приложением, вы можете сделать с выводом Testing.Platform: запускать, отлаживать, даже использовать HotReload и видеть вывод тестов во время его работы. В то же время сохраняется обратная совместимость, так что можно запускать dotnet test для выполнения тестов, даже если вы уже перешли на Testing.Platform.
Перенос тестов XUnit на Testing.Platform
Допустим, у вас есть тесты XUnit в приложении. Типичный файл проекта csproj для этого будет выглядеть примерно так:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
…
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
…
</ItemGroup>
<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>
</Project>
Чтобы использовать Testing.Platform, изменим файл:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
…
<IsTestProject>true</IsTestProject>
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
</PropertyGroup>
…
</Project>
По сути, нужно:
- Обновить версию платформы на net9.0
- Добавить декларацию UseMicrosoftTestingPlatformRunner
- Использовать недавно вышедший XUnit v3
Теперь, если вы выполните
dotnet run
в папке проекта, вы увидите что-то вроде следующего:xUnit.net v3 Microsoft.Testing.Platform Runner v1.0.0 (64-bit .NET 9.0.0)
Test run summary: Passed! - bin\Debug\net9.0\XUnit.Tests.dll (net9.0|x64)
total: 2
failed: 0
succeeded: 2
skipped: 0
duration: 276ms
Тот же вывод вы увидите, выполнив
dotnet test
, но это может занять больше времени. Вот и весь переход.Переход для NUnit выглядит немного иначе. Можете посмотреть это видео, чтобы узнать подробности.
Также существует TUnit, который предположительно создан поверх Testing.Platform, что, возможно, сделает его основным тестовым фреймворком в будущем.
Visual Studio, и Rider уже поддерживают запуск тестов на Testing.Platform в своих последних версиях.
Источник: https://dateo-software.de/blog/testing-platform
👍17
Practical debugging for dotnet developers eBook.pdf
34.2 MB
День 2158. #Книги
Практика Отладки для .NET-разработчиков
Даже с внедрением ИИ в процесс разработки программного обеспечения отладка остается важной частью нашей работы. Умение эффективно исследовать сложные проблемы и быстро находить решения — важный навык, которым нужно овладеть. Хорошая новость в том, что этому навыку можно научиться. Помочь вам в этом может книга «Practical Debugging for .NET Developers» («Практика Отладки для .NET-разработчиков») Майкла Шпильта, которая теперь доступна бесплатно!
В книге рассматриваются следующие темы:
- Расширенные методы отладки с Visual Studio
- .NET Core и .NET Framework на Windows, Linux и Mac
- Проблемы с производительностью
- Утечки памяти и проблемы с нехваткой памяти
- Низкая производительность ASP.NET и неудачные запросы
- Отладка стороннего кода
- Отладка производственного кода в облаке
- Сбои и зависания
Вот фрагмент из введения:
«Лучшие инженеры-программисты, которых я знаю, отлично справляются с отладкой. Они находят решения сложных проблем там, где никто другой не может. Они достигают этого, используя правильные инструменты, зная, что искать, и имея глубокое понимание как своей собственной области, так и экосистемы .NET. Более того, они проводят систематическое расследование, используя проверенные методологии отладки. Отладка — это не искусство, это то, чему можно научить, и эта книга делает именно это. Эта книга — о совершенствовании ваших навыков отладки, экономии вашего времени и повышении вашей производительности.»
Книга вышла в 2020м году, но большинство информации в ней до сих пор актуально. Неплохой подарок от Майкла на новогодние праздники.
Источник: https://bartwullems.blogspot.com/2024/12/free-ebook-practical-debugging-for-net.html
Практика Отладки для .NET-разработчиков
Даже с внедрением ИИ в процесс разработки программного обеспечения отладка остается важной частью нашей работы. Умение эффективно исследовать сложные проблемы и быстро находить решения — важный навык, которым нужно овладеть. Хорошая новость в том, что этому навыку можно научиться. Помочь вам в этом может книга «Practical Debugging for .NET Developers» («Практика Отладки для .NET-разработчиков») Майкла Шпильта, которая теперь доступна бесплатно!
В книге рассматриваются следующие темы:
- Расширенные методы отладки с Visual Studio
- .NET Core и .NET Framework на Windows, Linux и Mac
- Проблемы с производительностью
- Утечки памяти и проблемы с нехваткой памяти
- Низкая производительность ASP.NET и неудачные запросы
- Отладка стороннего кода
- Отладка производственного кода в облаке
- Сбои и зависания
Вот фрагмент из введения:
«Лучшие инженеры-программисты, которых я знаю, отлично справляются с отладкой. Они находят решения сложных проблем там, где никто другой не может. Они достигают этого, используя правильные инструменты, зная, что искать, и имея глубокое понимание как своей собственной области, так и экосистемы .NET. Более того, они проводят систематическое расследование, используя проверенные методологии отладки. Отладка — это не искусство, это то, чему можно научить, и эта книга делает именно это. Эта книга — о совершенствовании ваших навыков отладки, экономии вашего времени и повышении вашей производительности.»
Книга вышла в 2020м году, но большинство информации в ней до сих пор актуально. Неплохой подарок от Майкла на новогодние праздники.
Источник: https://bartwullems.blogspot.com/2024/12/free-ebook-practical-debugging-for-net.html
👍14
День 2159. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 37. Не ждите, что без обучения и освоения передовых практик продуктивность повысится как по волшебству. Начало
Руководители часто думают, что у разработчиков ПО масса свободного времени. Может быть, они сами работают не в полную силу и имеют некий резерв, который смогут использовать, если на них надавить? Щелканье кнутом не может заставить лошадь бежать быстрее, если она уже мчится на пределе. Продолжая метафору, вы должны понять, почему лошадь бежит не так быстро, как вам хотелось бы, а после этого искать возможности для ускорения.
Команды можно мотивировать (или заставить) работать усерднее ради достижения краткосрочной цели, но не бесконечно. Уставшие люди совершают больше ошибок, что вынуждает их переделывать сделанную работу, и в конце концов выгорают. Если давить на людей слишком долго, они уйдут или станут саботировать работу. Героические усилия нигде и никогда не были устойчивой стратегией повышения производительности труда.
Если нет возможности нанять столько людей, сколько нужно для выполнения работы в сжатые сроки, то какими ещё переменными можно манипулировать? В их числе — передовые процессы и практики, лучшие инструменты и талантливые специалисты. Лучше нанять несколько талантливых специалистов, чем большую команду средних работников. Но нельзя просто поменять свою команду на группу более способных людей. Нужно сделать имеющихся более продуктивными.
В чем проблема?
Первый вопрос, который вы должны задать: «Почему наша продуктивность не так высока, как хотелось бы?» Начинайте поиск решения с выявления причин проблемы. Изучите предыдущие проекты, чтобы увидеть, где могли скрываться дополнительные возможности для повышения эффективности и результативности работы. Вот некоторые вопросы, которые следует рассмотреть.
- Выполняет ли команда работу, которую не должна выполнять?
- Что делают люди из того, что повышает ценность проекта и, возможно, может быть использовано в дальнейшем?
- Чего не делает команда из того, что ускорило бы их работу?
- Что ещё вас тормозит?
Некоторые возможные решения
1. Перестать выполнять работу, не несущую ценности. Но будьте осторожны: шаги, которые не приносят немедленной выгоды, часто окупаются позже, поэтому думайте о последствиях, прежде чем прекращать что-либо делать.
2. Улучшить качество результатов труда команды. Часто вместо того, чтобы перейти к созданию следующего компонента, команда вынуждена переделывать выполненную работу и исправлять дефекты. Сократить количество дефектов можно путём внедрения дополнительных методов контроля качества. Статический анализ и обзоры кода отнимают время, но с лихвой окупаются за счёт сокращения последующих доработок. Акцент на проектировании, а не на рефакторинге уменьшает технический долг, который команда должна погасить позже.
3. Понять, на что тратится время. Приходится ли людям подолгу ждать других, прежде чем перейти к следующему шагу? Ускорьте действия, лежащие на критическом пути. Некоторые члены команды теряют продуктивность из-за слишком большого количества решаемых ими задач? Посмотрите, не препятствует ли прогрессу «сила трения».
4. Расширить возможности отдельных членов команды. Я всегда предполагаю, что люди работают максимально эффективно для имеющегося уровня знаний и рабочего окружения. И физическое, и культурное рабочее окружение влияет на продуктивность и качество работы разработчика. Выбор оптимальных процессов и технических приёмов может значительно улучшить качество и тем самым повысить продуктивность. Развитие здоровой культуры разработки ПО, мотивирующей и вознаграждающей желаемое поведение, способствует эффективной работе счастливой команды.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
Уроки 50 Лет Разработки ПО
Урок 37. Не ждите, что без обучения и освоения передовых практик продуктивность повысится как по волшебству. Начало
Руководители часто думают, что у разработчиков ПО масса свободного времени. Может быть, они сами работают не в полную силу и имеют некий резерв, который смогут использовать, если на них надавить? Щелканье кнутом не может заставить лошадь бежать быстрее, если она уже мчится на пределе. Продолжая метафору, вы должны понять, почему лошадь бежит не так быстро, как вам хотелось бы, а после этого искать возможности для ускорения.
Команды можно мотивировать (или заставить) работать усерднее ради достижения краткосрочной цели, но не бесконечно. Уставшие люди совершают больше ошибок, что вынуждает их переделывать сделанную работу, и в конце концов выгорают. Если давить на людей слишком долго, они уйдут или станут саботировать работу. Героические усилия нигде и никогда не были устойчивой стратегией повышения производительности труда.
Если нет возможности нанять столько людей, сколько нужно для выполнения работы в сжатые сроки, то какими ещё переменными можно манипулировать? В их числе — передовые процессы и практики, лучшие инструменты и талантливые специалисты. Лучше нанять несколько талантливых специалистов, чем большую команду средних работников. Но нельзя просто поменять свою команду на группу более способных людей. Нужно сделать имеющихся более продуктивными.
В чем проблема?
Первый вопрос, который вы должны задать: «Почему наша продуктивность не так высока, как хотелось бы?» Начинайте поиск решения с выявления причин проблемы. Изучите предыдущие проекты, чтобы увидеть, где могли скрываться дополнительные возможности для повышения эффективности и результативности работы. Вот некоторые вопросы, которые следует рассмотреть.
- Выполняет ли команда работу, которую не должна выполнять?
- Что делают люди из того, что повышает ценность проекта и, возможно, может быть использовано в дальнейшем?
- Чего не делает команда из того, что ускорило бы их работу?
- Что ещё вас тормозит?
Некоторые возможные решения
1. Перестать выполнять работу, не несущую ценности. Но будьте осторожны: шаги, которые не приносят немедленной выгоды, часто окупаются позже, поэтому думайте о последствиях, прежде чем прекращать что-либо делать.
2. Улучшить качество результатов труда команды. Часто вместо того, чтобы перейти к созданию следующего компонента, команда вынуждена переделывать выполненную работу и исправлять дефекты. Сократить количество дефектов можно путём внедрения дополнительных методов контроля качества. Статический анализ и обзоры кода отнимают время, но с лихвой окупаются за счёт сокращения последующих доработок. Акцент на проектировании, а не на рефакторинге уменьшает технический долг, который команда должна погасить позже.
3. Понять, на что тратится время. Приходится ли людям подолгу ждать других, прежде чем перейти к следующему шагу? Ускорьте действия, лежащие на критическом пути. Некоторые члены команды теряют продуктивность из-за слишком большого количества решаемых ими задач? Посмотрите, не препятствует ли прогрессу «сила трения».
4. Расширить возможности отдельных членов команды. Я всегда предполагаю, что люди работают максимально эффективно для имеющегося уровня знаний и рабочего окружения. И физическое, и культурное рабочее окружение влияет на продуктивность и качество работы разработчика. Выбор оптимальных процессов и технических приёмов может значительно улучшить качество и тем самым повысить продуктивность. Развитие здоровой культуры разработки ПО, мотивирующей и вознаграждающей желаемое поведение, способствует эффективной работе счастливой команды.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
👍9
День 2160. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 37. Не ждите, что без обучения и освоения передовых практик продуктивность повысится как по волшебству. Окончание
Начало
Инструменты и обучение
Правильно подобранные инструменты могут повысить продуктивность. В действительности прирост продуктивности, вызванный использованием одного нового инструмента, редко превышает 35%. Продуктивность разработчиков ПО с годами растёт благодаря накопленным преимуществам нескольких инструментов, новым языкам и методам разработки, повторному использованию ПО и другим факторам. Не забывайте учитывать затраты на обучение, в ходе которого люди выясняют, как заставить новый инструмент работать эффективно. Ищите инструменты, позволяющие автоматизировать и документировать повторяющиеся задачи, такие как тестирование.
Обучение — мощный рычаг повышения продуктивности. Руководители, пытающиеся сделать больше с меньшими затратами, могут не решаться оторвать членов команды от работы на прохождение обучения, да и курсы стоят дорого. Но посчитайте. Сэкономив хотя бы час-два на своей работе (в любое время до конца жизни) за счёт того, что вы узнали из книги, вы с лихвой окупите затраченные на неё деньги. Инвестиции в обучение окупаются всегда, если новая практика, позволяющая получить более качественный результат за меньшее время, применяется в работе.
Индивидуальные особенности разработчиков
Любому хотелось бы думать, что в его команде собрались самые талантливые специалисты. Но половина всех программистов по своей продуктивности находится ниже медианы. Все эти люди где-то работают, и не у каждого руководителя есть возможность нанять специалистов высшей квалификации. Нелегко количественно оценить продуктивность разработчика ПО, но нередко продуктивность и качество команды зависят от того, кому будет поручена работа.
В многочисленных публикациях по разработке ПО отмечается десятикратный и более разброс в продуктивности между лучшими и худшими исполнителями. Однако в недавнем отчёте Билла Николса (Bill Nichols) из Software Engineering Institute утверждается, что это миф, и индивидуальные особенности могут увеличить продуктивность разработчиков максимум в два раза в любой конкретной деятельности.
Нет сомнений, что квалифицированные и талантливые люди и команды работают более продуктивно. Неудивительно, что, согласно отчету The Standish Group (2015), проекты, укомплектованные «одаренными» командами, использующими методы Agile-разработки, оказались более успешными, чем проекты, реализуемые низкоквалифицированными командами. При этом интересно отметить, что небольшие проекты имели более высокий уровень успеха, чем крупные. Возможно, это объясняется тем, что небольшую команду проще укомплектовать высококвалифицированными специалистами. Но не каждый может позволить себе нанимать лучших из лучших.
Если вы не можете собрать звёздную команду, то сосредоточьтесь на создании продуктивного окружения, чтобы добиться наилучших результатов от тех, кто у вас есть. Развивайте таланты каждого, делитесь передовым опытом. Постарайтесь понять, в чём секрет успеха ваших лучших работников (они известны всем), и поощряйте всех, кто учится у них. Технические навыки важны, но не менее ценны общение, сотрудничество, наставничество и отношение к продукту как к общей собственности. Лучшие разработчики, уделяют большое внимание качеству. Они проявляют интеллектуальную любознательность, обладают обширным опытом, постоянно занимаются самообучением и всегда готовы делиться знаниями.
Если вы должны делать больше с меньшими затратами, то не добьётесь желаемого, отдавая ничем не подкрепленные приказы, оказывая больше давления на команду или нанимая таланты только из 90-го процентиля. Путь к повышению продуктивности неизбежно состоит из обучения, овладения передовыми практиками и совершенствования процессов.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
Уроки 50 Лет Разработки ПО
Урок 37. Не ждите, что без обучения и освоения передовых практик продуктивность повысится как по волшебству. Окончание
Начало
Инструменты и обучение
Правильно подобранные инструменты могут повысить продуктивность. В действительности прирост продуктивности, вызванный использованием одного нового инструмента, редко превышает 35%. Продуктивность разработчиков ПО с годами растёт благодаря накопленным преимуществам нескольких инструментов, новым языкам и методам разработки, повторному использованию ПО и другим факторам. Не забывайте учитывать затраты на обучение, в ходе которого люди выясняют, как заставить новый инструмент работать эффективно. Ищите инструменты, позволяющие автоматизировать и документировать повторяющиеся задачи, такие как тестирование.
Обучение — мощный рычаг повышения продуктивности. Руководители, пытающиеся сделать больше с меньшими затратами, могут не решаться оторвать членов команды от работы на прохождение обучения, да и курсы стоят дорого. Но посчитайте. Сэкономив хотя бы час-два на своей работе (в любое время до конца жизни) за счёт того, что вы узнали из книги, вы с лихвой окупите затраченные на неё деньги. Инвестиции в обучение окупаются всегда, если новая практика, позволяющая получить более качественный результат за меньшее время, применяется в работе.
Индивидуальные особенности разработчиков
Любому хотелось бы думать, что в его команде собрались самые талантливые специалисты. Но половина всех программистов по своей продуктивности находится ниже медианы. Все эти люди где-то работают, и не у каждого руководителя есть возможность нанять специалистов высшей квалификации. Нелегко количественно оценить продуктивность разработчика ПО, но нередко продуктивность и качество команды зависят от того, кому будет поручена работа.
В многочисленных публикациях по разработке ПО отмечается десятикратный и более разброс в продуктивности между лучшими и худшими исполнителями. Однако в недавнем отчёте Билла Николса (Bill Nichols) из Software Engineering Institute утверждается, что это миф, и индивидуальные особенности могут увеличить продуктивность разработчиков максимум в два раза в любой конкретной деятельности.
Нет сомнений, что квалифицированные и талантливые люди и команды работают более продуктивно. Неудивительно, что, согласно отчету The Standish Group (2015), проекты, укомплектованные «одаренными» командами, использующими методы Agile-разработки, оказались более успешными, чем проекты, реализуемые низкоквалифицированными командами. При этом интересно отметить, что небольшие проекты имели более высокий уровень успеха, чем крупные. Возможно, это объясняется тем, что небольшую команду проще укомплектовать высококвалифицированными специалистами. Но не каждый может позволить себе нанимать лучших из лучших.
Если вы не можете собрать звёздную команду, то сосредоточьтесь на создании продуктивного окружения, чтобы добиться наилучших результатов от тех, кто у вас есть. Развивайте таланты каждого, делитесь передовым опытом. Постарайтесь понять, в чём секрет успеха ваших лучших работников (они известны всем), и поощряйте всех, кто учится у них. Технические навыки важны, но не менее ценны общение, сотрудничество, наставничество и отношение к продукту как к общей собственности. Лучшие разработчики, уделяют большое внимание качеству. Они проявляют интеллектуальную любознательность, обладают обширным опытом, постоянно занимаются самообучением и всегда готовы делиться знаниями.
Если вы должны делать больше с меньшими затратами, то не добьётесь желаемого, отдавая ничем не подкрепленные приказы, оказывая больше давления на команду или нанимая таланты только из 90-го процентиля. Путь к повышению продуктивности неизбежно состоит из обучения, овладения передовыми практиками и совершенствования процессов.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 5.
👍10
День 2161. #ЗаметкиНаПолях
Планировка Фоновых Задач с Помощью Quartz. Начало
Большинству приложений ASP.NET Core необходимо обрабатывать фоновые задачи. Хотя существует множество способов их реализации, Quartz.NET выделяется своими надёжными возможностями планирования, настройкой хранения заданий и богатой функциональностью. Основы Quartz в этом посте. Здесь рассмотрим некоторые продвинутые настройки. Извините за многокода.
Настройка Телеметрии Quartz в ASP.NET Core
Сначала установим пакеты Quartz:
Также потребуются некоторые пакеты OpenTelemetry.
Затем настроим сервисы Quartz и инструментарий OpenTelemetry:
Определение и планирование заданий
Все задания реализуют IJob и выполняются как сервисы с ограниченной областью действия, поэтому при необходимости можно внедрять зависимости. Quartz позволяет передавать данные заданию с помощью словаря JobDataMap. Рекомендуется использовать только примитивные типы для данных задания, чтобы избежать проблем с сериализацией и использовать MergedJobDataMap для извлечения данных задания.
Создадим задание для email-напоминания:
Замечание: JobDataMap не строго типизирован. Поэтому рекомендуется:
- Использовать константы для ключей;
- Проверять данные в методе Execute;
- Создавать сервисы-обёртки для планирования заданий.
Вот как запланировать одноразовые напоминания:
Конечная точка планирует одноразовые напоминания по email с помощью Quartz. Она создаёт задание с данными пользователя, устанавливает триггер на указанное время и планирует их. EmailJob получает уникальный идентификатор в группе "email-reminders".
Пример запроса:
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-in-dotnet-advanced-concepts
Планировка Фоновых Задач с Помощью Quartz. Начало
Большинству приложений ASP.NET Core необходимо обрабатывать фоновые задачи. Хотя существует множество способов их реализации, Quartz.NET выделяется своими надёжными возможностями планирования, настройкой хранения заданий и богатой функциональностью. Основы Quartz в этом посте. Здесь рассмотрим некоторые продвинутые настройки. Извините за многокода.
Настройка Телеметрии Quartz в ASP.NET Core
Сначала установим пакеты Quartz:
Install-Package Quartz.Extensions.Hosting
Install-Package Quartz.Serialization.Json
# Пока в предрелизе
Install-Package OpenTelemetry.Instrumentation.Quartz
Также потребуются некоторые пакеты OpenTelemetry.
Затем настроим сервисы Quartz и инструментарий OpenTelemetry:
builder.Services.AddQuartz();
builder.Services.AddQuartzHostedService(opts =>
{
opts.WaitForJobsToComplete = true;
});
builder.Services.AddOpenTelemetry()
.WithTracing(trc =>
{
trc
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.AddQuartzInstrumentation();
})
.UseOtlpExporter();
Определение и планирование заданий
Все задания реализуют IJob и выполняются как сервисы с ограниченной областью действия, поэтому при необходимости можно внедрять зависимости. Quartz позволяет передавать данные заданию с помощью словаря JobDataMap. Рекомендуется использовать только примитивные типы для данных задания, чтобы избежать проблем с сериализацией и использовать MergedJobDataMap для извлечения данных задания.
Создадим задание для email-напоминания:
public class EmailJob(
IEmailService emailSvc) : IJob
{
public const string Name = nameof(EmailJob);
public async Task Execute(
IJobExecutionContext ctx)
{
var data = ctx.MergedJobDataMap;
try
{
await emailSvc.SendAsync(
data.GetString("userId"),
data.GetString("message"));
}
catch (Exception ex)
{
// … обработка … и throw,
// чтобы Quartz попробовал снова
throw;
}
}
}
Замечание: JobDataMap не строго типизирован. Поэтому рекомендуется:
- Использовать константы для ключей;
- Проверять данные в методе Execute;
- Создавать сервисы-обёртки для планирования заданий.
Вот как запланировать одноразовые напоминания:
public record Reminder(
string UserId,
string Message,
DateTime ScheduleTime
);
app.MapPost("/api/reminders/schedule", async (
ISchedulerFactory schFactory,
Reminder rem) =>
{
var scheduler = await schFactory.GetScheduler();
var jobData = new JobDataMap
{
{ "userId", rem.UserId },
{ "message", rem.Message }
};
var group = "email-reminders";
var job = JobBuilder.Create<EmailJob>()
.WithIdentity(
$"reminder-{Guid.NewGuid()}", group)
.SetJobData(jobData)
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity(
$"trigger-{Guid.NewGuid()}", group)
.StartAt(rem.ScheduleTime)
.Build();
await scheduler.ScheduleJob(job, trigger);
return Results.Ok(new
{
scheduled = true,
at = rem.ScheduleTime
});
})
.WithName("ScheduleReminder")
.WithOpenApi();
Конечная точка планирует одноразовые напоминания по email с помощью Quartz. Она создаёт задание с данными пользователя, устанавливает триггер на указанное время и планирует их. EmailJob получает уникальный идентификатор в группе "email-reminders".
Пример запроса:
POST /api/reminders/schedule
{
"userId": "user42",
"message": "Meeting!",
"scheduleTime": "2024-12-31T23:00:00"
}
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-in-dotnet-advanced-concepts
👍10
День 2162. #ЗаметкиНаПолях
Планировка Фоновых Задач с Помощью Quartz. Окончание
Начало
Планирование повторяющихся заданий
Для повторяющихся фоновых заданий можно использовать расписания cron:
Триггеры Cron более эффективны, чем простые. Они позволяют определять сложные расписания, например «каждый будний день в 10 утра»:
Настройка хранения заданий
По умолчанию Quartz использует хранилище в памяти, т.е. задания теряются при перезапуске приложения. Для постоянного хранения поддерживается несколько провайдеров БД. Вот как настроить постоянное хранилище с надлежащей изоляцией схемы:
Замечания:
- TablePrefix помогает организовать таблицы Quartz - в данном случае, помещая их в отдельную схему scheduler;
- Нужно будет запустить соответствующие скрипты БД для создания этих таблиц. Каждый поставщик БД имеет свои скрипты настройки.
Долгосрочные Задания
Мы настроили EmailJob с StoreDurably. Это позволяет определить задание 1 раз и повторно использовать его с разными триггерами:
Такой подход имеет несколько преимуществ:
- Определения заданий централизованы в стартовой конфигурации;
- Не получится случайно запланировать задание, которое не было правильно настроено;
- Конфигурации заданий согласованы во всех расписаниях.
Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-in-dotnet-advanced-concepts
Планировка Фоновых Задач с Помощью Quartz. Окончание
Начало
Планирование повторяющихся заданий
Для повторяющихся фоновых заданий можно использовать расписания cron:
public record RecurringReminder(
string UserId,
string Message,
string CronExpression
);
app.MapPost("/api/recurring/schedule", async (
ISchedulerFactory schFactory,
RecurringReminder rem) =>
{
var scheduler = await schFactory.GetScheduler();
var jobData = new JobDataMap
{
{ "userId", rem.UserId },
{ "message", rem.Message }
};
var group = "recurring-reminders";
var job = JobBuilder.Create<EmailJob>()
.WithIdentity(
$"recurring-{Guid.NewGuid()}", group)
.SetJobData(jobData)
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity(
$"rectrigger-{Guid.NewGuid()}", group)
.WithCronSchedule(rem.CronExpression)
.Build();
await scheduler.ScheduleJob(job, trigger);
return Results.Ok(new {
scheduled = true,
cron = rem.CronExpression });
})
.WithName("RecurringReminder")
.WithOpenApi();
Триггеры Cron более эффективны, чем простые. Они позволяют определять сложные расписания, например «каждый будний день в 10 утра»:
POST /api/recurring/schedule
{
"userId": "user69",
"message": "Daily",
"cronExpression": "0 0 10 ? * MON-FRI"
}
Настройка хранения заданий
По умолчанию Quartz использует хранилище в памяти, т.е. задания теряются при перезапуске приложения. Для постоянного хранения поддерживается несколько провайдеров БД. Вот как настроить постоянное хранилище с надлежащей изоляцией схемы:
builder.Services.AddQuartz(opts =>
{
opts.AddJob<EmailJob>(c => c
.StoreDurably()
.WithIdentity(EmailJob.Name));
opts.UsePersistentStore(o =>
{
o.UsePostgres(cfg =>
{
cfg.ConnectionString = "…";
cfg.TablePrefix = "scheduler.qrtz_";
},
dataSourceName: "reminders"); // Имя БД
o.UseNewtonsoftJsonSerializer();
o.UseProperties = true;
});
});
Замечания:
- TablePrefix помогает организовать таблицы Quartz - в данном случае, помещая их в отдельную схему scheduler;
- Нужно будет запустить соответствующие скрипты БД для создания этих таблиц. Каждый поставщик БД имеет свои скрипты настройки.
Долгосрочные Задания
Мы настроили EmailJob с StoreDurably. Это позволяет определить задание 1 раз и повторно использовать его с разными триггерами:
public async Task ScheduleReminder(
string userId, string msg, DateTime dt)
{
var scheduler = await schFactory.GetScheduler();
// Извлекаем задание по его имени
var jobKey = new JobKey(EmailJob.Name);
var trigger = TriggerBuilder.Create()
// Используем задание по ссылке
.ForJob(jobKey)
.WithIdentity($"trigger-{Guid.NewGuid()}")
.UsingJobData("userId", userId)
.UsingJobData("message", msg)
.StartAt(dt)
.Build();
// Передаём только триггер
await scheduler.ScheduleJob(trigger);
}
Такой подход имеет несколько преимуществ:
- Определения заданий централизованы в стартовой конфигурации;
- Не получится случайно запланировать задание, которое не было правильно настроено;
- Конфигурации заданий согласованы во всех расписаниях.
Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-in-dotnet-advanced-concepts
5👍9