День 1980. #ЗаметкиНаПолях
ReadOnly-Коллекция не Является Неизменяемой
Коллекция «только для чтения» не означает, что она не изменяема. Сегодня посмотрим, как можно изменить ReadOnlyCollection.
ReadOnlyCollection, которая существует со времен .NET Framework 2.0, — это хороший способ сообщить: «Вот коллекция, которую вы не можете изменить». С точки зрения реализации это всего лишь оболочка поверх коллекции, которая запрещает такие операции, как добавление, удаление или очистку. Но это не означает, что её элементы не могут изменяться.
ReadOnlyCollection не является неизменяемым представлением, это, по сути, просто представление коллекции или списка. Тем не менее, если исходный список изменится, изменится и ReadOnlyCollection:
Вывод довольно очевиден:
Но что, если мы добавим элемент в исходный список?
Получим:
Как и представление в базе данных, наше представление списка «только для чтения» обновляется. Это плохо? Нет, потому что имеет некоторые преимущества. Самое главное - базовая операция по созданию ReadOnlyCollection очень дёшева. Она занимает O(1) времени, поскольку аллокации памяти не требуется.
Если мы хотим иметь реальную неизменяемость, нужно использовать другие типы, например, ImmutableList. Если мы проведём тот же тест, что и выше, мы получим то, что ожидаем от неизменяемого типа:
Вывод:
Мы видим, что длина остаётся прежней. Недостаток очевиден: нам нужно скопировать все элементы из исходного списка в неизменяемый список за O(n).
Итого
ReadOnly-коллекции не являются неизменяемыми. Это просто представление коллекции, доступное только для чтения. Вы как потребитель не можете их изменить, но это не значит, что изначальный создатель/владелец списка не может этого сделать. Если вам действительно нужно текущее состояние, которое не может измениться, используйте ImmutableArray/ImmutableList или Frozen-коллекции.
Источник: https://steven-giesel.com/blogPost/c20eb758-a611-4f98-9ddf-b9e2b83fcac9/readonlycollection-is-not-an-immutable-collection
ReadOnly-Коллекция не Является Неизменяемой
Коллекция «только для чтения» не означает, что она не изменяема. Сегодня посмотрим, как можно изменить ReadOnlyCollection.
ReadOnlyCollection, которая существует со времен .NET Framework 2.0, — это хороший способ сообщить: «Вот коллекция, которую вы не можете изменить». С точки зрения реализации это всего лишь оболочка поверх коллекции, которая запрещает такие операции, как добавление, удаление или очистку. Но это не означает, что её элементы не могут изменяться.
ReadOnlyCollection не является неизменяемым представлением, это, по сути, просто представление коллекции или списка. Тем не менее, если исходный список изменится, изменится и ReadOnlyCollection:
var numbers = new List<int> { 1, 2 };
var asReadOnly = numbers.AsReadOnly();
var readOnly = new ReadOnlyCollection<int>(numbers);
Console.WriteLine($"List: {numbers.Count}");
Console.WriteLine($"AsReadOnly: {asReadOnly.Count}");
Console.WriteLine($"ReadOnly: {readOnly.Count}");
Вывод довольно очевиден:
List: 2
AsReadOnly: 2
ReadOnly: 2
Но что, если мы добавим элемент в исходный список?
numbers.Add(3);
Получим:
List: 3
AsReadOnly: 3
ReadOnly: 3
Как и представление в базе данных, наше представление списка «только для чтения» обновляется. Это плохо? Нет, потому что имеет некоторые преимущества. Самое главное - базовая операция по созданию ReadOnlyCollection очень дёшева. Она занимает O(1) времени, поскольку аллокации памяти не требуется.
Если мы хотим иметь реальную неизменяемость, нужно использовать другие типы, например, ImmutableList. Если мы проведём тот же тест, что и выше, мы получим то, что ожидаем от неизменяемого типа:
var immutable = numbers.ToImmutableList();
Console.WriteLine($"List: {numbers.Count}");
Console.WriteLine($"Immutable: {immutable.Count}");
numbers.Add(4);
Console.WriteLine($"List: {numbers.Count}");
Console.WriteLine($"Immutable: {immutable.Count}");
Вывод:
List: 3
Immutable: 3
List: 4
Immutable: 3
Мы видим, что длина остаётся прежней. Недостаток очевиден: нам нужно скопировать все элементы из исходного списка в неизменяемый список за O(n).
Итого
ReadOnly-коллекции не являются неизменяемыми. Это просто представление коллекции, доступное только для чтения. Вы как потребитель не можете их изменить, но это не значит, что изначальный создатель/владелец списка не может этого сделать. Если вам действительно нужно текущее состояние, которое не может измениться, используйте ImmutableArray/ImmutableList или Frozen-коллекции.
Источник: https://steven-giesel.com/blogPost/c20eb758-a611-4f98-9ddf-b9e2b83fcac9/readonlycollection-is-not-an-immutable-collection
👍38
День 1981. #ProjectManagement
Настоящий 10х-Разработчик Делает Всю Команду Лучше
Все знакомы с концепцией 10х-инженера: «занудного, асоциального гения, который создаёт новаторские продукты почти случайно». Суперразработчик, который в десять раз умнее и продуктивнее своих коллег, о котором ходят мифы и на которого идут венчурные инвесторы.
Истина в том, что отдельные люди имеют меньшее значение для успеха или провала проекта, чем вы думаете (и это хорошо, иначе уровень выгорания будет зашкаливать). Гораздо важнее качество сообществ обучения, к которым имеют доступ ваши сотрудники. Вместо инженера, который на порядок «лучше» своих коллег, лидеры должны искать людей, которые хотят и способны учиться, а также помогать всей команде учиться и работать.
Успешные инженерные организации требуют сильной культуры общего обучения. Им нужен способ сбора и распространения знаний, одновременно обеспечивающий общение и сотрудничество между командами. Поэтому организациям нужно инвестировать в создание сообществ практиков вокруг своих продуктов, а также инструментов и технологий, которые они используют.
Сообщества практиков — это отдельные группы по интересам: язык программирования, кибербезопасность, ИИ и т.п. С точки зрения бизнеса, такие группы выполняют несколько функций: разрушают разрозненность и поощряют межфункциональное сотрудничество, укрепляя доверие и уверенность среди сотрудников, а также ускоряя инновации. Сообщества позволяют коллегам из разных команд обсуждать конкретные темы, делиться опытом и ресурсами, использовать коллективный опыт для решения проблем и совершенствования. Участники могут раскрыть важный контекст и установить связи, которые они, возможно, не установили бы сами.
Это требует времени и энергии сотрудников. Не отвлекает ли это их от основных должностных обязанностей?
Формирование культуры общего обучения является одной из их основных должностных обязанностей. Это улучшает результаты и отдельных разработчиков, и команд. Сообщества практиков поощряют разработчиков делиться своими ошибками и тем, чему они научились на их основе, чтобы всё сообщество могло извлечь пользу из этих знаний. Это возможность учиться на работе. Недавний опрос Stack Overflow показал, что для половины разработчиков доступ к возможностям обучения способствует их счастью на работе.
Вот некоторые конкретные способы, с помощью которых разработчики (и их менеджеры) могут построить культуру общего обучения:
- Если вы менеджер или старший сотрудник, подавайте пример, уделяя приоритетное внимание собственному обучению. Как бы вы ни были заняты, старайтесь уделять регулярное время изучению и отработке новых навыков. Сообщайте подчинённым, что вы делали и что вы узнали, чтобы они осознали, что постоянное обучение приветствуется в организации.
- Убедитесь, что сотрудники уделяют время обучению. Предоставьте командам возможность выделять время для обучения. Иначе им придётся посвящать личное время обучению, а не делать обучение неотъемлемой частью вашей организационной культуры и повседневной работы.
- Делитесь ошибками с коллегами. Любая ошибка — это возможность учиться — не только для того, кто допустил ошибку, но и для остальных участников проекта. А когда старшие разработчики и менеджеры бесстрашно признают свои ошибки, перспектива становится менее пугающей для младших разработчиков.
- Предоставьте учебные ресурсы. Это ключ к развитию культуры обучения.
Блестящие, одаренные люди играют важную роль в командах разработчиков, но ожидать, что кто-то будет 10х-разработчиком — или ожидать этого от себя — контрпродуктивно. Заставить себя ускориться в 10 раз — надёжный рецепт выгорания. Сообщества практиков, основанные на культуре общего обучения, приводят к созданию высокопроизводительных команд, не возлагая всю ответственность на одного мифического 10х-разработчика.
Источник: https://stackoverflow.blog/2024/06/19/the-real-10x-developer-makes-their-whole-team-better/
Настоящий 10х-Разработчик Делает Всю Команду Лучше
Все знакомы с концепцией 10х-инженера: «занудного, асоциального гения, который создаёт новаторские продукты почти случайно». Суперразработчик, который в десять раз умнее и продуктивнее своих коллег, о котором ходят мифы и на которого идут венчурные инвесторы.
Истина в том, что отдельные люди имеют меньшее значение для успеха или провала проекта, чем вы думаете (и это хорошо, иначе уровень выгорания будет зашкаливать). Гораздо важнее качество сообществ обучения, к которым имеют доступ ваши сотрудники. Вместо инженера, который на порядок «лучше» своих коллег, лидеры должны искать людей, которые хотят и способны учиться, а также помогать всей команде учиться и работать.
Успешные инженерные организации требуют сильной культуры общего обучения. Им нужен способ сбора и распространения знаний, одновременно обеспечивающий общение и сотрудничество между командами. Поэтому организациям нужно инвестировать в создание сообществ практиков вокруг своих продуктов, а также инструментов и технологий, которые они используют.
Сообщества практиков — это отдельные группы по интересам: язык программирования, кибербезопасность, ИИ и т.п. С точки зрения бизнеса, такие группы выполняют несколько функций: разрушают разрозненность и поощряют межфункциональное сотрудничество, укрепляя доверие и уверенность среди сотрудников, а также ускоряя инновации. Сообщества позволяют коллегам из разных команд обсуждать конкретные темы, делиться опытом и ресурсами, использовать коллективный опыт для решения проблем и совершенствования. Участники могут раскрыть важный контекст и установить связи, которые они, возможно, не установили бы сами.
Это требует времени и энергии сотрудников. Не отвлекает ли это их от основных должностных обязанностей?
Формирование культуры общего обучения является одной из их основных должностных обязанностей. Это улучшает результаты и отдельных разработчиков, и команд. Сообщества практиков поощряют разработчиков делиться своими ошибками и тем, чему они научились на их основе, чтобы всё сообщество могло извлечь пользу из этих знаний. Это возможность учиться на работе. Недавний опрос Stack Overflow показал, что для половины разработчиков доступ к возможностям обучения способствует их счастью на работе.
Вот некоторые конкретные способы, с помощью которых разработчики (и их менеджеры) могут построить культуру общего обучения:
- Если вы менеджер или старший сотрудник, подавайте пример, уделяя приоритетное внимание собственному обучению. Как бы вы ни были заняты, старайтесь уделять регулярное время изучению и отработке новых навыков. Сообщайте подчинённым, что вы делали и что вы узнали, чтобы они осознали, что постоянное обучение приветствуется в организации.
- Убедитесь, что сотрудники уделяют время обучению. Предоставьте командам возможность выделять время для обучения. Иначе им придётся посвящать личное время обучению, а не делать обучение неотъемлемой частью вашей организационной культуры и повседневной работы.
- Делитесь ошибками с коллегами. Любая ошибка — это возможность учиться — не только для того, кто допустил ошибку, но и для остальных участников проекта. А когда старшие разработчики и менеджеры бесстрашно признают свои ошибки, перспектива становится менее пугающей для младших разработчиков.
- Предоставьте учебные ресурсы. Это ключ к развитию культуры обучения.
Блестящие, одаренные люди играют важную роль в командах разработчиков, но ожидать, что кто-то будет 10х-разработчиком — или ожидать этого от себя — контрпродуктивно. Заставить себя ускориться в 10 раз — надёжный рецепт выгорания. Сообщества практиков, основанные на культуре общего обучения, приводят к созданию высокопроизводительных команд, не возлагая всю ответственность на одного мифического 10х-разработчика.
Источник: https://stackoverflow.blog/2024/06/19/the-real-10x-developer-makes-their-whole-team-better/
👍16👎1
День 1982. #ЧтоНовенького #CSharp13
ReadOnlySet<T> в .NET 9
Очередная, шестая, превью версия .NET 9 представит новый тип ReadOnlySet<T>. Это множество только для чтения, аналогичное ReadOnlyCollection<T>. Посмотрим, как это работает и зачем оно добавлено.
IReadOnlySet недостаточно
У нас уже есть интерфейс IReadOnlySet<T>. Например, его реализует FrozenSet. Почему его недостаточно? Рассмотрим List<T> и IReadOnlyList<T>, которые страдают от той же проблемы:
Вывод (внезапно):
Конечно, потребителям вашего API не следует этого делать, но вы не можете этого предотвратить. Вот почему у нас есть AsReadOnly:
AsReadOnly возвращает ReadOnlyCollection<T>, поэтому приведение её к изменяемому списку невозможно.
Той же проблемой страдает и IReadOnlySet<T>. Именно для этого создан ReadOnlySet<T>:
Неправильный обходной путь
Если попытаться реализовать собственный способ создания множества только для чтения, пришлось бы создать что-то вроде ImmutableHashSet<T> или FrozenSet.
Хотя технически это работает, у этого две основные проблемы:
1. Неизменяемые коллекции, такие как ImmutableHashSet<T> или FrozenSet, должны cкопировать всю коллекцию в свою память, чтобы гарантировать неизменяемость. Это может быть пустой тратой памяти и циклов процессора.
2. Это не совсем множество только для чтения. «Только для чтения» и «неизменяемый» — это два разных понятия, как мы разобрали недавно.
Подробнее о предложении новинки тут.
Источник: https://steven-giesel.com/blogPost/f368c7d3-488e-4bea-92b4-abf176353fa3/readonlysett-in-net-9
ReadOnlySet<T> в .NET 9
Очередная, шестая, превью версия .NET 9 представит новый тип ReadOnlySet<T>. Это множество только для чтения, аналогичное ReadOnlyCollection<T>. Посмотрим, как это работает и зачем оно добавлено.
IReadOnlySet недостаточно
У нас уже есть интерфейс IReadOnlySet<T>. Например, его реализует FrozenSet. Почему его недостаточно? Рассмотрим List<T> и IReadOnlyList<T>, которые страдают от той же проблемы:
var list = new List<int> { 1, 2, 3 };
IReadOnlyList<int> readOnlyList = list;
// Вы можете привести это обратно к List<T> и изменить
var list2 = (List<int>)readOnlyList;
list2.Add(4);
Console.WriteLine($"List: {list.Count}");
Console.WriteLine($"ReadOnlyList: {readOnlyList.Count}");
Console.WriteLine($"List2: {list2.Count}");
Вывод (внезапно):
List: 4
ReadOnlyList: 4
List2: 4
Конечно, потребителям вашего API не следует этого делать, но вы не можете этого предотвратить. Вот почему у нас есть AsReadOnly:
List<int> list = [1, 2, 3];
var readOnlyList = list.AsReadOnly();
// Вы не можете привести это к List<T>
var list2 = (List<int>)readOnlyList; // Исключение
AsReadOnly возвращает ReadOnlyCollection<T>, поэтому приведение её к изменяемому списку невозможно.
Той же проблемой страдает и IReadOnlySet<T>. Именно для этого создан ReadOnlySet<T>:
var set = new HashSet<int> { 1, 2, 3 };
var readonlySet = new ReadOnlySet<int>(set);
Неправильный обходной путь
Если попытаться реализовать собственный способ создания множества только для чтения, пришлось бы создать что-то вроде ImmutableHashSet<T> или FrozenSet.
var set = new HashSet<int> { 1, 2, 3 };
var readOnly = set.ToFrozenSet(); // или ToImmutableHashSet()
Хотя технически это работает, у этого две основные проблемы:
1. Неизменяемые коллекции, такие как ImmutableHashSet<T> или FrozenSet, должны cкопировать всю коллекцию в свою память, чтобы гарантировать неизменяемость. Это может быть пустой тратой памяти и циклов процессора.
2. Это не совсем множество только для чтения. «Только для чтения» и «неизменяемый» — это два разных понятия, как мы разобрали недавно.
Подробнее о предложении новинки тут.
Источник: https://steven-giesel.com/blogPost/f368c7d3-488e-4bea-92b4-abf176353fa3/readonlysett-in-net-9
👍11
День 1983. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 14. Большая группа людей не способна организованно покинуть горящую комнату, не говоря уж о том, чтобы сформулировать требование
Большой группе людей трудно договариваться и принимать решения. Участники легко отвлекаются на посторонние разговоры. В большой группе всегда найдётся несколько человек, которым будет что сказать по теме, что приведёт к более длительному, но не всегда плодотворному обсуждению. Разногласия могут перерасти в продолжительные споры. Одни участники могут доминировать в обсуждении, а другие — полностью отключиться.
Не нужно приглашать шестерых представителей пользователей, достаточно двух или трёх. Также важно привлекать к обсуждению людей с опытом разработки и тестирования ПО, так как они имеют представление о выполнимости и возможности проверки предлагаемых требований.
Следуя стратегии ограничения численности групп, можно проводить отдельные семинары для представителей разных классов пользователей. Их требования часто различаются. Если собрать всех вместе, то любая возникающая тема будет интересна только части группы. Остальные могут заскучать и посчитать, что зря тратят время. Отдельные семинары с разными группами пользователей ведут к заинтересованности всех участников. Однако разумное объединение членов разных групп может создать эффект синергии и помочь выявить связи, вопросы и инновации, которые ни одна из групп не могла бы придумать независимо.
Координация
Иногда она осуществляется специально: кто-то берет на себя инициативу, встаёт у доски с маркером в руке и блюдёт порядок. Это может быть бизнес-аналитик или же беспристрастный внешний координатор. Он должен заранее ознакомиться с целями и повесткой семинара. Ограничение по времени также способствует более быстрому обсуждению. Координатор может решить продолжить обсуждение дольше запланированного, если это приведет к получению дополнительной ценности. Кроме того, он решает, когда уместно углубиться в детали, а когда лучше перейти к следующей теме.
Фокус
Координатор должен сначала рассмотреть горизонтальный охват — часть требований пользователей, которые группа должна обсудить на конкретном семинаре. Противоположность - вертикальный охват — глубина исследования выбранных элементов. Семинары не предназначены для выявления всех деталей каждого требования. Достаточно узнать о требованиях ровно столько, чтобы команда могла оценить их размеры и определить порядок реализации. Уделите достаточно времени обсуждению формулировок, чтобы все участники поняли суть каждого требования. Детали бизнес-аналитик обсудит отдельно с разными пользователями, например непосредственно перед реализацией требования.
Координатор должен уважать мнение участников и позволять всем быть услышанными. Если кто-то поднимает вопрос, выходящий за рамки обсуждения, координатор должен записать идею, чтобы запланировать её обсуждение в будущем, и вернуться к рассматриваемой теме.
Не ограничивайтесь обсуждениями в группах
Цель ограничения численности группы не исключить вклад других, а ускорить прогресс. Чтобы заполнить пробелы, используйте другие методы, например, обсуждение на форумах. Вовлечение других заинтересованных сторон в процесс поможет расширить знания, подтвердить результаты семинара, информировать сообщество о направлении проекта и обеспечить их участие.
Кто-то должен разрешать конфликты между требованиями. Противоречивой может быть даже терминология. Кто-то также должен согласовать приоритеты требований, полученных от разных групп пользователей, и решить, какие изменения принять. Проведение семинаров — эффективный способ совместного изучения требований. Он позволяет бизнес-аналитику привести команду представителей заинтересованных сторон к общему пониманию требований и их решений. Небольшие группы продвигаются к цели гораздо быстрее. И они всегда смогут договориться о том, какой пожарный выход использовать в случае необходимости.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 14. Большая группа людей не способна организованно покинуть горящую комнату, не говоря уж о том, чтобы сформулировать требование
Большой группе людей трудно договариваться и принимать решения. Участники легко отвлекаются на посторонние разговоры. В большой группе всегда найдётся несколько человек, которым будет что сказать по теме, что приведёт к более длительному, но не всегда плодотворному обсуждению. Разногласия могут перерасти в продолжительные споры. Одни участники могут доминировать в обсуждении, а другие — полностью отключиться.
Не нужно приглашать шестерых представителей пользователей, достаточно двух или трёх. Также важно привлекать к обсуждению людей с опытом разработки и тестирования ПО, так как они имеют представление о выполнимости и возможности проверки предлагаемых требований.
Следуя стратегии ограничения численности групп, можно проводить отдельные семинары для представителей разных классов пользователей. Их требования часто различаются. Если собрать всех вместе, то любая возникающая тема будет интересна только части группы. Остальные могут заскучать и посчитать, что зря тратят время. Отдельные семинары с разными группами пользователей ведут к заинтересованности всех участников. Однако разумное объединение членов разных групп может создать эффект синергии и помочь выявить связи, вопросы и инновации, которые ни одна из групп не могла бы придумать независимо.
Координация
Иногда она осуществляется специально: кто-то берет на себя инициативу, встаёт у доски с маркером в руке и блюдёт порядок. Это может быть бизнес-аналитик или же беспристрастный внешний координатор. Он должен заранее ознакомиться с целями и повесткой семинара. Ограничение по времени также способствует более быстрому обсуждению. Координатор может решить продолжить обсуждение дольше запланированного, если это приведет к получению дополнительной ценности. Кроме того, он решает, когда уместно углубиться в детали, а когда лучше перейти к следующей теме.
Фокус
Координатор должен сначала рассмотреть горизонтальный охват — часть требований пользователей, которые группа должна обсудить на конкретном семинаре. Противоположность - вертикальный охват — глубина исследования выбранных элементов. Семинары не предназначены для выявления всех деталей каждого требования. Достаточно узнать о требованиях ровно столько, чтобы команда могла оценить их размеры и определить порядок реализации. Уделите достаточно времени обсуждению формулировок, чтобы все участники поняли суть каждого требования. Детали бизнес-аналитик обсудит отдельно с разными пользователями, например непосредственно перед реализацией требования.
Координатор должен уважать мнение участников и позволять всем быть услышанными. Если кто-то поднимает вопрос, выходящий за рамки обсуждения, координатор должен записать идею, чтобы запланировать её обсуждение в будущем, и вернуться к рассматриваемой теме.
Не ограничивайтесь обсуждениями в группах
Цель ограничения численности группы не исключить вклад других, а ускорить прогресс. Чтобы заполнить пробелы, используйте другие методы, например, обсуждение на форумах. Вовлечение других заинтересованных сторон в процесс поможет расширить знания, подтвердить результаты семинара, информировать сообщество о направлении проекта и обеспечить их участие.
Кто-то должен разрешать конфликты между требованиями. Противоречивой может быть даже терминология. Кто-то также должен согласовать приоритеты требований, полученных от разных групп пользователей, и решить, какие изменения принять. Проведение семинаров — эффективный способ совместного изучения требований. Он позволяет бизнес-аналитику привести команду представителей заинтересованных сторон к общему пониманию требований и их решений. Небольшие группы продвигаются к цели гораздо быстрее. И они всегда смогут договориться о том, какой пожарный выход использовать в случае необходимости.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍3
День 1984. #Оффтоп
Сравнение WebAssembly и JavaScript
WebAssembly (Wasm) и JavaScript — две ключевые технологии в современной веб-разработке, каждая имеет свои сильные стороны и области применения.
Производительность
Wasm обычно превосходит JS в быстродействии благодаря двоичному формату, который обеспечивает скорость выполнения, близкую к нативному коду, что делает его особенно выгодным для ресурсоемких задач, таких как обработка данных и рендеринг игр. Однако Wasm предназначен для дополнения, а не замены JS. JS остаётся доминирующим языком веб-разработки благодаря простоте использования, гибкости и обширной экосистеме, а Wasm используется для задач, требующих повышенной производительности.
Портативность и совместимость
И Wasm, и JS хорошо переносимы и работают во всех основных браузерах и платформах. Wasm поддерживает несколько языков программирования: C, C++, C#, Rust и т.д., - компилируются в Wasm и запускаются в сети. Это открывает двери для большего числа разработчиков и позволяет повторно использовать код из других сред.
JS же пользуется универсальной поддержкой и может похвастаться огромной экосистемой фреймворков и библиотек, что делает его стандартным для большинства веб-проектов.
Простота использования
Низкая кривая обучения и динамическая типизация делают JS удобным для новичков. Обширная документация, активное сообщество, множество инструментов и фреймворков упрощают разработку.
Wasm мощный, но более сложный. Требует знания одного из поддерживаемых языков и понимания процесса компиляции. Его экосистема все ещё развивается и предлагает меньше ресурсов, чем JS.
Безопасность
И Wasm, и JS работают в изолированных средах, защищая хост-систему. Динамическая природа JS делают его уязвимым для таких атак, как межсайтовый скриптинг (XSS), если не обрабатывать пользовательский ввод должным образом. Бинарный формат Wasm делают его более устойчивым к определённым атакам на внедрение кода. Но всё же использование лучших практик каждого языка критично для обеспечения безопасности.
Принятие и использование
В 2024 Wasm растёт на 23% по сравнению с 2023. Такие отрасли, как игры, финансы и здравоохранение, используют Wasm для создания высокопроизводительных веб-приложений, требующих обработки в реальном времени.
JS остается основой веб-разработки: его регулярно используют более 60% разработчиков. Универсальность и обширная экосистема делают его незаменимым для широкого спектра применений.
Инновации и обновления
Системный интерфейс WebAssembly (WASI) упрощает запуск Wasm вне браузера, открывая новые варианты использования, такие как серверные приложения и устройства IoT. Модель компонентов Wasm также была улучшена, что сделало модульность и повторное использование модулей Wasm более эффективными.
JS продолжает развиваться благодаря новым предложениям ECMAScript. В 2024 стандартизированы улучшенное сопоставление по шаблону, улучшенные возможности асинхронного программирования и модульность.
Инструменты и фреймворки
Такие проекты, как Wasmtime и Wasmer, упростили запуск Wasm на серверах. Bytecode Alliance активно разрабатывает новые библиотеки и инструменты.
Фреймворки JS, такие как React, Vue и Angular, продолжают улучшаться, их обновления ориентированы на производительность, опыт разработчиков и интеграцию современных веб-стандартов.
Реальные истории успеха
AutoDesk использовала Wasm для повышения производительности своих инструментов. Финансовые учреждения используют Wasm для сложных расчётов в реальном времени.
Такие компании, как Airbnb и Netflix, используют JS для создания удобных интерактивных интерфейсов. Универсальность JS позволяет этим компаниям быстро внедрять новые функции.
Источник: https://www.sitepoint.com/webassembly-javascript-comparison/
Сравнение WebAssembly и JavaScript
WebAssembly (Wasm) и JavaScript — две ключевые технологии в современной веб-разработке, каждая имеет свои сильные стороны и области применения.
Производительность
Wasm обычно превосходит JS в быстродействии благодаря двоичному формату, который обеспечивает скорость выполнения, близкую к нативному коду, что делает его особенно выгодным для ресурсоемких задач, таких как обработка данных и рендеринг игр. Однако Wasm предназначен для дополнения, а не замены JS. JS остаётся доминирующим языком веб-разработки благодаря простоте использования, гибкости и обширной экосистеме, а Wasm используется для задач, требующих повышенной производительности.
Портативность и совместимость
И Wasm, и JS хорошо переносимы и работают во всех основных браузерах и платформах. Wasm поддерживает несколько языков программирования: C, C++, C#, Rust и т.д., - компилируются в Wasm и запускаются в сети. Это открывает двери для большего числа разработчиков и позволяет повторно использовать код из других сред.
JS же пользуется универсальной поддержкой и может похвастаться огромной экосистемой фреймворков и библиотек, что делает его стандартным для большинства веб-проектов.
Простота использования
Низкая кривая обучения и динамическая типизация делают JS удобным для новичков. Обширная документация, активное сообщество, множество инструментов и фреймворков упрощают разработку.
Wasm мощный, но более сложный. Требует знания одного из поддерживаемых языков и понимания процесса компиляции. Его экосистема все ещё развивается и предлагает меньше ресурсов, чем JS.
Безопасность
И Wasm, и JS работают в изолированных средах, защищая хост-систему. Динамическая природа JS делают его уязвимым для таких атак, как межсайтовый скриптинг (XSS), если не обрабатывать пользовательский ввод должным образом. Бинарный формат Wasm делают его более устойчивым к определённым атакам на внедрение кода. Но всё же использование лучших практик каждого языка критично для обеспечения безопасности.
Принятие и использование
В 2024 Wasm растёт на 23% по сравнению с 2023. Такие отрасли, как игры, финансы и здравоохранение, используют Wasm для создания высокопроизводительных веб-приложений, требующих обработки в реальном времени.
JS остается основой веб-разработки: его регулярно используют более 60% разработчиков. Универсальность и обширная экосистема делают его незаменимым для широкого спектра применений.
Инновации и обновления
Системный интерфейс WebAssembly (WASI) упрощает запуск Wasm вне браузера, открывая новые варианты использования, такие как серверные приложения и устройства IoT. Модель компонентов Wasm также была улучшена, что сделало модульность и повторное использование модулей Wasm более эффективными.
JS продолжает развиваться благодаря новым предложениям ECMAScript. В 2024 стандартизированы улучшенное сопоставление по шаблону, улучшенные возможности асинхронного программирования и модульность.
Инструменты и фреймворки
Такие проекты, как Wasmtime и Wasmer, упростили запуск Wasm на серверах. Bytecode Alliance активно разрабатывает новые библиотеки и инструменты.
Фреймворки JS, такие как React, Vue и Angular, продолжают улучшаться, их обновления ориентированы на производительность, опыт разработчиков и интеграцию современных веб-стандартов.
Реальные истории успеха
AutoDesk использовала Wasm для повышения производительности своих инструментов. Финансовые учреждения используют Wasm для сложных расчётов в реальном времени.
Такие компании, как Airbnb и Netflix, используют JS для создания удобных интерактивных интерфейсов. Универсальность JS позволяет этим компаниям быстро внедрять новые функции.
Источник: https://www.sitepoint.com/webassembly-javascript-comparison/
👍10👎1
Anonymous Quiz
25%
IMemoryCache
33%
IDistributedCache
42%
Никакой
👍5
День 1985. #Карьера
Полезные и Игнорируемые Навыки
Есть полезный, но недооцененный навык: принимать определённую степень хлопот и абсурда, когда этого требует реальность.
Это не самый приятный навык, поэтому его недооценивают. Но вы понимаете, насколько он может быть полезен, когда замечаете кого-то, у кого этого нет. Человек изо всех сил пытается пережить день, расстраиваясь из-за малейших неприятностей. Как большой начальник сходит с ума после того, как в аэропорту дважды меняли выход на посадку. Как он продвинулся так далеко в жизни, не имея возможности справляться с мелкими неприятностями, находящимися вне его контроля? Наиболее вероятный ответ: отрицая то, что, по его мнению, он контролирует, и требуя нереальной точности от подчинённых, которые компенсируют это сокрытием плохих новостей.
Вот ещё несколько полезных и недооцененных навыков:
1. Ваше желание чтобы что-то было правдой, влияет на то, насколько правдивым вы это считаете.
Это заметно в инвестировании, когда огромные вознаграждения за угаданный исход коррелируют с непоколебимой верой людей в свою правоту. Идея о соразмерности вознаграждения способностям верна лишь отчасти. Когда вознаграждение становится достаточно высоким, умственные способности, которые обычно были бы направлены на разработку стратегии и расчёт, перегружены мечтами о награде. Отчасти поэтому люди тратят выходные на поиск нового телефона и 15 минут на выбор крупной инвестиции. Признание того, что огромные награды требуют дополнительного скептицизма в отношении ваших рассуждений, недооценено.
2. Уважительно общаться с людьми, с которыми вы не согласны.
Доверие к человеку выше, когда вы близки. Но вы столкнётесь с большим количеством людей, которые с вами не согласны. Чем больше Интернет знакомит людей с новыми точками зрения, тем больше людей раздражает существование других точек зрения. Способ открыть свой разум тем, с кем вы не согласны, состоит в том, чтобы найти тему, где ваши взгляды совпадают. Это ставит галочку в вашей голове: «Этот человек не совсем сумасшедший». И уже дальше обсуждайте темы, в которых вы не согласны. Без первого шага слишком легко списать человека со счетов, прежде чем вы услышите его аргументы.
3. Возможность поговорить 10 минут с кем угодно.
Технологии заменили многие личные разговоры. Сидеть с кем-то, кого вы никогда не встречали, смотреть ему в глаза и поддерживать разговор – то, что раньше было настолько обычным явлением, что не считалось навыком – теперь является конкурентным преимуществом.
4. Переходить к сути.
Все заняты. Выскажите свою точку зрения, используя как можно меньше слов, и более не мешайте.
5. Дипломатично говорить: «Нет».
«Нет» часто произносится двумя разрушительными способами. Во-первых, человеку неприятно говорить «нет», поэтому он тянет или говорит «да», откладывая неизбежное «нет». Так вы не держите слово, и другой человек будет разочарован больше, чем если бы вы сразу отказали. Другой вариант —непреднамеренное резкое «нет», из-за которого другой человек больше никогда не захочет привлекать ваше внимание к какой-либо идее или проблеме. Дипломатичное «нет» — это когда вы даёте однозначный ответ, но заботитесь о том, как собеседник может интерпретировать его.
6. Уважать удачу так же, как и риск.
На результаты могут влиять события, находящиеся вне вашего контроля. И удача, и риск происходят потому, что мир слишком сложен, чтобы позволить 100% ваших действий определять 100% ваших результатов. Но риск легко замечать, потому что он – приемлемая отмазка, когда что-то идёт не так. Удача – наоборот. Больно думать, что часть, а может и весь ваш успех не был вызван вашими действиями. Так удача преуменьшается и игнорируется в отличие от риска. Способность осознавать, что ваши победы могут не сигнализировать о том, что вы сделали что-то правильно, так же как ваши поражения могут не сигнализировать о том, что вы сделали что-то неправильно, жизненно важна для изучения чего-то ценного на основе обратной связи из реального мира.
Источник: https://collabfund.com/blog/useful-and-overlooked-skills/
Полезные и Игнорируемые Навыки
Есть полезный, но недооцененный навык: принимать определённую степень хлопот и абсурда, когда этого требует реальность.
Это не самый приятный навык, поэтому его недооценивают. Но вы понимаете, насколько он может быть полезен, когда замечаете кого-то, у кого этого нет. Человек изо всех сил пытается пережить день, расстраиваясь из-за малейших неприятностей. Как большой начальник сходит с ума после того, как в аэропорту дважды меняли выход на посадку. Как он продвинулся так далеко в жизни, не имея возможности справляться с мелкими неприятностями, находящимися вне его контроля? Наиболее вероятный ответ: отрицая то, что, по его мнению, он контролирует, и требуя нереальной точности от подчинённых, которые компенсируют это сокрытием плохих новостей.
Вот ещё несколько полезных и недооцененных навыков:
1. Ваше желание чтобы что-то было правдой, влияет на то, насколько правдивым вы это считаете.
Это заметно в инвестировании, когда огромные вознаграждения за угаданный исход коррелируют с непоколебимой верой людей в свою правоту. Идея о соразмерности вознаграждения способностям верна лишь отчасти. Когда вознаграждение становится достаточно высоким, умственные способности, которые обычно были бы направлены на разработку стратегии и расчёт, перегружены мечтами о награде. Отчасти поэтому люди тратят выходные на поиск нового телефона и 15 минут на выбор крупной инвестиции. Признание того, что огромные награды требуют дополнительного скептицизма в отношении ваших рассуждений, недооценено.
2. Уважительно общаться с людьми, с которыми вы не согласны.
Доверие к человеку выше, когда вы близки. Но вы столкнётесь с большим количеством людей, которые с вами не согласны. Чем больше Интернет знакомит людей с новыми точками зрения, тем больше людей раздражает существование других точек зрения. Способ открыть свой разум тем, с кем вы не согласны, состоит в том, чтобы найти тему, где ваши взгляды совпадают. Это ставит галочку в вашей голове: «Этот человек не совсем сумасшедший». И уже дальше обсуждайте темы, в которых вы не согласны. Без первого шага слишком легко списать человека со счетов, прежде чем вы услышите его аргументы.
3. Возможность поговорить 10 минут с кем угодно.
Технологии заменили многие личные разговоры. Сидеть с кем-то, кого вы никогда не встречали, смотреть ему в глаза и поддерживать разговор – то, что раньше было настолько обычным явлением, что не считалось навыком – теперь является конкурентным преимуществом.
4. Переходить к сути.
Все заняты. Выскажите свою точку зрения, используя как можно меньше слов, и более не мешайте.
5. Дипломатично говорить: «Нет».
«Нет» часто произносится двумя разрушительными способами. Во-первых, человеку неприятно говорить «нет», поэтому он тянет или говорит «да», откладывая неизбежное «нет». Так вы не держите слово, и другой человек будет разочарован больше, чем если бы вы сразу отказали. Другой вариант —непреднамеренное резкое «нет», из-за которого другой человек больше никогда не захочет привлекать ваше внимание к какой-либо идее или проблеме. Дипломатичное «нет» — это когда вы даёте однозначный ответ, но заботитесь о том, как собеседник может интерпретировать его.
6. Уважать удачу так же, как и риск.
На результаты могут влиять события, находящиеся вне вашего контроля. И удача, и риск происходят потому, что мир слишком сложен, чтобы позволить 100% ваших действий определять 100% ваших результатов. Но риск легко замечать, потому что он – приемлемая отмазка, когда что-то идёт не так. Удача – наоборот. Больно думать, что часть, а может и весь ваш успех не был вызван вашими действиями. Так удача преуменьшается и игнорируется в отличие от риска. Способность осознавать, что ваши победы могут не сигнализировать о том, что вы сделали что-то правильно, так же как ваши поражения могут не сигнализировать о том, что вы сделали что-то неправильно, жизненно важна для изучения чего-то ценного на основе обратной связи из реального мира.
Источник: https://collabfund.com/blog/useful-and-overlooked-skills/
👍16👎1
День 1986. #ЗаметкиНаПолях #Cancellation
Отмена. Часть 1: Обзор. Начало
Отмена — это тема, о которой возникает множество вопросов. И хотя документация Microsoft довольно хороша, в этой серии подробно рассмотрим эту тему.
Скоординированная отмена в .NET
Это означает, что одна часть кода запрашивает отмену, а другая часть кода отвечает на этот запрос. Мы часто говорим о том, что один код «отменяет» другой код, но на самом деле запрашивающий код просто вежливо уведомляет другой код о том, что он хотел бы его остановить, а отвечающий код может отреагировать на этот запрос на отмену любым способом. Отвечающий код может немедленно остановить то, что он делает, или продолжать работу до тех пор, пока не достигнет допустимой точки остановки, либо он может полностью игнорировать запрос на отмену.
Важный вывод: отвечающий код должен ответить на запрос отмены, чтобы отмена действительно что-то отменила.
Обычно возникает вопрос: как отменить неотменяемый код? Это сложный сценарий, рассмотрим его позже.
Токены отмены и «90% случаев»
В .NET токен отмены является «носителем» запроса на отмену. Запрашивающий код вызывает отмену на токене, а отвечающий код реагирует на это. Т.е. токен отмены — это то, как запрос отмены передается от запрашивающего кода к отвечающему коду.
Поэтому в 90% случаев добавьте параметр CancellationToken в метод, а затем передайте его любому API, который вы вызываете:
Токен отмены может обозначать отмену любого типа: нажатие пользователем кнопки «Отмена»; клиент отключается от сервера; закрытие приложения; тайм-аут. Для вашего кода не должно иметь значения, почему он отменяется; просто его отменяют.
Каждый токен можно отменить только один раз; как только токен отменён, он отменён навсегда.
Контракт отмены: сигнатура метода
По соглашению параметр CancellationToken обычно является последним, если не присутствует параметр IProgress<T>. Обычно предоставляется перегрузка или значение по умолчанию, чтобы вызывающему коду не приходилось предоставлять CancellationToken, если его нет; значение CancellationToken по умолчанию - CancellationToken.None, т.е. токен, который никогда не будет отменён:
Некоторые сигнатуры методов принимают CancellationToken и значение тайм-аута как отдельные параметры. В основном это делается в BCL, чтобы обеспечить более эффективные методы p/Invoke, которые принимают параметры тайм-аута. Если не используете API p/Invoke, используйте только CancellationToken, который может представлять собой любой вид отмены.
Принимая параметр CancellationToken, метод неявно заявляет, что он может отреагировать на отмену. Технически это означает «может ответить», а не «должен ответить». В некоторых случаях (например, при реализации интерфейса) аргумент CancellationToken может игнорироваться. Таким образом, наличие параметра CancellationToken не обязательно означает, что код должен поддерживать отмену.
Окончание следует…
Источник: https://blog.stephencleary.com/2022/02/cancellation-1-overview.html
Отмена. Часть 1: Обзор. Начало
Отмена — это тема, о которой возникает множество вопросов. И хотя документация Microsoft довольно хороша, в этой серии подробно рассмотрим эту тему.
Скоординированная отмена в .NET
Это означает, что одна часть кода запрашивает отмену, а другая часть кода отвечает на этот запрос. Мы часто говорим о том, что один код «отменяет» другой код, но на самом деле запрашивающий код просто вежливо уведомляет другой код о том, что он хотел бы его остановить, а отвечающий код может отреагировать на этот запрос на отмену любым способом. Отвечающий код может немедленно остановить то, что он делает, или продолжать работу до тех пор, пока не достигнет допустимой точки остановки, либо он может полностью игнорировать запрос на отмену.
Важный вывод: отвечающий код должен ответить на запрос отмены, чтобы отмена действительно что-то отменила.
Обычно возникает вопрос: как отменить неотменяемый код? Это сложный сценарий, рассмотрим его позже.
Токены отмены и «90% случаев»
В .NET токен отмены является «носителем» запроса на отмену. Запрашивающий код вызывает отмену на токене, а отвечающий код реагирует на это. Т.е. токен отмены — это то, как запрос отмены передается от запрашивающего кода к отвечающему коду.
Поэтому в 90% случаев добавьте параметр CancellationToken в метод, а затем передайте его любому API, который вы вызываете:
async Task DoAsync(
int data,
CancellationToken ct)
{
var myVal = await DoFirstAsync(data, ct);
await DoSecondAsync(myVal, ct);
}
Токен отмены может обозначать отмену любого типа: нажатие пользователем кнопки «Отмена»; клиент отключается от сервера; закрытие приложения; тайм-аут. Для вашего кода не должно иметь значения, почему он отменяется; просто его отменяют.
Каждый токен можно отменить только один раз; как только токен отменён, он отменён навсегда.
Контракт отмены: сигнатура метода
По соглашению параметр CancellationToken обычно является последним, если не присутствует параметр IProgress<T>. Обычно предоставляется перегрузка или значение по умолчанию, чтобы вызывающему коду не приходилось предоставлять CancellationToken, если его нет; значение CancellationToken по умолчанию - CancellationToken.None, т.е. токен, который никогда не будет отменён:
async Task DoAsync(int data) =>
DoAsync(data, CancellationToken.None);
async Task DoAsync(int data, CancellationToken ct)
{
…
}
// либо
async Task DoAsync(
int data, CancellationToken ct = default)
{
…
}
Некоторые сигнатуры методов принимают CancellationToken и значение тайм-аута как отдельные параметры. В основном это делается в BCL, чтобы обеспечить более эффективные методы p/Invoke, которые принимают параметры тайм-аута. Если не используете API p/Invoke, используйте только CancellationToken, который может представлять собой любой вид отмены.
Принимая параметр CancellationToken, метод неявно заявляет, что он может отреагировать на отмену. Технически это означает «может ответить», а не «должен ответить». В некоторых случаях (например, при реализации интерфейса) аргумент CancellationToken может игнорироваться. Таким образом, наличие параметра CancellationToken не обязательно означает, что код должен поддерживать отмену.
Окончание следует…
Источник: https://blog.stephencleary.com/2022/02/cancellation-1-overview.html
👍20
День 1987. #ЗаметкиНаПолях #Cancellation
Отмена. Часть 1: Обзор. Окончание
Начало
Контракт отмены: ответ
Как мы уже говорили, когда запрашивается отмена, отвечающий код может отменить то, что он делает, а может и нет. Даже если он попытается отменить, обычно возникает состояние гонки, и метод может фактически завершиться до того, как запрос на отмену будет обработан. Контракт отмены решает эту проблему путем фиксирования факта отмены кода через выброс исключения OperationCanceledException, когда запрошена отмена и фактически отменяется некоторая работа. Если запрос на отмену игнорируется или поступает слишком поздно и работа таки завершается, метод возвращается в обычном режиме.
Стандартный код для «90% случаев» обрабатывает это неявно; если DoFirstAsync или DoSecondAsync выбрасывают OperationCanceledException, то это исключение также распространяется из DoAsync. Никаких изменений в коде в «90% случаев» не требуется:
Существует множество примеров кода, которые просто молча делают ранний возврат, когда запрашивается отмена. Пожалуйста не делайте так; это нарушение контракта отмены! Когда отвечающий код просто возвращается раньше, вызывающий код не может знать, был ли его запрос на отмену удовлетворён или проигнорирован.
Исключение из «90% случаев»
Код в «90% случаев» просто принимает параметр CancellationToken и передаёт его дальше. Из этого правила есть одно заметное исключение: не следует передавать токен отмены в Task.Run.
Причина в том, что семантика сбивает с толку. Многие разработчики передают делегат и токен отмены в Task.Run и ожидают, что делегат будет отменён при отмене токена, но этого не происходит. Токен отмены, передаваемый в Task.Run, просто отменяет планирование делегата в пуле потоков; как только этот делегат начинает работать (что происходит практически сразу), этот токен отмены игнорируется.
Вот что пишут многие разработчики, ошибочно ожидая, что
Никогда не передавая CancellationToken в Task.Run (который в любом случае игнорируется, если только не возникает серьёзная конкуренция за пул потоков или токен уже не отменен), мы яснее даём понять, что сам делегат должен реагировать на токен:
Источник: https://blog.stephencleary.com/2022/02/cancellation-1-overview.html
Отмена. Часть 1: Обзор. Окончание
Начало
Контракт отмены: ответ
Как мы уже говорили, когда запрашивается отмена, отвечающий код может отменить то, что он делает, а может и нет. Даже если он попытается отменить, обычно возникает состояние гонки, и метод может фактически завершиться до того, как запрос на отмену будет обработан. Контракт отмены решает эту проблему путем фиксирования факта отмены кода через выброс исключения OperationCanceledException, когда запрошена отмена и фактически отменяется некоторая работа. Если запрос на отмену игнорируется или поступает слишком поздно и работа таки завершается, метод возвращается в обычном режиме.
Стандартный код для «90% случаев» обрабатывает это неявно; если DoFirstAsync или DoSecondAsync выбрасывают OperationCanceledException, то это исключение также распространяется из DoAsync. Никаких изменений в коде в «90% случаев» не требуется:
async Task DoAsync(
int data,
CancellationToken ct)
{
var myVal = await DoFirstAsync(data, ct);
await DoSecondAsync(myVal, ct);
}
Существует множество примеров кода, которые просто молча делают ранний возврат, когда запрашивается отмена. Пожалуйста не делайте так; это нарушение контракта отмены! Когда отвечающий код просто возвращается раньше, вызывающий код не может знать, был ли его запрос на отмену удовлетворён или проигнорирован.
Исключение из «90% случаев»
Код в «90% случаев» просто принимает параметр CancellationToken и передаёт его дальше. Из этого правила есть одно заметное исключение: не следует передавать токен отмены в Task.Run.
Причина в том, что семантика сбивает с толку. Многие разработчики передают делегат и токен отмены в Task.Run и ожидают, что делегат будет отменён при отмене токена, но этого не происходит. Токен отмены, передаваемый в Task.Run, просто отменяет планирование делегата в пуле потоков; как только этот делегат начинает работать (что происходит практически сразу), этот токен отмены игнорируется.
Вот что пишут многие разработчики, ошибочно ожидая, что
// Что-то делаем
будет отменено после его запуска:async Task DoSomethingAsync(CancellationToken ct)
{
await Task.Run(() =>
{
// Что-то делаем
}, ct);
…
}
Никогда не передавая CancellationToken в Task.Run (который в любом случае игнорируется, если только не возникает серьёзная конкуренция за пул потоков или токен уже не отменен), мы яснее даём понять, что сам делегат должен реагировать на токен:
async Task DoSomethingAsync(CancellationToken ct)
{
await Task.Run(() =>
{
// Что-то делаем
// IDE сообщает, что ct не используется,
// поэтому делегату нужно его использовать.
});
…
}
Источник: https://blog.stephencleary.com/2022/02/cancellation-1-overview.html
👍20
День 1988. #ЧтоНовенького
Оценка Кода с Помощью .NET Upgrade Assistant
Я уже писал про инструмент Upgrade Assistant ранее. Сегодня посмотрим, какие обновления он получил.
Независимо от того, выполняете ли вы обновление с .NET Framework до .NET 8 или просто между версиями .NET Core (с .NET 6 или 7 до .NET 8 или 9), .NET Upgrade Assistant поможет вам понять, какие изменения потребуются. Он доступен как расширение Visual Studio или как инструмент командной строки. Теперь в рамках обновления вы получите доступ к мощным функциям оценки кода.
Инструмент оценки кода сканирует решение на уровне исходного кода и выявляет потенциальные проблемы, которые могут возникнуть в процессе обновления. Вам будет предоставлена комплексная информационная панель, которая предоставит обзор проблем во всём решении и оценку того, сколько усилий потребуется для устранения каждой проблемы.
Каждая проблема в отчете классифицирована по степени серьезности: обязательная проблема, блокирующее обновление, или дополнительная возможность новой версии .NET.
Проблемы могут указывать точные места в исходном коде, что упрощает устранение неполадок и исправление зависимостей. Вы можете перейти к строке, которая требует внимания, устранить проблемы и пометить их как исправленные, а также сохранить текущее состояние проблем и составить отчёт, чтобы вы или ваши коллеги могли продолжить работу с того места, на котором вы остановились. Также доступны соответствующие ссылки на документацию, лучшие практики и обсуждения в сообществе, чтобы дать вам рекомендации, необходимые для решения каждой проблемы.
Анализ в Visual Studio
После установки расширения Visual Studio запустить инструмент обновления можно, просто щелкнув правой кнопкой мыши на решении и выбрав пункт Upgrade (Обновить).
Инструмент откроет окно, предлагающее либо создать новый отчёт, либо открыть существующий. Для нового отчёта вам будет предложено выбрать проекты для анализа, и предпочитаемую целевую платформу для обновления. Далее нужно выбрать компоненты из ранее выбранных проектов для анализа: только исходный код и настройки или также включить все бинарные зависимости. После этого выбора нажмите Analyze (Анализ), чтобы начать оценку приложения и получить отчет.
Интерпретация результатов
После анализа инструмент предоставит сводную информацию и подробный отчёт. В отчёте будет представлена информация о количестве проанализированных проектов, обнаруженных проблемах, а также оценка того, сколько усилий потребуется для устранения каждой проблемы.
Вы можете просмотреть саммари проблем для всего решения или углубиться в представления конкретного проекта. Здесь вы можете просмотреть подробную информацию о каждом инциденте, получить помощь по их устранению, перейти к их местоположению в коде и так далее. Можно просматривать проблемы по типу проблемы или по компоненту, чтобы понять, что создаёт основную часть проблем в отчёте. Отчёты можно сохранять в форматах HTML, CSV и JSON, чтобы делиться с коллегами.
Источник: https://devblogs.microsoft.com/visualstudio/code-assessment-with-net-upgrade-assistant/
Оценка Кода с Помощью .NET Upgrade Assistant
Я уже писал про инструмент Upgrade Assistant ранее. Сегодня посмотрим, какие обновления он получил.
Независимо от того, выполняете ли вы обновление с .NET Framework до .NET 8 или просто между версиями .NET Core (с .NET 6 или 7 до .NET 8 или 9), .NET Upgrade Assistant поможет вам понять, какие изменения потребуются. Он доступен как расширение Visual Studio или как инструмент командной строки. Теперь в рамках обновления вы получите доступ к мощным функциям оценки кода.
Инструмент оценки кода сканирует решение на уровне исходного кода и выявляет потенциальные проблемы, которые могут возникнуть в процессе обновления. Вам будет предоставлена комплексная информационная панель, которая предоставит обзор проблем во всём решении и оценку того, сколько усилий потребуется для устранения каждой проблемы.
Каждая проблема в отчете классифицирована по степени серьезности: обязательная проблема, блокирующее обновление, или дополнительная возможность новой версии .NET.
Проблемы могут указывать точные места в исходном коде, что упрощает устранение неполадок и исправление зависимостей. Вы можете перейти к строке, которая требует внимания, устранить проблемы и пометить их как исправленные, а также сохранить текущее состояние проблем и составить отчёт, чтобы вы или ваши коллеги могли продолжить работу с того места, на котором вы остановились. Также доступны соответствующие ссылки на документацию, лучшие практики и обсуждения в сообществе, чтобы дать вам рекомендации, необходимые для решения каждой проблемы.
Анализ в Visual Studio
После установки расширения Visual Studio запустить инструмент обновления можно, просто щелкнув правой кнопкой мыши на решении и выбрав пункт Upgrade (Обновить).
Инструмент откроет окно, предлагающее либо создать новый отчёт, либо открыть существующий. Для нового отчёта вам будет предложено выбрать проекты для анализа, и предпочитаемую целевую платформу для обновления. Далее нужно выбрать компоненты из ранее выбранных проектов для анализа: только исходный код и настройки или также включить все бинарные зависимости. После этого выбора нажмите Analyze (Анализ), чтобы начать оценку приложения и получить отчет.
Интерпретация результатов
После анализа инструмент предоставит сводную информацию и подробный отчёт. В отчёте будет представлена информация о количестве проанализированных проектов, обнаруженных проблемах, а также оценка того, сколько усилий потребуется для устранения каждой проблемы.
Вы можете просмотреть саммари проблем для всего решения или углубиться в представления конкретного проекта. Здесь вы можете просмотреть подробную информацию о каждом инциденте, получить помощь по их устранению, перейти к их местоположению в коде и так далее. Можно просматривать проблемы по типу проблемы или по компоненту, чтобы понять, что создаёт основную часть проблем в отчёте. Отчёты можно сохранять в форматах HTML, CSV и JSON, чтобы делиться с коллегами.
Источник: https://devblogs.microsoft.com/visualstudio/code-assessment-with-net-upgrade-assistant/
👍9
День 1989. #CSharp13
⚡️BREAKING! Типов-Расширений не Будет в C#13
О типах-расширениях я уже рассказывал, их с помпой представили Мэдс Торгенсен и Дастин Кэмбелл аж на Microsoft Build как главную новинку C# 13. Но позавчера в очередном обзоре новинок Кэтлин Доллард, главный программный менеджер .NET, сообщила, что «разработка и реализация потребуют больше времени. Ищите типы расширений в ранних предварительных версиях C#14 (NET 10)».
Подробности проблемы были описаны в саммари встречи о дизайне языка. Идея с генератором кода расширений, использовавшего
Мы видим два основных подхода:
1) Полностью посвятить себя поддержке во время выполнения. Если бы мы хотели пойти по пути поддержки во время выполнения, мы бы не полагались только на Unsafe.As; мы бы обновили среду выполнения, чтобы напрямую разрешить присвоение ref базового типа типу расширения. Это было бы безопаснее на уровне выполнения, поскольку даёт примитив, который можно проверить. Это также может дать лучшую отправную точку для дальнейшей поддержки членов интерфейса. Однако, к сожалению, мы не сможем достаточно обкатать функциональность до выхода .NET 9. Мы не боимся, что обещанные функции не будут выпущены, если они не готовы. Но это, скорее всего, будет означать, что расширения не будут выпущены в стабильной форме, по крайней мере, до выхода .NET 11.
2) Вернуться к рассмотрению расширений как сахара над статическими методами для типов расширений, что очень похоже на современные методы расширения. Здесь возникают повышенные трудности с представлением компилятора: публичная модель (сахар) и внутренняя реализация модели этих типов должны будут конвертироваться между собой. И дальнейшее расширение сахара возможно, но будет иметь некоторые сложности. Также потребуется больше переписывать тела членов, чтобы имитировать семантику методов экземпляра. Преимущества:
- Такая версия может быть выпущена в период с выходом .NET 9, по крайней мере, в предварительной версии.
- Существующие методы расширения фактически могут быть преобразованы в новую форму. Это будет не идеально; в частности, любой класс-держатель методов расширения, имеющий расширения для нескольких типов, скорее всего, не сможет работать.»
По итогам встречи было принято решение остановиться на втором варианте, но спустя чуть менее, чем месяц, видимо, разработчики языка решили подумать ещё.
Что ж, лично я могу только поддержать стремление выпускать только полноценно готовые новые фичи. На примере первичных конструкторов мы уже видели, что получается, когда создатели языка идут по другому пути.
С другой стороны, по большому счёту из новинок #CSharp13 теперь и выделить то нечего. Так, мелкие улучшения в довольно нишевых сценариях.
Что думаете?
Источники:
- https://devblogs.microsoft.com/dotnet/csharp-13-explore-preview-features/#update-on-extension-types
- https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-06-12.md#extensions
⚡️BREAKING! Типов-Расширений не Будет в C#13
О типах-расширениях я уже рассказывал, их с помпой представили Мэдс Торгенсен и Дастин Кэмбелл аж на Microsoft Build как главную новинку C# 13. Но позавчера в очередном обзоре новинок Кэтлин Доллард, главный программный менеджер .NET, сообщила, что «разработка и реализация потребуют больше времени. Ищите типы расширений в ранних предварительных версиях C#14 (NET 10)».
Подробности проблемы были описаны в саммари встречи о дизайне языка. Идея с генератором кода расширений, использовавшего
Unsafe.As
, «была отвергнута архитекторами среды выполнения .NET как принципиально небезопасная. Существуют потенциальные проблемы с псевдонимами, которые могут привести к путанице в частях JIT, особенно в редких сценариях оптимизации, и нельзя гарантировать, что они всегда будут безопасно обрабатываться с учётом предполагаемых вариантов использования. Нужно будет научить среду выполнения обрабатывать эти сценарии. Это долгосрочная функция, и нам потребуется время, чтобы опробовать её с реальными пользователями, прежде чем мы будем полностью уверены, что у нас правильный дизайн, поэтому мы хотели вернуться к чертёжной доске. Мы видим два основных подхода:
1) Полностью посвятить себя поддержке во время выполнения. Если бы мы хотели пойти по пути поддержки во время выполнения, мы бы не полагались только на Unsafe.As; мы бы обновили среду выполнения, чтобы напрямую разрешить присвоение ref базового типа типу расширения. Это было бы безопаснее на уровне выполнения, поскольку даёт примитив, который можно проверить. Это также может дать лучшую отправную точку для дальнейшей поддержки членов интерфейса. Однако, к сожалению, мы не сможем достаточно обкатать функциональность до выхода .NET 9. Мы не боимся, что обещанные функции не будут выпущены, если они не готовы. Но это, скорее всего, будет означать, что расширения не будут выпущены в стабильной форме, по крайней мере, до выхода .NET 11.
2) Вернуться к рассмотрению расширений как сахара над статическими методами для типов расширений, что очень похоже на современные методы расширения. Здесь возникают повышенные трудности с представлением компилятора: публичная модель (сахар) и внутренняя реализация модели этих типов должны будут конвертироваться между собой. И дальнейшее расширение сахара возможно, но будет иметь некоторые сложности. Также потребуется больше переписывать тела членов, чтобы имитировать семантику методов экземпляра. Преимущества:
- Такая версия может быть выпущена в период с выходом .NET 9, по крайней мере, в предварительной версии.
- Существующие методы расширения фактически могут быть преобразованы в новую форму. Это будет не идеально; в частности, любой класс-держатель методов расширения, имеющий расширения для нескольких типов, скорее всего, не сможет работать.»
По итогам встречи было принято решение остановиться на втором варианте, но спустя чуть менее, чем месяц, видимо, разработчики языка решили подумать ещё.
Что ж, лично я могу только поддержать стремление выпускать только полноценно готовые новые фичи. На примере первичных конструкторов мы уже видели, что получается, когда создатели языка идут по другому пути.
С другой стороны, по большому счёту из новинок #CSharp13 теперь и выделить то нечего. Так, мелкие улучшения в довольно нишевых сценариях.
Что думаете?
Источники:
- https://devblogs.microsoft.com/dotnet/csharp-13-explore-preview-features/#update-on-extension-types
- https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-06-12.md#extensions
👍13
День 1990. #BlazorBasics
Основы Blazor. Что Такое Blazor? Начало
Blazor — современная технология разработки UI от Microsoft. Он позволяет разрабатывать современные веб-приложения, такие как одностраничные приложения (Single-Page Application - SPA). Blazor - часть платформы .NET, т.е. он имеет доступ к обширной экосистеме .NET: API, языки программирования и среда выполнения.
Технологии
Blazor использует HTML, CSS и C# для создания веб-UI на стороне клиента. Вместо использования специфичных для Microsoft технологий, вроде XAML, для описания UI используются стандартные HTML и CSS. Вместо JavaScript или TypeScript, которые используются в React, Angular, Vue и других веб-фреймворках, Blazor использует C# для реализации поведения приложения.
Модель компонентов
Вот код типичного компонента Blazor:
1) Используется стандартный HTML (теги
2) Код C# либо начинается с символа
3) Директива
4) Мы определяем свойства в разделе
5) Атрибут
6) Тег
Как Blazor работает внутри?
В зависимости от модели хостинга (о них в продолжении) Blazor работает по-разному. Вы можете использовать одни и те же компоненты независимо от того, какую модель хостинга вы выберете. Можно создать библиотеку классов, содержащую компоненты Blazor, чтобы использовать их в разных приложениях. Приложение сможет получить доступ к библиотеке классов и использовать компоненты Blazor вне зависимости от модели хостинга.
Почему Blazor — это не Silverlight
Silverlight был откровенным провалом. Но не Microsoft отказалась от этой технологии. Это была архитектура, которая оказалась не в том месте и не в то время. Silverlight был основан на плагине для браузера. Плагины для браузера (вроде Flash) были обычным явлением в те времена, но постепенно от них стали отказываться, не в последнюю очередь из-за проблем с безопасностью.
Blazor основан на открытых веб-стандартах, таких как HTML, CSS и WebAssembly. Очень вероятно, что эти технологии будут поддерживаться в течение многих десятилетий. Кроме того, использование открытых стандартов означает, что без каких-либо плагинов или расширений Blazor работает в каждом браузере в любой операционной системе.
Blazor — это подходящее кроссплатформенное решение пользовательского веб-интерфейса .NET (которым всегда хотел быть Silverlight), но сделанное правильно.
Окончание следует…
Источник: https://www.telerik.com/blogs/blazor-basics-introduction-blazor-development
Основы Blazor. Что Такое Blazor? Начало
Blazor — современная технология разработки UI от Microsoft. Он позволяет разрабатывать современные веб-приложения, такие как одностраничные приложения (Single-Page Application - SPA). Blazor - часть платформы .NET, т.е. он имеет доступ к обширной экосистеме .NET: API, языки программирования и среда выполнения.
Технологии
Blazor использует HTML, CSS и C# для создания веб-UI на стороне клиента. Вместо использования специфичных для Microsoft технологий, вроде XAML, для описания UI используются стандартные HTML и CSS. Вместо JavaScript или TypeScript, которые используются в React, Angular, Vue и других веб-фреймворках, Blazor использует C# для реализации поведения приложения.
Модель компонентов
Вот код типичного компонента Blazor:
@page "/counter"
<PageTitle>Счётчик</PageTitle>
<h1>Счётчик</h1>
<p role="status">Счёт: @count</p>
<button class="btn" @onclick="Increment">Увеличить</button>
@code {
private int count = 0;
private void Increment()
{
count++;
}
}
1) Используется стандартный HTML (теги
h1
, p
и button
).2) Код C# либо начинается с символа
@
, либо заключен в блок кода, начинающийся с @code
. 3) Директива
@page
в первой строке делает этот компонент страницей, доступ к которой возможен по маршруту /counter
.4) Мы определяем свойства в разделе
@code
компонента, к которым можем получить доступ, используя символ @
перед ним в HTML-шаблоне компонента.5) Атрибут
@onclick
, добавленный в HTML-тег кнопки, позволяет связать с кнопкой метод Increment
, определённый в блоке кода компонента. При каждом нажатии кнопки метод выполняется.6) Тег
<PageTitle>
ссылается на компонент из библиотеки базовых классов. Тот же синтаксис используется при использовании пользовательских компонентов Blazor в вашем проекте.Как Blazor работает внутри?
В зависимости от модели хостинга (о них в продолжении) Blazor работает по-разному. Вы можете использовать одни и те же компоненты независимо от того, какую модель хостинга вы выберете. Можно создать библиотеку классов, содержащую компоненты Blazor, чтобы использовать их в разных приложениях. Приложение сможет получить доступ к библиотеке классов и использовать компоненты Blazor вне зависимости от модели хостинга.
Почему Blazor — это не Silverlight
Silverlight был откровенным провалом. Но не Microsoft отказалась от этой технологии. Это была архитектура, которая оказалась не в том месте и не в то время. Silverlight был основан на плагине для браузера. Плагины для браузера (вроде Flash) были обычным явлением в те времена, но постепенно от них стали отказываться, не в последнюю очередь из-за проблем с безопасностью.
Blazor основан на открытых веб-стандартах, таких как HTML, CSS и WebAssembly. Очень вероятно, что эти технологии будут поддерживаться в течение многих десятилетий. Кроме того, использование открытых стандартов означает, что без каких-либо плагинов или расширений Blazor работает в каждом браузере в любой операционной системе.
Blazor — это подходящее кроссплатформенное решение пользовательского веб-интерфейса .NET (которым всегда хотел быть Silverlight), но сделанное правильно.
Окончание следует…
Источник: https://www.telerik.com/blogs/blazor-basics-introduction-blazor-development
👍29
День 1991. #BlazorBasics
Основы Blazor. Что Такое Blazor? Окончание
Начало
Модели хостинга
1. Blazor WebAssembly — наиболее известная модель, в которой код .NET запускается в браузере. При первом запросе к сайту браузер загружает приложение, включая среду выполнения .NET. Код приложения написан на C#, а среда выполнения .NET преобразует код C# в двоичный в WebAssembly во время выполнения.
Браузер клиента хранит WebAssembly, среду выполнения .NET и код приложения. Для этой модели первоначальная загрузка среды выполнения и веб-приложения составляет около 1–5МБ. Общий размер зависит от размера вашего приложения.
Преимущество в том, что после загрузки весь код приложения оказывается на устройстве, а код в WebAssembly может выполняться на стороне клиента. Клиент подключается к серверной части только для получения дополнительных данных. Это делает подход Blazor WebAssembly масштабируемым.
2. Blazor Server был первой моделью хостинга, представленной в .NET Core 3. Веб-приложение запускается на сервере, а клиент подключается с помощью соединения SignalR (веб-сокет).
Браузер клиента хранит Blazor.js. Клиент и сервер взаимодействуют через соединение SignalR. Среда выполнения .NET, API и код приложения содержатся на сервере.
Для этого подхода требуется сервер, способный выполнять код .NET, поскольку приложение запускается на сервере, обычно в ASP.NET Core. Масштабируемость имеет свои ограничения, поскольку каждый клиент подключается к серверу, используя постоянное соединение через веб-сокет с помощью SignalR.
Однако он обеспечивает более быструю загрузку и начальный рендеринг страницы, поскольку с сервера клиенту передаются только HTML и CSS, которые появляются на экране. У вас также есть полный доступ к серверным технологиям, поскольку код выполняется на сервере.
Blazor Server зависит от стабильного сетевого подключения.
3. Blazor Hybrid — новейшая модель хостинга, а также самая сложная. Приложение частично работает на нативной платформе. Другая часть запускается в браузере. Идея состоит в том, чтобы объединить веб-технологии для реализации приложения с нативным доступом к API.
Автономные сценарии могут выиграть от гибридного подхода Blazor. Вы также можете использовать нативные компоненты UI для создания своего приложения. Однако развёртывание и реализация гораздо сложнее по сравнению с другими подходами. В превью .NET 9 включён шаблон гибридного приложения Blazor и MAUI, где вы можете посмотреть эту модель в деле.
Что выбрать?
Все модели хостинга имеют свои сильные и слабые стороны. Лучший совет — использовать модель хостинга, которая соответствует нефункциональным требованиям веб-приложения. Руководство в документации Microsoft поможет сделать выбор.
Для внутреннего приложения с известным количеством пользователей я бы использовал Blazor Server. Можно писать как внешний, так и внутренний код в одном проекте. Код работает во всех браузерах, даже в старых, которые не поддерживают WebAssembly.
Для приложения, ориентированного на клиента, с масштабируемым количеством пользователей я бы использовал Blazor WebAssembly. Это заставит реализовать отдельные интерфейс и серверную часть, что позволит лучше контролировать границы безопасности. Также его можно масштабировать по мере необходимости. Есть экономия на инфраструктуре за счёт перекладывания части работы с сервера на клиента.
Источник: https://www.telerik.com/blogs/blazor-basics-introduction-blazor-development
Основы Blazor. Что Такое Blazor? Окончание
Начало
Модели хостинга
1. Blazor WebAssembly — наиболее известная модель, в которой код .NET запускается в браузере. При первом запросе к сайту браузер загружает приложение, включая среду выполнения .NET. Код приложения написан на C#, а среда выполнения .NET преобразует код C# в двоичный в WebAssembly во время выполнения.
Браузер клиента хранит WebAssembly, среду выполнения .NET и код приложения. Для этой модели первоначальная загрузка среды выполнения и веб-приложения составляет около 1–5МБ. Общий размер зависит от размера вашего приложения.
Преимущество в том, что после загрузки весь код приложения оказывается на устройстве, а код в WebAssembly может выполняться на стороне клиента. Клиент подключается к серверной части только для получения дополнительных данных. Это делает подход Blazor WebAssembly масштабируемым.
2. Blazor Server был первой моделью хостинга, представленной в .NET Core 3. Веб-приложение запускается на сервере, а клиент подключается с помощью соединения SignalR (веб-сокет).
Браузер клиента хранит Blazor.js. Клиент и сервер взаимодействуют через соединение SignalR. Среда выполнения .NET, API и код приложения содержатся на сервере.
Для этого подхода требуется сервер, способный выполнять код .NET, поскольку приложение запускается на сервере, обычно в ASP.NET Core. Масштабируемость имеет свои ограничения, поскольку каждый клиент подключается к серверу, используя постоянное соединение через веб-сокет с помощью SignalR.
Однако он обеспечивает более быструю загрузку и начальный рендеринг страницы, поскольку с сервера клиенту передаются только HTML и CSS, которые появляются на экране. У вас также есть полный доступ к серверным технологиям, поскольку код выполняется на сервере.
Blazor Server зависит от стабильного сетевого подключения.
3. Blazor Hybrid — новейшая модель хостинга, а также самая сложная. Приложение частично работает на нативной платформе. Другая часть запускается в браузере. Идея состоит в том, чтобы объединить веб-технологии для реализации приложения с нативным доступом к API.
Автономные сценарии могут выиграть от гибридного подхода Blazor. Вы также можете использовать нативные компоненты UI для создания своего приложения. Однако развёртывание и реализация гораздо сложнее по сравнению с другими подходами. В превью .NET 9 включён шаблон гибридного приложения Blazor и MAUI, где вы можете посмотреть эту модель в деле.
Что выбрать?
Все модели хостинга имеют свои сильные и слабые стороны. Лучший совет — использовать модель хостинга, которая соответствует нефункциональным требованиям веб-приложения. Руководство в документации Microsoft поможет сделать выбор.
Для внутреннего приложения с известным количеством пользователей я бы использовал Blazor Server. Можно писать как внешний, так и внутренний код в одном проекте. Код работает во всех браузерах, даже в старых, которые не поддерживают WebAssembly.
Для приложения, ориентированного на клиента, с масштабируемым количеством пользователей я бы использовал Blazor WebAssembly. Это заставит реализовать отдельные интерфейс и серверную часть, что позволит лучше контролировать границы безопасности. Также его можно масштабировать по мере необходимости. Есть экономия на инфраструктуре за счёт перекладывания части работы с сервера на клиента.
Источник: https://www.telerik.com/blogs/blazor-basics-introduction-blazor-development
👍13
День 1992. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 15. Расстановка приоритетов по децибелам - не лучшая стратегия
Слышали поговорку: «Смазывают то колесо, которое скрипит»? По аналогии тот, кто громче всех отстаивает свои требования, получает наивысший приоритет.
Часто требований так много, что все их сложно добавить в проект. Лица, принимающие решения, должны выбрать, что добавить прямо сейчас, что отложить, от чего вовсе отказаться. Расстановка приоритетов — обязательный элемент планирования проекта. Она помогает распределить требования между итерациями, сборками или выпусками.
Каждому заинтересованному лицу кажется, что его потребности самые важные. Влиятельные, волевые или громкоголосые клиенты могут оказывать сильное давление, но они не всегда отстаивают самые важные с точки зрения бизнеса функции. Цель расстановки приоритетов — быстрое и недорогое предоставление максимальной ценности для клиента. Не нужно тратить силы на реализацию функций, не способствующих успеху продукта.
Методы определения приоритетов
- трехуровневая классификация: высокий, средний и низкий приоритет;
- классификация MoSCoW (Must, Should, Could, Won’t — обязательно, желательно, возможно, не нужно);
- попарное сравнение требований для сортировки по приоритетам;
- упорядочивание приоритетов похожих требований;
- распределение 100 баллов между требованиями в зависимости от приоритета;
- игра в планирование ;
- аналитические методы ранжирования требований на основе их ценности для продукта и стоимости реализации.
Критерии выбора приоритетов
1. Бизнес-цели
Наиболее весомый критерий — степень, в которой каждое требование поможет организации достичь её бизнес-целей. Такие суждения основываются на бизнес-требованиях проекта, которые спонсор должен определить на ранней стадии проекта. Они описывают создаваемую или используемую бизнес-возможность и количественно определяют бизнес-цели проекта.
2. Группы пользователей
Удовлетворение требований привилегированных групп пользователей больше способствует успеху бизнеса, чем удовлетворение потребностей других групп.
3. Частота использования
Один из способов оценить частоту использования — изучение особенностей применения приложения. Например, какой процент пользовательских сеансов на сайте авиакомпании связан с бронированием, отменой бронирования, проверкой статуса рейса и т.п.? Обычно (но не всегда) наиболее часто используемые операции будут иметь наивысший приоритет.
4. Соответствие нормативам
Такие требования должны иметь высокий приоритет. Вы не сможете продать продукт, если он не будет сертифицирован. Некоторые из таких функций могут иметь высокий приоритет, даже если ни один конечный пользователь не запрашивает их.
5. Основная функциональность
Некоторые возможности следует реализовать на раннем этапе, даже если они не приносят немедленную выгоду, т.к. они - основа для последующих функций. Определяя последовательность реализации, нужно учитывать зависимости между требованиями. От некоторых функций может зависеть архитектурная надёжность сложного продукта.
6. Рискованная функциональность
Требования, подразумевающие высокий риск с точки зрения реализации, следует реализовывать на ранней стадии, чтобы оценить их выполнимость и снизить общий технический риск проекта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 15. Расстановка приоритетов по децибелам - не лучшая стратегия
Слышали поговорку: «Смазывают то колесо, которое скрипит»? По аналогии тот, кто громче всех отстаивает свои требования, получает наивысший приоритет.
Часто требований так много, что все их сложно добавить в проект. Лица, принимающие решения, должны выбрать, что добавить прямо сейчас, что отложить, от чего вовсе отказаться. Расстановка приоритетов — обязательный элемент планирования проекта. Она помогает распределить требования между итерациями, сборками или выпусками.
Каждому заинтересованному лицу кажется, что его потребности самые важные. Влиятельные, волевые или громкоголосые клиенты могут оказывать сильное давление, но они не всегда отстаивают самые важные с точки зрения бизнеса функции. Цель расстановки приоритетов — быстрое и недорогое предоставление максимальной ценности для клиента. Не нужно тратить силы на реализацию функций, не способствующих успеху продукта.
Методы определения приоритетов
- трехуровневая классификация: высокий, средний и низкий приоритет;
- классификация MoSCoW (Must, Should, Could, Won’t — обязательно, желательно, возможно, не нужно);
- попарное сравнение требований для сортировки по приоритетам;
- упорядочивание приоритетов похожих требований;
- распределение 100 баллов между требованиями в зависимости от приоритета;
- игра в планирование ;
- аналитические методы ранжирования требований на основе их ценности для продукта и стоимости реализации.
Критерии выбора приоритетов
1. Бизнес-цели
Наиболее весомый критерий — степень, в которой каждое требование поможет организации достичь её бизнес-целей. Такие суждения основываются на бизнес-требованиях проекта, которые спонсор должен определить на ранней стадии проекта. Они описывают создаваемую или используемую бизнес-возможность и количественно определяют бизнес-цели проекта.
2. Группы пользователей
Удовлетворение требований привилегированных групп пользователей больше способствует успеху бизнеса, чем удовлетворение потребностей других групп.
3. Частота использования
Один из способов оценить частоту использования — изучение особенностей применения приложения. Например, какой процент пользовательских сеансов на сайте авиакомпании связан с бронированием, отменой бронирования, проверкой статуса рейса и т.п.? Обычно (но не всегда) наиболее часто используемые операции будут иметь наивысший приоритет.
4. Соответствие нормативам
Такие требования должны иметь высокий приоритет. Вы не сможете продать продукт, если он не будет сертифицирован. Некоторые из таких функций могут иметь высокий приоритет, даже если ни один конечный пользователь не запрашивает их.
5. Основная функциональность
Некоторые возможности следует реализовать на раннем этапе, даже если они не приносят немедленную выгоду, т.к. они - основа для последующих функций. Определяя последовательность реализации, нужно учитывать зависимости между требованиями. От некоторых функций может зависеть архитектурная надёжность сложного продукта.
6. Рискованная функциональность
Требования, подразумевающие высокий риск с точки зрения реализации, следует реализовывать на ранней стадии, чтобы оценить их выполнимость и снизить общий технический риск проекта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍5
День 1993. #ЗаметкиНаПолях #Cancellation
Отмена. Часть 2: Запрос Отмены.
В прошлый раз мы рассмотрели базовый контракт отмены. Теперь рассмотрим, как создавать токены отмены для запроса отмены.
CancellationTokenSource
Некоторые токены отмены предоставляются используемой вами платформой или библиотекой. Например, ASP.NET предоставит вам CancellationToken, который представляет собой неожиданное отключение клиента. Polly может предоставить вашему делегату токен, который представляет собой более общую отмену (например, срабатывание политики тайм-аута).
В других сценариях вам потребуется предоставить собственный токен. В общем случае, когда вы хотите создать CancellationToken, который можно будет отменить позже, нужно использовать CancellationTokenSource.
Каждый CancellationTokenSource управляет своим набором токенов. Каждый токен, созданный из CancellationTokenSource, представляет собой небольшую структуру, которая ссылается на свой CancellationTokenSource. Токен отмены может только отвечать на запросы отмены; CancellationTokenSource необходим для запроса отмены. Поэтому запрашивающий код создает CancellationTokenSource и сохраняет ссылку на него (используя эту ссылку позже для запроса отмены), а отвечающий код просто получает CancellationToken и использует его для ответа на запросы отмены.
Таймауты
Одной из распространённых потребностей отмены является реализация тайм-аута. Решение состоит в том, чтобы иметь таймер, который запрашивает отмену по истечении срока его действия. В CancellationTokenSource такое поведение встроено. Вы можете использовать конструктор CancellationTokenSource, который принимает таймаут, или вызвать CancelAfter для существующего CancellationTokenSource:
Очистка
Чтобы избежать утечек ресурсов, важно уничтожать (dispose) экземпляры CancellationTokenSource. Очищается несколько видов ресурсов: во-первых, таймер тайм-аута (если он есть); во-вторых, все «слушатели», прикрепленные к токенам отмены. Эта очистка выполняется при отмене или уничтожении CancellationTokenSource. Вы должны убедиться, что либо одно, либо другое выполнено, чтобы избежать утечек ресурсов.
Если токен отмены сохраняется и используется позже, вы бы не хотели уничтожать CancellationTokenSource. В этом случае следует сохранять CancellationTokenSource активным до тех пор, пока вы не будете уверены, что весь код, использующий его токены, выполнен. Это более сложный случай, и иногда удобнее отменить CancellationTokenSource, а не уничтожать его.
Предупреждение: уничтожение связанных источников CancellationTokenSource.
Вызов Cancel или Dispose очистит все регистрации для конкретного CancellationTokenSource. Однако если этот CancellationTokenSource связан с «родительским» CancellationTokenSource, вызов Cancel для «дочернего» CancellationTokenSource приведёт к отмене регистрации в «родительском» CancellationTokenSource. Вы можете вызвать Dispose (или использовать оператор using) для «дочернего элемента», чтобы очистить регистрацию у родителя этого дочернего элемента, разрывая ссылку.
Эта и другие темы, касающиеся связанных CancellationTokenSource, будут рассмотрены далее в этой серии.
Источник: https://blog.stephencleary.com/2022/03/cancellation-2-requesting-cancellation.html
Отмена. Часть 2: Запрос Отмены.
В прошлый раз мы рассмотрели базовый контракт отмены. Теперь рассмотрим, как создавать токены отмены для запроса отмены.
CancellationTokenSource
Некоторые токены отмены предоставляются используемой вами платформой или библиотекой. Например, ASP.NET предоставит вам CancellationToken, который представляет собой неожиданное отключение клиента. Polly может предоставить вашему делегату токен, который представляет собой более общую отмену (например, срабатывание политики тайм-аута).
В других сценариях вам потребуется предоставить собственный токен. В общем случае, когда вы хотите создать CancellationToken, который можно будет отменить позже, нужно использовать CancellationTokenSource.
Каждый CancellationTokenSource управляет своим набором токенов. Каждый токен, созданный из CancellationTokenSource, представляет собой небольшую структуру, которая ссылается на свой CancellationTokenSource. Токен отмены может только отвечать на запросы отмены; CancellationTokenSource необходим для запроса отмены. Поэтому запрашивающий код создает CancellationTokenSource и сохраняет ссылку на него (используя эту ссылку позже для запроса отмены), а отвечающий код просто получает CancellationToken и использует его для ответа на запросы отмены.
Таймауты
Одной из распространённых потребностей отмены является реализация тайм-аута. Решение состоит в том, чтобы иметь таймер, который запрашивает отмену по истечении срока его действия. В CancellationTokenSource такое поведение встроено. Вы можете использовать конструктор CancellationTokenSource, который принимает таймаут, или вызвать CancelAfter для существующего CancellationTokenSource:
async Task DoSomethingWithTimeoutAsync()
{
// Создаём CTS, который отменится через 5 минут
using CancellationTokenSource cts
= new(TimeSpan.FromMinutes(5));
// Передаём токен
await DoSomethingAsync(cts.Token);
// В конце метода CTS уничтожается
// Его токены не могут больше использоваться
}
Очистка
Чтобы избежать утечек ресурсов, важно уничтожать (dispose) экземпляры CancellationTokenSource. Очищается несколько видов ресурсов: во-первых, таймер тайм-аута (если он есть); во-вторых, все «слушатели», прикрепленные к токенам отмены. Эта очистка выполняется при отмене или уничтожении CancellationTokenSource. Вы должны убедиться, что либо одно, либо другое выполнено, чтобы избежать утечек ресурсов.
Если токен отмены сохраняется и используется позже, вы бы не хотели уничтожать CancellationTokenSource. В этом случае следует сохранять CancellationTokenSource активным до тех пор, пока вы не будете уверены, что весь код, использующий его токены, выполнен. Это более сложный случай, и иногда удобнее отменить CancellationTokenSource, а не уничтожать его.
Предупреждение: уничтожение связанных источников CancellationTokenSource.
Вызов Cancel или Dispose очистит все регистрации для конкретного CancellationTokenSource. Однако если этот CancellationTokenSource связан с «родительским» CancellationTokenSource, вызов Cancel для «дочернего» CancellationTokenSource приведёт к отмене регистрации в «родительском» CancellationTokenSource. Вы можете вызвать Dispose (или использовать оператор using) для «дочернего элемента», чтобы очистить регистрацию у родителя этого дочернего элемента, разрывая ссылку.
Эта и другие темы, касающиеся связанных CancellationTokenSource, будут рассмотрены далее в этой серии.
Источник: https://blog.stephencleary.com/2022/03/cancellation-2-requesting-cancellation.html
👍16
День 1994. #ЗаметкиНаПолях
Activator.CreateInstance(Type) Может Возвращать Null
Большинство людей ожидают, что этот метод вернет не-null объект, поскольку вы явно запрашиваете создание нового экземпляра, но это не всегда так. Для типов Nullable<T>
Заметьте, что такое же поведение наблюдается при использовании ключевого слова
Вы можете использовать null-снисходительный оператор (!), чтобы подавить предупреждение о том, что значение может быть
Источник: https://www.meziantou.net/activator-createinstance-type-may-return-null.htm
Activator.CreateInstance(Type) Может Возвращать Null
Activator.CreateInstance(Type)
позволяет создать экземпляр типа, не зная тип во время компиляции. Например, вы можете захотеть создать экземпляр типа на основе файла конфигурации или ввода пользователя. Всегда, когда вы не можете использовать ключевое слово new
, вы можете использовать Activator.CreateInstance(Type)
.Большинство людей ожидают, что этот метод вернет не-null объект, поскольку вы явно запрашиваете создание нового экземпляра, но это не всегда так. Для типов Nullable<T>
Activator.CreateInstance(Type)
возвращает значение null
.object? value = Activator.CreateInstance(typeof(int?));
Console.WriteLine(value is null); // true
Заметьте, что такое же поведение наблюдается при использовании ключевого слова
new
:object? value = new int?();
Console.WriteLine(value is null); // true
Вы можете использовать null-снисходительный оператор (!), чтобы подавить предупреждение о том, что значение может быть
null
, если вы уверены, что тип не может быть Nullable<T>:object? value = Activator.CreateInstance(typeof(object))!;
Console.WriteLine(value.GetHashCode());
Console.WriteLine(value is null); // всегда false
Источник: https://www.meziantou.net/activator-createinstance-type-may-return-null.htm
👍16
День 1995. #ЧтоНовенького
UUID Версии 7 в .NET 9
Спецификация UUID (универсальные уникальные идентификаторы), также известные как GUID (глобальные уникальные идентификаторы), определяет несколько различных версий UUID.
.NET использует UUID версии 4 в методе
Новый API по-прежнему находится внутри System.Guid:
Что аналогично:
Основным преимуществом является перегрузка с меткой времени, включенная в UUID. Вот как устроен UUID версии 7:
| 48-bit timestamp | 12-bit random | 62-bit random |
Длина осталась прежней, но первые 48 бит занимает метка времени. Основное преимущество заключается в том, что вы можете сортировать UUID по времени их создания, что делает их более подходящими для идентификаторов в базах данных, чем UUID версии 4.
Управление меткой времени
Поскольку метод принимает DateTimeOffset, вызывающая функция может использовать TimeProvider для управления UtcNow:
timeProvider можно внедрить через DI и эмулировать в сценариях тестирования.
Интересно, что внутренний код вызывает
Оригинальное предложение и дискуссия: https://github.com/dotnet/runtime/issues/103658
Источник: https://steven-giesel.com/blogPost/ea42a518-4d8b-4e08-8f73-e542bdd3b983/uuid-v7-in-net-9
UUID Версии 7 в .NET 9
Спецификация UUID (универсальные уникальные идентификаторы), также известные как GUID (глобальные уникальные идентификаторы), определяет несколько различных версий UUID.
.NET использует UUID версии 4 в методе
Guid.NewGuid()
. Это, почти полностью случайное (или псевдослучайное) число. Но в превью 7 .NET 9 мы получим UUID версии 7.Новый API по-прежнему находится внутри System.Guid:
var guid = Guid.CreateVersion7();
Что аналогично:
var guid =
Guid.CreateVersion7(Guid.CreateVersion7(DateTimeOffset.UtcNow));
Основным преимуществом является перегрузка с меткой времени, включенная в UUID. Вот как устроен UUID версии 7:
| 48-bit timestamp | 12-bit random | 62-bit random |
Длина осталась прежней, но первые 48 бит занимает метка времени. Основное преимущество заключается в том, что вы можете сортировать UUID по времени их создания, что делает их более подходящими для идентификаторов в базах данных, чем UUID версии 4.
Управление меткой времени
Поскольку метод принимает DateTimeOffset, вызывающая функция может использовать TimeProvider для управления UtcNow:
var uuid = Guid.CreateVersion7(timeProvider.GetUtcNow());
timeProvider можно внедрить через DI и эмулировать в сценариях тестирования.
Интересно, что внутренний код вызывает
NewGuid()
, а затем заменяет его первые байты на метку времени с помощью Unsafe.AsRef
. Это делает CreateVersion7()
примерно в 2 раза медленнее, чем NewGuid()
, но это в любом случае десятки наносекунд.CreateVersion7
- довольно странное название метода, как по мне. Во-первых, оно какбэ намекает, что должны быть CreateVersion1
, …, CreateVersion6
, а их нет. А во-вторых, не соответствует методу NewGuid
. То есть предполагается, что вы должны разбираться в версиях UUID, чтобы знать, какой версии UUID в NewGuid
. Впрочем, возможно (и надеюсь), что к релизу .NET 9 метод переименуют.Оригинальное предложение и дискуссия: https://github.com/dotnet/runtime/issues/103658
Источник: https://steven-giesel.com/blogPost/ea42a518-4d8b-4e08-8f73-e542bdd3b983/uuid-v7-in-net-9
👍33
День 1996. #ЗаметкиНаПолях
Кастомизируем Swagger UI
Swagger — это набор инструментов для разработки, документирования и использования RESTful API. Он помогает разработчикам более эффективно проектировать, создавать, документировать и использовать API.
Swashbuckle — проект с открытым кодом, который интегрирует Swagger с приложениями .NET. По умолчанию при создании проекта API в Program.cs создаётся код, который добавляет поддержку Swagger вместе со Swagger UI.
Этот UI можно обогатить множеством вещей.
IDocumentFilter
С помощью этого интерфейса можно манипулировать и настраивать весь документ Swagger/OpenAPI перед его визуализацией или доставкой клиентам. Он обеспечивает возможность изменять, добавлять или удалять любую часть документа, например пути, операции, схемы и т. д.
Метод Apply предоставляет доступ к объекту OpenApiDocument, который представляет собой документ Swagger, и объекту DocumentFilterContext, который предоставляет дополнительный контекст и информацию.
Например, вам нужно удалить устаревшую конечную точку из Swagger UI, не удаляя её из кода. Если мы пометим какую-то конечную точку как устаревшую (Deprecated), это не скроет её из Swagger UI. Она будет просто перечёркнута и выделена серым цветом.
Добавим фильтр в Program.cs:
Теперь эта конечная точка не появится в Swagger UI.
Также можно добавить дополнительные метаданные ко всем (или избранным) конечным точкам. Например, добавление стандартного заголовка полезно для ограничения скорости, отслеживания запросов или любых других сквозных задач:
Источник: https://thecodeman.net/blog
Кастомизируем Swagger UI
Swagger — это набор инструментов для разработки, документирования и использования RESTful API. Он помогает разработчикам более эффективно проектировать, создавать, документировать и использовать API.
Swashbuckle — проект с открытым кодом, который интегрирует Swagger с приложениями .NET. По умолчанию при создании проекта API в Program.cs создаётся код, который добавляет поддержку Swagger вместе со Swagger UI.
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
Этот UI можно обогатить множеством вещей.
IDocumentFilter
С помощью этого интерфейса можно манипулировать и настраивать весь документ Swagger/OpenAPI перед его визуализацией или доставкой клиентам. Он обеспечивает возможность изменять, добавлять или удалять любую часть документа, например пути, операции, схемы и т. д.
Метод Apply предоставляет доступ к объекту OpenApiDocument, который представляет собой документ Swagger, и объекту DocumentFilterContext, который предоставляет дополнительный контекст и информацию.
Например, вам нужно удалить устаревшую конечную точку из Swagger UI, не удаляя её из кода. Если мы пометим какую-то конечную точку как устаревшую (Deprecated), это не скроет её из Swagger UI. Она будет просто перечёркнута и выделена серым цветом.
public class RemoveObsoleteFilter : IDocumentFilter
{
public void Apply(
OpenApiDocument doc,
DocumentFilterContext ctx) {
var obsPaths = doc.Paths
.Where(p => p.Value.Operations
.Any(op => op.Value.Deprecated))
.Select(p => p.Key)
.ToList();
foreach (var path in obsPaths)
doc.Paths.Remove(path);
}
}
Добавим фильтр в Program.cs:
builder.Services.AddSwaggerGen(c =>
{
c.DocumentFilter<RemoveObsoleteFilter>();
});
Теперь эта конечная точка не появится в Swagger UI.
Также можно добавить дополнительные метаданные ко всем (или избранным) конечным точкам. Например, добавление стандартного заголовка полезно для ограничения скорости, отслеживания запросов или любых других сквозных задач:
public class CustomHeaderFilter : IDocumentFilter
{
public void Apply(
OpenApiDocument doc,
DocumentFilterContext ctx)
{
foreach (var path in doc.Paths.Values)
{
foreach (var op in path.Operations.Values)
{
foreach (var resp in op.Responses.Values)
{
resp.Headers ??=
new Dictionary<string, OpenApiHeader>();
resp.Headers
.Add("X-Custom-Header",
new OpenApiHeader
{
Description = "Custom header",
Schema = new OpenApiSchema
{
Type = "string"
}
});
}
}
}
}
}
Источник: https://thecodeman.net/blog
👍22
День 1997. #ЗаметкиНаПолях
Добавляем Аудит NuGet в Проекты .NET.
Аудит безопасности для менеджеров пакетов, таких как NuGet, является критически важным процессом для обеспечения безопасности программных проектов. В NuGet есть функция, которая вам поможет. Она может запустить аудит безопасности с помощью команды dotnet restore, которая сверяет ваши зависимости со списком известных уязвимостей из GitHub Advisory Database.
Если обнаружены уязвимости, вы можете обновить затронутые пакеты до более новой версии, содержащей исправления безопасности, или, если обновления недоступны, проверить, как обезопасить код или использовать альтернативный пакет.
Для аудита NuGet требуется .NET SDK 8.0.100 или более поздней версии. Чтобы включить аудит NuGet для ваших проектов .NET, добавьте в файл проекта следующие свойства:
Вы также можете проверить наличие уязвимостей в своих проектах с помощью команды
Если вы пока не можете устранить уязвимость, можно отключить предупреждение для каждого пакета, используя NoWarn в элементе PackageReference. Если ссылка транзитивная, можно добавить прямую ссылку на пакет с уязвимостью:
Если у вас глобально включены WarningsAsErrors в проекте, но вы не хотите такого поведения для уязвимостей, используйте WarningsNotAsErrors:
Источник: https://www.meziantou.net/enable-nuget-auditing-for-your-dotnet-projects.htm
Добавляем Аудит NuGet в Проекты .NET.
Аудит безопасности для менеджеров пакетов, таких как NuGet, является критически важным процессом для обеспечения безопасности программных проектов. В NuGet есть функция, которая вам поможет. Она может запустить аудит безопасности с помощью команды dotnet restore, которая сверяет ваши зависимости со списком известных уязвимостей из GitHub Advisory Database.
Если обнаружены уязвимости, вы можете обновить затронутые пакеты до более новой версии, содержащей исправления безопасности, или, если обновления недоступны, проверить, как обезопасить код или использовать альтернативный пакет.
Для аудита NuGet требуется .NET SDK 8.0.100 или более поздней версии. Чтобы включить аудит NuGet для ваших проектов .NET, добавьте в файл проекта следующие свойства:
<Project>
<PropertyGroup>
<NuGetAudit>true</NuGetAudit>
<!-- Прямые и транзитивные пакеты -->
<NuGetAuditMode>all</NuGetAuditMode>
<!-- Уровень уязвимостей для отчёта -->
<NuGetAuditLevel>low</NuGetAuditLevel>
<!-- Отменяем сборку в CI при обнаружении уязвимостей -->
<WarningsAsErrors Condition="$(ContinuousIntegrationBuild) == 'true' OR '$(Configuration)' == 'Release'">
(WarningsAsErrors);NU1900;NU1901;NU1902;NU1903;NU1904
</WarningsAsErrors>
</PropertyGroup>
</Project>
Вы также можете проверить наличие уязвимостей в своих проектах с помощью команды
dotnet list package --vulnerable.
Если вы пока не можете устранить уязвимость, можно отключить предупреждение для каждого пакета, используя NoWarn в элементе PackageReference. Если ссылка транзитивная, можно добавить прямую ссылку на пакет с уязвимостью:
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="System.Formats.Asn1" Version="8.0.0" NoWarn="NU1903" />
<PackageReference Include="System.Text.Json" Version="8.0.1" />
</ItemGroup>
</Project>
Если у вас глобально включены WarningsAsErrors в проекте, но вы не хотите такого поведения для уязвимостей, используйте WarningsNotAsErrors:
<Project>
<PropertyGroup>
<WarningsNotAsErrors>NU1901;NU1902;NU1903;NU1904</WarningsNotAsErrors>
</PropertyGroup>
<Project>
Источник: https://www.meziantou.net/enable-nuget-auditing-for-your-dotnet-projects.htm
👍17