.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
День 1686. #ЗаметкиНаПолях
Решение Проблем Гонки с Помощью Оптимистической Блокировки EF Core. Окончание
Начало

Обработка исключений параллелизма
Теперь мы можем исправить предыдущий фрагмент кода.

Если два одновременных запроса проходят проверку IsOverlapping, только один может завершить вызов SaveChanges. Другой конкурентный запрос приведёт к несоответствию версии в базе данных и выдаст исключение DbUpdateConcurrencyException.

На случай конфликта параллелизма нам нужно добавить оператор try-catch, чтобы перехватить исключение DbUpdateConcurrencyException. То, как вы будете обрабатывать фактическое исключение, зависит от ваших бизнес-требований.
public Result<Guid> Handle(
ReserveBooking command,
AppDbContext ctx)
{
var user = ctx.Users.GetById(command.UserId);
var apart = ctx.Aparts.GetById(command.ApartId);
var (start, end) = command;

if (ctx.Bookings.IsOverlapping(apart, start, end))
return Result.Failure<Guid>(Errors.Overlap);

try
{
var booking = Booking
.Reserve(apart, user, start, end);

ctx.Add(booking);
ctx.SaveChanges();

return booking.Id;
}
catch (DbUpdateConcurrencyException)
{
return Result.Failure<Guid>(Errors.Overlap);
}
}

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

Однако вам всё равно придётся ожидать конфликтов параллелизма и реализовать специальную логику для их обработки.

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

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

Источник: https://www.milanjovanovic.tech/blog/solving-race-conditions-with-ef-core-optimistic-locking
👍15
Какие (относительно) редкие управляющие ключевые слова вы используете в своём коде?
Anonymous Poll
58%
continue
26%
checked/unchecked
24%
do
46%
finally
30%
goto
39%
lock
27%
unsafe
День 1687. #ВопросыНаСобеседовании #Многопоточность
Самые часто задаваемые вопросы на собеседовании по C#

22. В контексте многопоточности C# каковы основные различия между ThreadPool и созданием выделенных экземпляров Thread?

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

2. Время жизни потока: потоки из ThreadPool имеют фоновый статус, и их время жизни управляется системой. Выделенные потоки по умолчанию имеют приоритетный статус, а их время существования контролируется разработчиком.

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

4. Приоритет и настройка: потоки из ThreadPool имеют приоритет по умолчанию и ограниченную настройку. Выделенные потоки можно настраивать по приоритету, имени, размеру стека и другим свойствам.

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

Пример использования ThreadPool:
ThreadPool.QueueUserWorkItem((_) =>
{
// Логика вашей задачи здесь
});

Пример выделенного потока:
var thread = new Thread(() =>
{
// Логика вашей задачи здесь
});
thread.Start();

Источник: https://dev.to/bytehide/c-multithreading-interview-questions-and-answers-4opj
👍10
День 1688. #ЧтоНовенького
Сохраняем Регистр Символов при Замене в Visual Studio
В инструмент поиска и замены Visual Studio добавлена новая функция, которая позволяет пользователям находить и заменять текст, не беспокоясь о различных регистрах. Например, в случае, когда параметр метода catalogItemId и свойство объекта CatalogItemId имеют одно и то же имя, но разные заглавные буквы, но оба должны быть заменены чем-то вроде productId в соответствии с регистром (см. картинку).

Эта функция была запрошена пользователями на Stack Overflow ещё в 2008 (sic!) году. И наконец стала доступна, начиная с версии 17.8 Preview 1.

Когда вы выполняете замену, вы можете сохранить исходный регистр каждого совпадения в коде. Переключите сохранение регистра в окне «Заменить» с помощью Alt+V или нажав кнопку «Сохранить регистр» (иконка AB).
В окне «Заменить в Файлах» отметьте флажок «Сохранить регистр» (Preserve case). Регистр также сохраняется в тексте, содержащем дефисы и символы подчёркивания.

