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

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2152. #ЗаметкиНаПолях
Внутренние и Публичные 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.
👍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/
👍9
День 2155. #ЗаметкиНаПолях
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. Стратегия выполнения транзакций
В этом способе создаётся стратегия выполнения, в которой управляются транзакции. Она продолжает пытаться выполнить операции с БД указанное количество раз, если транзакция не удаётся из-за временной ошибки. Это итеративное поведение гарантирует, что незначительные проблемы не повлияют на фактические операции.

Добавим к зданиям различные помещения в зданиях:
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 для этого будет выглядеть примерно так:
<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
👍14
День 2159. #УрокиРазработки
Уроки 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.
👍10
День 2161. #ЗаметкиНаПолях
Планировка Фоновых Задач с Помощью 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:
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
День 2163.
Дорогие подписчики, с новым 2025м годом!


.NET появился в начале века,
Стал любимой платформой для каждого человека.
От Windows Forms до ASP.NET,
Он покорил разработчиков свет.

C# и VB.NET были языки его,
На них кодить просто и легко.
WPF и WCF — его дети,
Служили верой и правдой всем на свете.

С каждым годом он рос и крепчал,
Новые фичи в себя включал.
.NET Core пришел на смену,
Кроссплатформенность — его арена.

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

(с) Copilot, естественно. Я бы так не написал 😄
2👍51
День 2164. #Оффтоп
Никому Больше не Нравится Название .NET Core


Автор оригинала: Стивен Клири

Я подумал, что будет неплохо написать об истории терминологии «.NET Core». Вот каким я запомнил термин «.NET Core». Это не гарантирует правильности и, конечно, не гарантирует полноты! Я что-то упустил? Не стесняйтесь сообщить в комментариях!

.NET Compact Framework
Я думаю, что впервые услышал термин «.NET Core» в отношении .NET Compact Framework. Это было давно, когда .NET Framework 3.5 был новинкой. Точнее это был «.NET Framework 3.5 SP1» — Service Pack 1. Да, и у .NET раньше были пакеты обновлений.

Я не уверен, является ли «.NET Core» правильным термином для обозначения NetCF или нет. Насколько мне известно, это был неофициальный термин, который был применён, поскольку .NET Compact Framework содержал небольшое подмножество огромного .NET Framework, предназначенное для работы на встраиваемых устройствах. Следовательно, это был «основной» (core), минимальный, фреймворк.

Silverlight, WinRT, Windows Phone, Windows Store и Universal Windows Platform
Прошу прощенья у всех, кого передёрнуло от одного прочтения названия этого раздела…

Все эти технологии имели какое-то отношение к «.NET Core» как к термину. Все они были минимальными подфреймворками полной .NET Framework. И по крайней мере некоторые из них имели схожую терминологию для своих сред выполнения (например, Silverlight работал на «Core CLR»). Мой мозг милостиво забыл грязные подробности. Я только смутно помню, что платформа Windows Phone отличалась от платформы для приложений в Windows Store, а Silverlight стал ещё более урезанным для работы на Windows Phone.

Это было не самое весёлое время для разработчика библиотек.

netcore как моникер целевой платформы
Моникеры целевой платформы (Target framework moniker - TFM) очень важны для разработчиков библиотек.

Термин «.NET Core» официально вошёл в пространство NuGet как TFM, но не для того, что мы называем .NET Core сегодня. Он был для приложений Windows Store (и приложений WinRT) и ненадолго распространился на приложения UWP.

Да, проекты Windows Store ещё в Windows 8.0 (а также WinRT) использовали идентификатор TFM netcore45. Windows 8.1 использовал netcore451. Когда приложения Windows Store были заменены приложениями универсальной платформы Windows (UWP), они недолго использовали netcore50, прежде чем перейти на uap10.0.
Поэтому, если (современной) команде .NET Core вдруг понадобится TFM, они обнаружат, что netcoreNN недоступен. Я предполагаю, что именно поэтому был выбран моникер netcoreappNN (после краткого использования на dnxcore50 и aspnetcore50). Так что .NET Core TFM для старых версий (1.0-3.1) – это с netcoreapp1.0 до netcoreapp3.1. Это была просто досадная историческая случайность.