Источник
👍6👎1
День 1689. #TipsAndTricks
Теневые Свойства в Entity Framework Core
Множество моделей, перегружено свойствами, которые на самом деле не обязательно в них включать. Вместо этого мы можем использовать теневые свойства, чтобы сохранить чистоту модели и включать в неё только те свойства, которые относятся к предметной области.

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

Другой вариант использования — свойства, которые содержат ссылку на внешний ключ, или свойства навигации. Это очень путает, потому что неясно, какое свойство использовать. Например:
class Customer
{
// внешний ключ
public Guid AddressId { get; set; }

// навигационное свойство
public Address Address { get; set; }
}
Мы можем сказать Entity Framework создать теневое свойство AddressId и добавить необходимые ограничения отношений.

Рассмотрим пример создания теневого свойства для «мягкого удаления»:
protected override void 
OnModelCreating(ModelBuilder mb)
{
mb.Entity<Customer>()
.Property<DateTime?>("DeletedOn");

mb.Entity<Customer>()
.HasQueryFilter(e =>
EF.Property<DateTime?>(e, "DeletedOn") == null);
}

Чтобы устанавливать и обновлять значения теневого свойства, получите EntityEntry сущности и используйте метод Property:
dbContext
.Entry(customer)
.Property("DeletedOn")
.CurrentValue = DateTime.UtcNow;
dbContext.SaveChanges();

Это более полезно, когда не нужно думать об этих свойствах, а они устанавливаются автоматически. Этого можно добиться, переопределив метод SaveChanges объекта DbContext:
public class DemoDbContext : DbContext
{
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
foreach (var e in
ChangeTracker.Entries())
{
if (e.State == EntityState.Added)
e.Property("CreatedOn")
.CurrentValue = DateTime.UtcNow;

if (e.State == EntityState.Modified)
e.Property("UpdatedOn")
.CurrentValue = DateTime.UtcNow;

if (e.State == EntityState.Deleted)
e.Property("DeletedOn")
.CurrentValue = DateTime.UtcNow;
}
return base.SaveChanges();
}
}

Источник: https://timdeschryver.dev/blog/entity-framework-features-i-wish-i-knew-earlier#shadow-properties
👍18
День 1690. #Карьера
Худший Программист, Которого Я Знаю
Самое замечательное в измерении продуктивности разработчиков заключается в том, что вы можете быстро выявить плохих программистов. Я хочу рассказать вам о худшем программисте, которого я знаю, и почему я боролся за то, чтобы удержать его в команде. Его зовут Тим Маккиннон, и я хочу, чтобы вы знали, насколько он непродуктивен.

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

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

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

Что ж, Тиму явно пора было уходить. Таков был вывод менеджера, и он попросил меня принять необходимые меры, чтобы Тима уволили и заменили кем-то, кто будет… творить истории. Но я наотрез отказался. Для меня это даже не было трудным решением, я просто сказал «нет».

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

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

Тим не поставлял ПО; Тим руководил командой, которая поставляла ПО. Вся команда становилась более эффективной, более продуктивной, более слаженной и более веселой, потому что Тим был в команде.

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

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

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

Источник: https://dannorth.net/2023/09/02/the-worst-programmer/
Автор оригинала: Дэн Норт
👍35
День 1691. #ЧтоНовенького
Обновление Visual Studio без Прав Администратора
В мире ИТ администраторам и организациям крайне важно эффективно управлять безопасностью и применять передовые методы обеспечения безопасности. Одна из распространённых практик предполагает внедрение соответствующих уровней разрешений, чтобы гарантировать, что только авторизованные учётные записи могут получить доступ к конфиденциальным данным и функциям. Ещё один полезный совет – регулярные обновления ПО с последними обновлениями безопасности.

До сих пор установщик Visual Studio требовал прав администратора, поскольку ему необходимо записывать в «защищённые» области Windows. Однако если у пользователя, запускающего установщик, нет необходимых повышенных разрешений, ему запрещалось использовать функции установщика для обновления или изменения Visual Studio. Таким образом во многих организациях разработчик с привилегиями обычного пользователя не мог получить обновления продукта.

Теперь обычные пользователи теперь могут обновлять и изменять Visual Studio, начиная с версии 17.7. Стандартным пользователям может быть предоставлена возможность полноценно использовать установщик для получения обновлений и внесения изменений в Visual Studio. Администратор должен явно делегировать управление обычному пользователю и включить эту функцию, выполнив два простых шага на клиентском компьютере:
1. Выполнить первоначальную установку. Для первого получения установщика на любом клиентском компьютере всегда требуются права администратора.
2. Настроить политику AllowStandardUserControl. Для настройки политик Visual Studio также потребуются права администратора.

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

Другие функции управления безопасностью
Visual Studio значительно упростила для корпоративных администраторов соблюдение общих рекомендаций по обеспечению безопасности. Например, недавно администраторы получили возможность легко настраивать политики Visual Studio и включать автоматические ежемесячные обновления безопасности администратора с помощью Microsoft Intune. Также во время обновления можно автоматически удалять компоненты, для которых прекратилась поддержка.

Источник: https://devblogs.microsoft.com/visualstudio/standard-user-update/
👍3
День 1692. #ЗаметкиНаПолях
Общее Хранилище или Долгоживущие Ветки Функций?
Эффективные стратегиях разработки ПО, часто делятся на два подхода: разработка на основе общего хранилища кода и долгоживущие ветки функций. Каждый имеет свои преимущества и проблемы, и знание того, какой подход выбрать, может существенно повлиять на успех вашего проекта.

Общее хранилище
Подход к разработке ПО, при котором разработчики часто интегрируют свои изменения кода в одну общую ветку, известную как trunk. Цель — выполнять небольшие инкрементные обновления, чтобы минимизировать конфликты слияния и оптимизировать конвейер разработки. Непрерывная интеграция (CI) часто является неотъемлемой частью этой стратегии, поскольку позволяет быстро обнаруживать и решать проблемы.

Плюсы:
- CI обеспечивает мгновенную обратную связь, что упрощает раннее выявление проблем.
- Слияние становится проще благодаря частым интеграциям.
- Частые слияния улучшают общение в команде.
- Функции можно развёртывать быстрее и чаще.
- Единый источник достоверной информации (общая ветка) упрощает настройку CI/CD.

Минусы:
- Без надежных автоматизированных тестов может быть рискованным. Важно знать, что каждое новое изменение не сломало что-то в системе.
- Значительные обновления может быть сложно реализовать поэтапно. Хотя, крупные изменения в качестве исключения могут быть выделены в отдельные ветки.
- Флаги функций могут добавить дополнительный уровень сложности. Условная логика добавляет хаоса, и после добавления функций необходимо приложить дополнительные усилия для удаления условных операторов.

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

*Термин «долгоживущий» даётся без какой-либо конкретной меры. Его «долголетие» зависит от того, насколько активна кодовая база. Важным фактором является количество изменений в основной ветке с момента открытия ветки функции, а не календарное время.

Плюсы:
- Разработчики могут работать над большими функциями, не затрагивая основную ветку.
- Основная ветка остается стабильной. Легче гарантировать, что только проверенный рабочий код будет разрешён для слияния с основной веткой.
- Идеально подходит для реализации значительных изменений.
- Функции можно выпускать массово, используя (ещё одну) ветку для релиза и объединяя несколько веток функций в ветку релиза. Особенно полезно для взаимозависимых функций.

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

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

Источник
👍7
День 1693. #ЧтоНовенького
Доступ к Закрытым Членам Класса без Рефлексии в .NET 8
Закрытые члены класса в C# создаются для того, чтобы к ним нельзя было получить доступ извне. Но если нельзя, а очень хочется… то в .NET 8 появился ещё один способ получить к ним доступ без использования рефлексии.