Больше никакого .NET Core
Команда .NET отказалась от «Core». Теперь у нас единый .NET — большое облегчение для авторов библиотек!

С версии 5 даже TFM изменились: современный .NET использует net9.0 и подобные, опустив прозвище «core» даже из TFM.

Я все ещё время от времени называю .NET как «.NET Core», особенно в разговорах, где упоминаются как .NET Framework, так и нового .NET. Например, я буду говорить «миграция на .NET Core», а не просто «миграция на .NET» для проекта, который в настоящее время нацелен на .NET Framework. Однако правильный термин больше не «.NET Core», а просто «.NET».

Источник: https://blog.stephencleary.com/2024/12/netcore.html
👍19👎2
День 2165. #Оффтоп #AI
ИИ не Заменит Команду Инженеров. Начало
Если позволите, я тоже немного отдохну. Поэтому вот вам лёгкий лонгрид на праздники.

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

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

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

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

ПО — индустрия обучения. Вы не можете научиться быть инженером-программистом, читая книги. Вы можете учиться только делая… и делая, и ещё делая. Неважно, какое у вас образование, большая часть обучения происходит на работе… и никогда не заканчивается!

Требуется более 7 лет, чтобы выковать компетентного инженера-программиста (как в большинстве случаев называют, сеньора). Это много лет написания, проверки и развёртывания кода каждый день в команде вместе с более опытными инженерами.

Что значит быть «сеньором»?
Об этом есть целая серия постов на канале. Ищите по тэгу #КакСтатьСеньором

По поводу сроков есть очень много споров:
«7 лет?! Пфф, мне потребовалось 2 года!»
«Меня повысили до сеньора меньше, чем за 5 лет!»

Молодцы! Да, в 7 годах нет ничего волшебного. Но для того, чтобы стать опытным инженером, способным сплотить команду, требуются время и опыт. Более того, нужна практика.

Думаю, мы стали использовать слово «сеньор» как сокращение для инженеров, которые могут поставлять готовый чистый код и быть продуктивными, и кажется, что это огромная ошибка. Это подразумевает, что младшие инженеры менее продуктивны, что неверно. И это упускает из виду истинную природу работы по разработке ПО, в которой написание кода является лишь небольшой частью.

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

Что подводит нас к вопросу об ИИ.

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

Источник:
https://stackoverflow.blog/2024/12/31/generative-ai-is-not-going-to-build-your-engineering-team-for-you
5👍20👎1
День 2166. #Оффтоп #AI
ИИ не Заменит Команду Инженеров. Продолжение

1. ПО - индустрия обучения

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

Однако в последнее время ряд руководителей и «лидеров мнений» в сфере технологий, похоже, убедили себя в том, что ИИ находится на грани замены всей работы, выполняемой джунами. Это говорит о глубоком непонимании того, чем на самом деле занимаются инженеры. Не нанимая и не обучая джунов, мы каннибализируем собственное будущее.

Писать код легко
Написание кода — самая лёгкая часть разработки ПО, и с каждым днём становится проще. Сложная часть — это эксплуатация, понимание, расширение и управление им на протяжении всего его жизненного цикла.

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

Социотехнические системы состоят из ПО, инструментов и людей; для их понимания требуется знакомство с взаимодействием между ПО, пользователями, производством, инфраструктурой и непрерывными изменениями с течением времени. Эти системы фантастически сложны и подвержены хаосу и непредсказуемому поведению. Если кто-то утверждает, что понимает систему, которую он разрабатывает и эксплуатирует, то либо система мала, либо (более вероятно) он недостаточно знает, чтобы знать, чего он не знает. Код прост, а системы сложны.

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

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

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

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

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

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

Источник:
https://stackoverflow.blog/2024/12/31/generative-ai-is-not-going-to-build-your-engineering-team-for-you
5👍8
День 2167. #Оффтоп #AI
ИИ не Заменит Команду Инженеров. Продолжение

1. ПО – индустрия обучения
2. Просто писать код, сложно писать хороший код

Как инженеры на самом деле используют ИИ
Вы можете сгенерировать много кода очень быстро, но вы не можете доверять тому, что получится. Однако есть некоторые примеры использования, в которых ИИ неизменно блистает:
1. Часто проще попросить ChatGPT сгенерировать пример кода с использованием незнакомых API, чем читать документацию по API.
2. Создание кода, который раздражает или утомителен для написания, но при этом имеет узкую область действия и легко объясняется. Чем более предсказуем сценарий, тем лучше эти инструменты пишут код за вас.
3. Написание небольших функций, чтобы делать что-то на незнакомых языках или в незнакомых сценариях. Если у вас есть фрагмент кода Python и вы хотите то же самое на Java, но вы не знаете Java, ИИ поможет.

Но, помните: вероятность того, что результат полностью выдуман, составляет 50/50. Всегда придется предполагать, что результаты неверны, пока вы не проверите их вручную.

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

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

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

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

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

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

Каждому нанятому инженеру требуется время на разгон, прежде чем он сможет внести свой вклад, независимо от его уровня. Сколько времени? Зависит от чистоты и организованности кодовой базы, прошлого опыта работы с вашими инструментами и технологиями и многого другого, но, скорее всего, 6-9 месяцев. Да, разгон будет дольше для джуна, и это потребует больше инвестиций от команды. Но не критически больше. Джун должен начать приносить пользу в течение примерно того же периода времени, и джуны развиваются гораздо быстрее, чем более опытные работники.

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

Источник:
https://stackoverflow.blog/2024/12/31/generative-ai-is-not-going-to-build-your-engineering-team-for-you
👍16
День 2168. #Оффтоп #AI
ИИ не Заменит Команду Инженеров. Продолжение

1. ПО - индустрия обучения
2. Просто писать код, сложно писать хороший код
3. ИИ похож на джуна

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

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

И они полны энергии… вовлечены. Они получают удовольствие! Это обычно означает, что они будут делать работу лучше, особенно под руководством кого-то более опытного. Наличие в команде мидлов — это потрясающе. Единственный способ получить их — нанять джунов.

Почти все согласны, что нанимать джунов — это хорошо в долгосрочной перспективе… и это должен делать кто-то другой, т.к. «нам сейчас нужны сеньоры», «джунов долго обучать» и т.п. Долгосрочное мышление — не то, в чём компании или капитализм в целом обычно хороши. Компании гораздо более склонны выносить такие издержки за пределы компании. Но есть несколько аргументов в пользу найма джунов в краткосрочной перспективе.

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

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

Здоровая команда включает людей разных уровней
Вы не будете укомплектовывать команду по разработке продукта шестью экспертами по БД и одним мобильным разработчиком. Также нельзя включать в неё 6 сеньоров и 1 джуна. Существует не так много высокоуровневой архитектуры и планирования, не так много важных решений, которые нужно принять. Сеньоры будут проводить большую часть времени, выполняя работу, которая кажется им скучной и повторяющейся, поэтому будут оверинжинирить решения и/или экономить на них — иногда в одно и то же время. Они будут хронически недодокументировать и недоинвестировать в работу, которая делает системы простыми и управляемыми.

Команды, из инженеров одного уровня будут иметь разные патологии, но схожие проблемы с разногласиями и «слепыми пятнами». Сама работа имеет широкий диапазон сложности и трудности — от простых, узконаправленных функций до сложных, высокорискованных архитектурных решений. Лучшие команды — те, где никому не скучно, потому что каждый работает над чем-то, что бросает ему вызов и расширяет границы. Единственный способ добиться этого — иметь в команде разные уровни навыков.

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

Источник:
https://stackoverflow.blog/2024/12/31/generative-ai-is-not-going-to-build-your-engineering-team-for-you
1👍17
День 2169. #Оффтоп #AI
ИИ не Заменит Команду Инженеров. Окончание