Рассмотрим следующий класс:
class Sample
{
// Конструкторы
private Sample() { }
private Sample(int value) { }

// Поле
private int field1 = 1;

// Статическое поле
private static int staticField = 2;

// Методы
private int Method(int value) => value;
private static int StaticMethod(int value) => value;
}

.NET 8 предоставляет новый атрибут [UnsafeAccessor]. Чтобы получить доступ к закрытому члену, вы можете объявить внешний (extern) метод с атрибутом [UnsafeAccessor], чтобы объявить метод доступа для закрытого члена. Реализация метода, аннотированного этим атрибутом, будет предоставлена средой выполнения на основе информации в атрибуте и сигнатуры метода, к которому применяется атрибут. Обратите внимание, что UnsafeAccessor менее функционален, чем рефлексия. Например, вы не можете получить доступ к свойствам, а также обобщённые типы пока не полностью поддерживаются.

Конструкторы
var sample1 = CallConstructor();
var sample2 = CallConstructorWithArg(1);

// Возвращаемый тип метода должен быть типом класса
[UnsafeAccessor(
UnsafeAccessorKind.Constructor)]
extern static Sample CallConstructor();

[UnsafeAccessor(
UnsafeAccessorKind.Constructor)]
extern static Sample CallConstructorWithArg(int value);

Методы
var sample = CallConstructor();
Console.WriteLine(Method(sample, 1));

// Первый аргумент – экземпляр класса
[UnsafeAccessor(
UnsafeAccessorKind.Method,
Name = "Method")]
extern static int
Method(Sample @this, int value);

В статических методах так же. Несмотря на то, что экземпляр не требуется, среда выполнения должна знать тип:
Console.WriteLine(StaticMethod(null, 2));

[UnsafeAccessor(
UnsafeAccessorKind.StaticMethod,
Name = "StaticMethod")]
extern static int StaticMethod(Sample @this, int value);

Поля
Используем "ref", чтобы получить ссылку на поле для чтения и записи в него:
[UnsafeAccessor(UnsafeAccessorKind.Field, 
Name = "field1")]
extern static ref int
GetField(Sample @this);

var sample = CallConstructor();
_ = GetField(sample);
GetField(sample) = 42;

В readonly поля также возможна запись, как и при использовании рефлексии.

Аналогично со статическими полями. Как и для статических методов, необходим аргумент с типом класса:
[UnsafeAccessor(
UnsafeAccessorKind.StaticField,
Name = "staticField")]
extern static ref int
GetStaticField(Sample @this);

_ = GetStaticField(sample);

Вы можете записывать в static readonly поля, но с осторожностью. Эти поля очень похожи на константы для JIT. Поэтому запись значения в них может приводить к непредсказуемому поведению, т.к. значение может не читаться повторно в дальнейшем. Заметьте, что это невозможно при использовании рефлексии.

Помните, что имя атрибута начинается с "Unsafe", потому что позволяет делать небезопасные вещи.

Источник: https://www.meziantou.net/accessing-private-members-without-reflection-in-csharp.htm
👍11
День 1694.
DotNext 2023
Посетил конференцию DotNext 2023. Это мой первый опыт офлайн конференции. Вот некоторые фотки оттуда. Доклады выбирал по степени полезности для текущей работы, поэтому некоторые хотел, но не посетил, обязательно посмотрю в записи.

Были и другие активности. Великолепно неформально с Антоном Оникийчуком и Юлией Цисык про найм в .NET. Чего ждут работодатели, случаи были на собеседовании, красные флаги для компаний и для кандидатов и о многом другом. Множество шуток, баек и полезной информации. К концу 3го часа Антон с Юлей взмолились отпустить их домой :)

PVS-Studio предлагали задачки на поиск ошибок (я молодец, заслужил пряник – реальный тульский пряник). Positive Technologies - найти уязвимости в примерах кода. А также можно было поиграть на старых консольках, пособирать деревянные паззлы или потыкать механические клавиатуры.

В общем, если у вас будет возможность, советую посещать конференции офлайн. А ещё лучше там выступить, в DotNext уже принимают заявки.
👍46👎1
День 1695.
Значения Задержек, Которые Должен Знать Каждый Программист
Сегодня темя для любителей оптимизации и быстродействия. Подсмотрел её на одном из докладов DotNext и решил поделиться.

Сразу несколько замечаний:
1. Числа не стоит воспринимать как абсолютные, важно не конкретное значение, а порядок.
2. Со временем числа естественно меняются в сторону уменьшения, поэтому периодически их нужно перепроверять. Например, проследить за динамикой изменения за последние 30 лет можно здесь.

Итак,
Обращение к кэшу L1 – 1ns
Ошибка при предсказании условного перехода – 3ns
Обращение к кэшу L2 – 4ns
Открытие/закрытие мьютекса – 17ns
Обращение к главной памяти – 100ns
Сжатие 1Кб быстрым алгоритмом Snappy – 2μs
Чтение 1Мб последовательно из памяти – 2μs
Произвольный доступ к SSD – 16μs
Пересылка 2Кб по сети со скоростью 1Гб/с – 20μs
Чтение 1Мб последовательно с SSD – 49μs
Передача сообщения туда/обратно в одном дата-центре – 500μs
Чтение 1Мб последовательно с HDD – 825μs
Произвольный доступ к HDD – 2ms
Передача пакета между континентами и обратно – 150ms

Здесь:
1ns (наносекунда) = 10^-9 секунды
1μs (микросекунда) = 10^-6 секунды = 1000ns
1ms (миллисекунда) = 10^-3 секунды = 1000μs = 1000000ns

Таким образом, можно прочитать:
- последовательно с жесткого диска со скоростью ~200Мб/с.
- последовательно с SSD со скоростью ~1Гб/с (3-7Гб/с для NVME).
- последовательно из основной памяти со скоростью ~100Гб/с (пакетная скорость)
- последовательно из Ethernet 10Гбит/с со скоростью ~1000Мб/с.
Между Европой и Америкой возможно не более 6-7 рейсов туда/обратно в секунду, но в центре обработки данных можно достичь примерно 2000 в секунду.

Пример
Какая будет общая задержка получения 30 изображений по 256Кб с одного сервера?

Упрощённое решение: вся работа делается одним сервером, где чтение с диска превалирует над остальными операциями.

Время на чтение одного изображения с SSD:
(256Кб / 1Мб) * 49μs + 16μs доступ = 28.25μs
Среднее время генерации результата:
30 чтений * 28.25μs = 847.5μs

Таким образом, один сервер с SSD может выдать 1000000μs / 847.5μs ~ 1179 страниц результатов в секунду.
👍28
День 1696. #Карьера
Что Мы Имеем в Виду, Когда Говорим о Синдроме Самозванца
Синдром самозванца — сомнение в своих способностях до такой степени, что вы чувствуете себя мошенником — является вечной темой разговоров среди разработчиков.

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

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

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

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

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

«Это как программировать в темноте»
Доктор Кэт Хикс, директор Developer Success Lab в Pluralsight, провела исследование, в котором дала 25 авторам кода исследовать и отладить чужую кодовую базу, а потом провела с ними подробное интервью. Выяснилось, что испытуемые не ценили усилия коллег по написанию кода и в реальности считали проверку чужого кода непродуктивной работой. Это усугублялось тем, что боязнь «не выглядеть как инженер» провоцировала их меньше делиться с коллегами результатами своего труда. В итоге авторы кода часто выражали острое одиночество, даже в многочисленных командах. Доктор Хикс назвала это «программированием в темноте». Это одиночество и изоляция могут усугубить чувство самозванства на работе. А страх не выглядеть инженером легко интерпретируется как синдром самозванца.

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

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

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

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

Источник: https://stackoverflow.blog/2023/09/11/what-we-talk-about-when-we-talk-about-imposter-syndrome/
👍15