1. ПО - индустрия обучения
2. Просто писать код, сложно писать хороший код
3. ИИ похож на джуна
4. Здоровая команда включает людей разных уровней

Узкое место — найм, а не обучение
Узкое место сейчас — это предоставление джунам их первой работы. Оно в компаниях, которые видят в джунах издержки, а не инвестиции в своё будущее.

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

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

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

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

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

Должна ли каждая компания нанимать джунов?
Нет. Вот несколько факторов, которые не позволят компании нанимать джунов:
- Меньше двух лет работы;
- Команда постоянно находится в режиме пожаротушения;
- Нет опытных менеджеров;
- Нет дорожной карты продукта;
- Никто в команде не заинтересован в том, чтобы быть их наставником или руководителем.

Единственное, что хуже, чем вообще не нанимать джунов, — это нанимать их в ужасные условия, где они не смогут ничему научиться. Хотя большинство джунов скорее предпочтут паршивую первую работу, чем вообще ничего.

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

Никто не придёт решить наши проблемы за нас
В большинстве мест, где есть программа найма и обучения инженеров начального уровня, она есть только потому, что инженеры решили за неё бороться. Инженеры её создавали, выбивали ресурсы, разрабатывали программу, проводили собеседования и нанимали джунов и их наставников. Это вполне в пределах возможностей большинства мотивированных, опытных инженеров (и также полезно для вашей карьеры).

Финансы будут против. Руководители вряд ли вмешаются. Чем больше роль человека склоняет его относиться к инженерам как к взаимозаменяемым ресурсам, тем меньше вероятность, что он поймёт, почему это важно.

ИИ не решит все наши проблемы и не напишет весь код за нас. А даже если бы это было так, написание кода — лишь часть того, что делают профессиональные инженеры-программисты, и, возможно, самая простая часть. Только у нас есть контекст и авторитет, чтобы управлять изменениями, которые составляют основу для отличных команд и совершенствования как инженер.

Источник: https://stackoverflow.blog/2024/12/31/generative-ai-is-not-going-to-build-your-engineering-team-for-you
👍8
День 2170. #ЗаметкиНаПолях
Подписываем Коммиты в Git SSH-Ключами в Windows
Подписание коммитов в Git — это способ проверки подлинности и целостности коммитов. Это гарантирует, что коммиты действительно сделаны вами и не были подделаны. В Windows легко настроить SSH-Agent для подписи.

Сначала установим SSH в Windows. Откройте окно PowerShell от имени администратора и выполните следующую команду:
Add-WindowsCapability -Online -Name OpenSSH.Client

Можно проверить статус так:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Client*'

Теперь создадим пару ключей SSH (для PowerShell 7.1+):
$passphrase = Read-Host -Prompt "Enter passphrase" -AsSecureString
$KeyName = "git"
ssh-keygen -t ed25519 -C $KeyName -N (ConvertFrom-SecureString -AsPlainText $passphrase)

Чтобы не вводить парольную фразу каждый раз при использовании ключа, можно добавить её в SSH Agent. Запустим сервис SSH Agent и настроим его на автоматический запуск:
Set-Service -Name ssh-agent -StartupType Automatic
Start-Service ssh-agent

Теперь добавим ключ в SSH Agent:
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Можно проверить, что ключ добавлен:
ssh-add -L

Должен отобразиться публичный ключ.

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

Теперь, если нужно, установите Git:
winget install --id Git.Git –exact

Наконец, настроим Git для использования SSH-ключа для подписи коммитов:
# Используем SSH-ключ для подписей
git config --global user.signingkey (Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub)
git config --global gpg.format ssh
git config --global gpg.ssh.program (Get-Command ssh-keygen.exe).Source
git config --global core.sshCommand (Get-Command ssh.exe).Source

# Настраиваем подписывать коммиты и теги по умолчанию
git config --global commit.gpgsign true
git config --global tag.gpgsign true


Последний шаг — зарегистрировать SSH-ключ в провайдере Git. Вы можете найти открытый ключ в папке .ssh в каталоге вашего профиля пользователя. Скопируйте содержимое файла id_ed25519.pub и добавьте его у провайдера Git:
GitHub: https://github.com/settings/ssh/new
GitLab: https://gitlab.com/-/user_settings/ssh_keys

Для GitHub можно также использовать GitHub CLI:
gh ssh-key add $env:USERPROFILE\.ssh\id_ed25519 --title git --type signing


Проверяем подпись коммита:
git commit --allow-empty --message="Testing SSH signing"

На сайте GitHub вы должны увидеть значок "Verified" рядом с сообщением коммита.

Можно проверить подпись локально. Сначала добавим SSH-ключ в доверенных подписантов:
git config --global gpg.ssh.allowedSignersFile $env:USERPROFILE/.ssh/allowed_signers

$email = (git config user.email)
$key = (Get-Content $env:USERPROFILE/.ssh/id_ed25519.pub)
$signer = "$email $key"
echo $signer | Out-File $env:USERPROFILE/.ssh/allowed_signers -Append

Теперь можно проверить подпись коммита:
git show --show-signature


Эта настройка позволяет проверить ваш коммит, используя ваш SSH-ключ. Если вы хотите проверять коммиты, подписанные другими людьми, нужно добавить их ключи в файл allowed_signers. Для GitHub вы можете запросить ключи SSH, используя API GitHub:
gh api /users/meziantou/ssh_signing_keys

Затем вы можете добавить ключ в файл allowed_signers и выполнить предыдущую команду для проверки подписи.

Источник: https://www.meziantou.net/signing-commits-in-git-using-ssh-keys-on-windows.htm
👍22
Какой псевдопеременной НЕ существует в отлaдчике языка C# в Visual Studio?
#Quiz #VS #Debugging
Anonymous Quiz
6%
$exception
24%
$returnvalue
10%
$thread
60%
$user
👎3
День 2171. #ЗаметкиНаПолях
Псевдопеременные в Отладчике Visual Studio в C#
Псевдопеременные — это термины, используемые для отображения определённой информации в окне Watch или Immediate. Вы можете ввести псевдопеременную так же, как вы вводите обычную переменную. Однако псевдопеременные не являются переменными и не соответствуют именам переменных в вашем коде.

1. $exception
Оценивает текущее выброшенное исключение. Переменная доступна в момент выбрасывания исключения, а также в блоке catch, если исключение перехвачено. Это полезно в случаях, когда вы не добавили параметр Exception в предложение catch. Вы также можете увидеть исключение в окне Locals.

2. $returnvalue
Показывает и возвращает значение метода, из которого только что вышли. Это полезно, если вы не присваиваете возвращаемое значение какой-то переменной (а, например, сразу используете return). Заметьте, однако, что значение будет доступно только сразу после выхода из метода:
- на следующей строке, если вы поставили там точку останова, либо перескочили (F10) через вызов метода;
- при выходе из метода (на строке с закрывающей скобкой после return), если вы проходите по коду самого метода.
Кроме того, возвращаемое значение автоматически показывается в окнах Locals и Autos.

3. $user
Показывает информацию о текущем пользователе ОС и процессе. Сюда входит имя машины, привилегии процесса и некоторые другие сведения, связанные с безопасностью.

4. $threadSmallObjectHeapBytes
Отображает общее количество байт, выделенных в куче малых объектов (Small Object Heap) текущим потоком. (.NET 6+)

5. $threadUserOldHeapBytes
Отображает общее количество байт, выделенных в Пользовательской Куче Старшего поколения (User Old Heap) текущим потоком. User Old Heap = Large Object Heap + Pinned Object Heap (.NET 6+)

6. $1, $2, …, $n
Отображают по порядку объекты, для которых создан Object ID при отладке. Подробнее в этом посте.

Источники:
- Michael Shpilt «Practical Debugging for .NET Developers». - 2020. Глава 3.
-
https://learn.microsoft.com/en-us/visualstudio/debugger/pseudovariables?view=vs-2022
👍24