TG Telegram Group Link
Channel: .NET Разработчик
Back to Bottom
День 2339. #ЗаметкиНаПолях
RabbitMQ в .NET с Нуля. Окончание
Начало
Продолжение

Типы обмена в RabbitMQ
Обменник (Exchange) в RabbitMQ решает, куда отправить сообщение. Каждый тип обмена имеет свою стратегию маршрутизации сообщений.

1. Direct Exchange (маршрутизация один-к-одному)
Сообщение направляется в очереди с точно таким же ключом маршрутизации. Это как отправка почты определённому получателю. Например, отправка email только в очередь, ответственную за маркетинговую рассылку:
channel.ExchangeDeclare(
"direct-exchange", ExchangeType.Direct);
channel.QueueBind(
"market-queue", "direct-exchange", "market");

Если вы отправите сообщение с routingKey: "market" (см. вызов BasicPublishAsync в примере кода производителя), оно попадёт в очередь "market-queue".

2. Fanout Exchange (отправка всем)
Сообщения отправляются во все очереди, связанные с этим обменником, игнорируя routingKey. Например, всеобщая рассылка по всем сервисам (email, СМС):
channel.ExchangeDeclare(
"fanout-exchange", ExchangeType.Fanout);
channel.QueueBind(
"email-queue", "fanout-exchange", "");
channel.QueueBind(
"sms-queue", "fanout-exchange", "");

Любое сообщение, отправленное в "fanout-exchange", попадёт в обе очереди.

3. Topic Exchange (маршрутизация по шаблону)
Использует шаблон routingKey для гибкой настройки:
- * - ровно одно слово,
- # - 0 и более слов.
Например, маршрутизация логов на основе важности и типа системы:
channel.ExchangeDeclare(
"topic-exchange", ExchangeType.Topic);
channel.QueueBind(
"error-queue", "topic-exchange", "log.error.#");
channel.QueueBind(
"auth-queue", "topic-exchange", "log.*.auth");

"log.error.auth" – попадёт в обе очереди.
"log.info.auth" – попадёт в auth-queue.
"log.error.database" – попадёт в error-queue.

4. Headers Exchange (маршрутизация по метаданным)
Вместо routingKey использует заголовки сообщения. Например, маршрутизация сообщений по сложным условиям (x-type="invoice" и region="EU"):
channel.ExchangeDeclare(
"headers-exchange", ExchangeType.Headers);
var args = new Dictionary<string, object>
{
{"x-match", "all"}, // либо "any"
{"x-type", "invoice"},
{"region", "EU"}
};
channel.QueueBind(
"invoice-eu-queue",
"headers-exchange",
string.Empty,
args);

Только сообщения, которые включают и x-type="invoice", и region="EU" в своих заголовках, попадут в очередь "invoice-eu-queue".

Итого
RabbitMQ — мощный инструмент для создания масштабируемых, слабо связанных систем, а .NET делает его удивительно простым в интеграции. Независимо от того, создаете ли вы микросервисы или просто хотите разгрузить основное приложение от выполнения некоторых длительных задач, RabbitMQ вам поможет.

Источник: https://thecodeman.net/posts/rabbitmq-in-dotnet-from-scratch
👍13
День 2340. #TipsAndTricks
Широко известный в узких кругах дотнетчиков блогер Ник Чапсас помимо основных видео на своём ютуб-канале также выпускает шортсы с короткими советами по написанию более лучшего кода. Так вот, таких советов накопилось уже более сотни, поэтому он собрал первую сотню в одно почти часовое видео.

Смотрим и мотаем на ус 😉

https://youtu.be/8F-Pb-SKO5g
👍22
День 2341. #ЗаметкиНаПолях
Исключаем Windows-приложение из Захвата Экрана
Некоторые приложения отображают конфиденциальную информацию. Recall в Windows может регулярно делать снимки экрана и таким образом сохранять конфиденциальную информацию, что крайне нежелательно.

Вы можете исключить своё приложение из этой функции и захвата экрана в целом, используя SetWindowDisplayAffinity и флаг WDA_EXCLUDEFROMCAPTURE. Это функция API Windows, позволяющая установить привязку отображения окна, которая определяет, как окно взаимодействует с программным обеспечением захвата экрана.

1. Добавьте NuGet-пакет Microsoft.Windows.CsWin32

2. Добавьте в проект файл NativeMethods.txt со следующим содержимым:
SetWindowDisplayAffinity


3. Добавьте следующий код в проект:
unsafe
{
// для WPF:
// new WindowInteropHelper(
// Application.Current.MainWindow)
// .Handle

// для WinForms:
// this.Handle

var windowHandle = (HWND)Handle;
Windows.Win32.PInvoke.SetWindowDisplayAffinity(
windowHandle,
Windows.Win32.UI
.WindowsAndMessaging
.WINDOW_DISPLAY_AFFINITY
.WDA_EXCLUDEFROMCAPTURE
);
}


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

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

Источник:
https://www.meziantou.net/how-to-exclude-your-windows-app-from-screen-capture-and-recall.htm
👍26
День 2342. #УрокиРазработки
Уроки 50 Лет Разработки ПО

Урок 56. Здравый смысл и опыт иногда важнее определённого процесса


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

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

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

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

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

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

Методы Agile-разработки получили широкое распространение с конца 1990-х. В «Википедии» определены не менее 14 важных систем и 21 широко используемая практика Agile-разработки ПО. Некоторые пуристы очень обеспокоены соответствием, скажем, методологии Scrum. Потому что «если использовать только отдельные компоненты Scrum, то это будет не Scrum». Так цель соответствовать Scrum или качественно и быстро выполнить работу?

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

Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍5
День 2343. #ЧтоНовенького
Вышел 5 Превью .NET 10. Начало
Microsoft объявили о выпуске .NET 10 превью 5, представив обновления для нескольких компонентов, включая ASP.NET Core, .NET MAUI, WPF и EF Core.

ASP.NET Core
1. Появилась возможность настраивать пользовательские дескрипторы безопасности для очередей запросов HTTP.sys через свойство RequestQueueSecurityDescriptor в HttpSysOptions. Это обеспечивает лучший контроль над доступом к очередям запросов на уровне ОС.

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

3. Генерация OpenAPI была улучшена в версии 3.1. Выпуск также расширяет извлечение метаданных из XML-документации, распознавая теги <returns> и <response> для описаний ответов.

4. В Blazor представлен метод для более простого рендеринга страниц Not Found путем указания компонента NotFoundPage в конфигурации маршрутизатора. Этот подход имеет приоритет над старым фрагментом NotFound. Теперь страница NotFound.razor включена в шаблоны проектов по умолчанию и будет отображаться всякий раз, когда в приложении вызывается метод NavigationManager.NotFound():
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>This content will be ignored because we have NotFoundPage defined.</NotFound>
</Router>


5. Введены подробные метрики и возможности трассировки для приложений Blazor. Метрики публикуются через выделенные счетчики для компонентов, событий жизненного цикла и конвейеров сервера. Трассировка использует новый источник активности Microsoft.AspNetCore.Components, включающий подробный инструментарий для навигации, обработки событий и жизненных циклов конвейера. Разработчики могут включить эту диагностику, настроив OpenTelemetry для сбора данных из соответствующих источников и счётчиков:
builder.Services
.ConfigureOpenTelemetryMeterProvider(p =>
{
p.AddMeter("Microsoft.AspNetCore.Components");
p.AddMeter("Microsoft.AspNetCore.Components.Lifecycle");
p.AddMeter("Microsoft.AspNetCore.Components.Server.Circuits");
});

builder.Services
.ConfigureOpenTelemetryTracerProvider(p =>
{
p.AddSource("Microsoft.AspNetCore.Components");
});


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

Источник:
https://www.infoq.com/news/2025/06/dotnet-10-preview-5/
👍10
День 2344. #ЧтоНовенького
Вышел 5 Превью .NET 10. Окончание

Начало

MAUI
1. Добавлена поддержка глобальных и неявных пространств имён XAML. Это упрощает разметку, позволяя разработчикам использовать элементы управления без указания нескольких объявлений xmlns. Новое глобальное пространство имён может включать пользовательские представления, конвертеры и сторонние библиотеки, что позволяет сделать XAML более чистым и удобным для обслуживания. Функцию можно активировать через свойства проекта, что снижает необходимость в подробных объявлениях. Однако Microsoft отмечает, что могут возникать ошибки инструментов, пока эта функция остаётся в предварительной версии.

2. Добавлена возможность перехвата веб-запросов в HybridWebView благодаря обработке события WebResourceRequested. Можно изменять или блокировать запросы, позволяя использовать такие сценарии, как внедрение пользовательских заголовков или обслуживание локальных ресурсов:
<HybridWebView WebResourceRequested="HybridWebView_WebResourceRequested" />


WPF
1. Представлен сокращённый синтаксис для Grid.RowDefinitions и Grid.ColumnDefinitions, делая XAML более лаконичным и улучшая поддержку Hot Reload.

2. Улучшения шрифтов и глобализации включают добавление шрифта simsun-extg для улучшения рендеринга на восточноазиатских языках. Тема Fluent была усовершенствована, устраняя сбои и улучшая стили для макетов RTL. Повышение производительности было достигнуто за счёт сокращения выделения памяти и удаления неиспользуемых путей кода.

Entity Framework
В предыдущих версиях EF Core, когда вы указывали значение по умолчанию для свойства, EF Core всегда позволял базе данных автоматически генерировать имя ограничения. Теперь вы можете явно указать имя для ограничений значения по умолчанию для SQL Server, что даёт больше контроля над схемой БД:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Blog>()
.Property(b => b.IsActive)
.HasDefaultValue(true, "DF_Blog_IsActive");

mb.Entity<Post>()
.Property(p => b.CreatedDate)
.HasDefaultValueSql("GETDATE()", "DF_Post_CreatedDate");
}

Вы также можете вызвать UseNamedDefaultConstraints, чтобы включить автоматическое именование всех ограничений по умолчанию. Обратите внимание, что если у вас есть существующие миграции, то следующая добавленная миграция переименует каждое ограничение по умолчанию в модели:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.UseNamedDefaultConstraints();
}


Полный список новинок можно посмотреть здесь

Источник: https://www.infoq.com/news/2025/06/dotnet-10-preview-5/
👍4
День 2345. #TipsAndTricks
Добавляем Описание в Параметризованные Тесты

Часто нам требуется протестировать несколько вариантов использования метода с разными данными, и для этого подойдут параметризованные тесты, например, Theory в xUnit.

См. подробнее про параметризованные тесты в xUnit.

При этом бывает полезно добавить не только тестовые данные, но и описание к каждому тестовому случаю. Рассмотрим, как это сделать.

Представим, что у нас есть такой тест:
[Theory]
[MemberData(nameof(InvalidFilters))]
public async Task ShouldNotAllowInvalidInvariants(
LimitFilters filters)
{

}


Тест принимает следующую запись с тестовыми данными:
public record LimitFilters(
Guid? WorkpieceNumber,
IEnumerable<int>? Ids,
IEnumerable<int>? Tools,
IEnumerable<int>? LimitIds);
}

Если мы выполним тест, мы увидим в окне выполнения теста что-то вроде следующего:
 ShouldNotAllowInvalidInvariants(filters: { WorkpieceNumber = … })
ShouldNotAllowInvalidInvariants(filters: { WorkpieceNumber = … })


Как видите, сложно понять, о чём каждый тестовый случай, особенно учитывая, что у нас есть коллекции в параметрах. Но обратите внимание, что из-за использования record, мы видим строковое представление записи, т.к. среда выполнения вызывает метод ToString() параметров. Мы можем использовать это.

Чтобы заставить среду выводить более осмысленное описание, мы можем добавить описание теста в LimitDesignerFilters и переопределить метод ToString():
public record LimitDesignerFilters(
string Description,
Guid? WorkpieceNumber,
IEnumerable<int>? Ids,
IEnumerable<int>? Tools,
IEnumerable<int>? LimitIds)
{
public override string ToString()
=> Description;
}


Теперь мы можем задать свойству Description описание каждого тестового случая:
public static TheoryData<LimitDesignerFilters> 
InvalidFilters =>
[
new("Workpiece is null", null, [1], [1], [1]),
new("Param1 is null", Guid.NewGuid(), null, [1], [1]),
];

Тогда в окне выполнения теста мы увидим следующее:
 ShouldNotAllowInvalidInvariants(filters: Param1 is null)
ShouldNotAllowInvalidInvariants(filters: Workpiece is null)

Тут всё ещё присутствует название параметра (filters), но всё же, понять, что проверяет каждый тест, уже гораздо проще.

Источник: https://steven-giesel.com/blogPost/80a53df4-a867-4202-916c-08e980f02505/adding-test-description-for-datadriven-tests-in-xunit
👍15
День 2346. #BestPractices
Пишем Хорошую Документацию. Начало

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

1. Знайте свою аудиторию (глубоко)
Прежде чем написать хоть слово, поймите, для кого вы пишете. Опытные или младшие разработчики? Внутренние команды, уже знакомые с экосистемой, или внешние пользователи, впервые сталкивающиеся с продуктом?
- Техническая компетентность: адаптируйте язык и глубину объяснения. Избегайте чрезмерно упрощённых объяснений для экспертов, но не предполагайте глубоких знаний предметной области от новичков.
- Цели: чего они пытаются достичь с помощью вашего ПО/API? Они ищут краткое руководство по началу работы, устранение конкретной ошибки, понимание расширенных концепций или интеграцию с другими системами? Структурируйте документы так, чтобы они отвечали этим конкретным потребностям.
- Контекст: где они обычно ищут информацию? Подойдёт ли интерактивный UI для API или лучше статические справочные страницы?
Поставьте себя на место разработчика. Какая информация вам нужна и как бы вы хотели, чтобы она была представлена?

2. Важна структура: создайте логическую основу
Даже самый точный контент бесполезен, если разработчики не могут его найти. Логическая структура обеспечивает ментальную карту, позволяя пользователям интуитивно ориентироваться.
- Чёткая иерархия: организуйте контент логически, начиная с вводных концепций (Начало работы, Установка) и переходя к конкретике (Справочник API, Руководства, Устранение неполадок). Используйте чёткие заголовки и подзаголовки (H1, H2, H3) последовательно.
- Оглавление: хорошо структурированное, всегда видимое (на боковой панели) оглавление позволяет пользователям видеть общую компоновку и быстро переходить к нужным разделам.
- Функциональность поиска: убедитесь, что поиск эффективно индексирует контент и выделяет ключевые слова в результатах. Разработчики часто знают, что им нужно, но не знают, где это находится.
- Перекрёстные ссылки: делайте ссылки на связанные концепции, руководства и API. Если вы упоминаете конечную точку API в руководстве, давайте прямую ссылку на неё. Это создаёт сеть знаний, а не изолированные хранилища.
- Информационная архитектура: планируйте поток. Рассмотрите возможность использования устоявшихся фреймворков, таких как Diátaxis (концепции, руководства, пояснения, справочные материалы), чтобы гарантировать, что вы систематически охватываете различные потребности в обучении.

3. Содержание: ясность, краткость и примеры
Основа документации — это содержание.
- Ясность: используйте понятный, недвусмысленный язык. Избегайте жаргона, где возможно, или чётко определите понятия при их первом использовании. Предпочитайте активный залог пассивному («Функция возвращает X» вместо «X возвращается функцией»).
- Краткость: разработчики заняты. Переходите к сути. Устраняйте бессмыслицу и ненужные слова. Используйте короткие предложения и абзацы. Маркеры и нумерованные списки отлично подходят для разбиения текста и выделения ключевой информации.
- Точность: неточная документация хуже, чем её отсутствие. Установите процессы проверки и обеспечьте обновление документов вместе с изменениями кода.
- Примеры кода: многочисленные, практичные, копируемые и вставляемые примеры, которые работают из коробки (включая необходимые импорты или настройки). Объясняйте, что делает код и почему он структурирован именно так. Покажите общие случаи использования, пограничные случаи и обработку ошибок. Если ваш API/SDK поддерживает несколько языков, предоставьте примеры на каждом из них.

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

Источник:
https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
👍4👎2
День 2347. #BestPractices
Пишем Хорошую Документацию. Продолжение

Начало

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

5. Поддерживайте точность и актуальность
Устаревшая документация подрывает доверие быстрее, чем что-либо ещё. Разработчики полагаются на правильность документов. Если они сталкиваются с несоответствиями, они полностью перестают доверять документации.
- Версионирование: чётко версионируйте документацию вместе с выпусками ПО/API. Позвольте пользователям легко переключаться между версиями.
- Документация-как-Код: относитесь к документации как к коду. Храните её в системе контроля версий (например, Git) вместе с исходным кодом, который она описывает. Это упрощает отслеживание изменений, просмотр обновлений и синхронизацию документов с выпусками кода. Интегрируйте обновления документации в свой конвейер CI/CD.
- Циклы обратной связи: упростите разработчикам возможность сообщать об ошибках или предлагать улучшения (например, кнопка «Предложить изменения», ссылающаяся на GitHub Issues или специальную форму обратной связи). Незамедлительно реагируйте на эти отзывы.
- Регулярные обзоры: запланируйте периодические обзоры документации для проверки точности, ясности и полноты.

6. Визуальная привлекательность и последовательность
Хотя суть является ключевой, представление тоже имеет значение. Красивые документы приятны и легко читаются.
- Чистый дизайн: используйте достаточно свободного пространства, читаемые шрифты и четкую визуальную иерархию. Избегайте загромождённых шаблонов.
- Единообразное форматирование: применяйте единый стиль для блоков кода, заметок, предупреждений, заголовков, ссылок и т. д. По возможности используйте руководство по стилю.
- Подсветка синтаксиса: необходима для примеров кода. Используйте чёткое и правильное выделение для соответствующих языков программирования.
- Наглядные пособия: используйте диаграммы (блок-схемы, диаграммы последовательности, диаграммы архитектуры), снимки экрана или короткие видеоролики, где они могут прояснить сложные концепции более эффективно, чем текст. Убедитесь, что визуальные материалы понятны, маркированы и актуальны.

7. Улучшите интерактивность и поисковую доступность
Выйдите за рамки статического текста:
- Интерактивные элементы: помимо пользовательского интерфейса API (например, Swagger), рассмотрите использование встроенных редакторов кода (например, CodeSandbox) или интерактивных руководств (например, Jupiter Notebooks).
- Расширенный поиск: для больших наборов документации разрешите пользователям фильтровать результаты поиска по категории, версии или разделу API.
- Виджеты "Была ли эта страница полезна?": собирайте быстрые отзывы об эффективности страницы.

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

Источник:
https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
👍5
День 2348. #BestPractices
Пишем Хорошую Документацию. Окончание

Начало
Продолжение

8. Используйте современные инструменты (вне зависимости от API)
Существует множество инструментов, которые помогут вам эффективно и результативно создавать документацию:
- Генераторы статических сайтов (SSG): такие инструменты, как MkDocs, Docusaurus, Hugo, Jekyll и Sphinx, являются популярным выбором. Они берут простые файлы разметки (например, Markdown) и создают профессионально выглядящие веб-сайты документации, с возможностью поиска. Они часто поставляются с темами, плагинами для поиска, поддержкой управления версиями и хорошо согласуются с подходом «Документация-как-Код».
- Платформы документации: такие сервисы, как Read the Docs, GitBook или Confluence, предлагают решения со встроенными функциями для совместной работы, управления версиями и презентации.
Выбирайте инструменты, которые соответствуют вашему рабочему процессу, размеру команды и техническим требованиям.

9. Используйте ИИ (осторожно)
Искусственный интеллект проникает в документацию. Генератор документации ИИ может стать мощным помощником, но крайне важно понимать его сильные и слабые стороны.
Потенциальные преимущества
- Генерация шаблонов: ИИ может быстро генерировать первоначальные черновики описаний функций/методов на основе комментариев или сигнатур кода (например, блоков ///summary).
- Саммари: ИИ может обобщать длинные технические объяснения или сложные разделы кода.
- Проверки согласованности: ИИ может помочь выявить несоответствия в терминологии или стиле в больших наборах документации.
- Перевод: сервисы перевода на другие языки совершенствуются, хотя человеческая проверка по-прежнему необходима для технической точности.

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

10. Развивайте культуру документирования
Отличная документация обычно не является продуктом одного человека, работающего в изоляции. Для этого требуются командные усилия и культурный сдвиг:
- Интеграция в рабочий процесс: сделайте документацию частью определения «готово» для новых функций или изменений API. Выделяйте на неё время во время спринтов.
- Поощряйте вклад: сделайте так, чтобы всем разработчикам (а не только преданным писателям) было легко вносить исправления и улучшения. Снизьте барьер для входа (например, простое редактирование Markdown через Git).
- Признавайте и вознаграждайте: признавайте и цените усилия, которые вложены в создание и поддержание высококачественной документации.
- Показывайте пример: если руководители групп и старшие разработчики отдают приоритет документации, другие, скорее всего, последуют их примеру.

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

Источник: https://dev.to/therealmrmumba/beyond-code-how-to-create-beautiful-documentation-that-developers-actually-love-best-practices-hc4
👍2
День 2349. #SystemDesign101 #Шпаргалка
Коды Состояний HTTP


1xx: Информационные
100 Continue (продолжайте);
101 Switching Protocols (переключение протоколов);
102 Processing (идёт обработка);
103 Early Hints (предварительный ответ).

2xx: Успех
200 OK (хорошо);
201 Created (создано);
202 Accepted (принято);
204 No Content (нет содержимого);
205 Reset Content (сбросить содержимое);
206 Partial Content (частичное содержимое);
207 Multi-Status (многостатусный);
208 Already Reported (уже сообщалось).

3xx: Перенаправление
300 Multiple Choices (несколько вариантов);
301 Moved Permanently (перемещено навсегда);
302 Found (найдено);
303 See Other (смотреть другое);
304 Not Modified (не изменялось);
305 Use Proxy (использовать прокси);
307 Temporary Redirect (временное перенаправление);
308 Permanent Redirect (постоянное перенаправление).

4xx: Ошибка клиента
400 Bad Request (некорректный запрос);
401 Unauthorized (не авторизован);
402 Payment Required (необходима оплата);
403 Forbidden (запрещено);
404 Not Found (не найдено);
405 Method Not Allowed (метод не поддерживается);
406 Not Acceptable (неприемлемо);
407 Proxy Authentication Required (необходима аутентификация прокси);
408 Request Timeout (истекло время ожидания);
409 Conflict (конфликт);
410 Gone (удалён);
411 Length Required (необходима длина);
412 Precondition Failed (условие ложно);
413 Payload Too Large (полезная нагрузка слишком велика);
414 URI Too Long (URI слишком длинный);
415 Unsupported Media Type (неподдерживаемый тип данных);
416 Range Not Satisfiable (диапазон не достижим);
417 Expectation Failed (ожидание не оправдалось);
422 Unprocessable Entity (необрабатываемый экземпляр);
423 Locked (заблокировано);
424 Failed Dependency (невыполненная зависимость);
425 Too Early (слишком рано);
426 Upgrade Required (необходимо обновление);
428 Precondition Required (необходимо предусловие);
429 Too Many Requests (слишком много запросов);
431 Request Header Fields Too Large (поля заголовка запроса слишком большие);
449 Retry With (повторить с);
499 Client Closed Request (клиент закрыл соединение).

5xx: Ошибка сервера
500 Internal Server Error (внутренняя ошибка сервера);
501 Not Implemented (не реализовано);
502 Bad Gateway (ошибочный шлюз);
503 Service Unavailable (сервис недоступен);
504 Gateway Timeout (шлюз не отвечает);
505 HTTP Version Not Supported (версия HTTP не поддерживается);
506 Variant Also Negotiates (вариант тоже проводит согласование);
507 Insufficient Storage (переполнение хранилища);
508 Loop Detected (обнаружено бесконечное перенаправление);
509 Bandwidth Limit Exceeded (исчерпана пропускная ширина канала);
510 Not Extended (отсутствует расширение);
511 Network Authentication Required (требуется сетевая аутентификация);
520 Unknown Error (неизвестная ошибка);
521 Web Server Is Down (веб-сервер не работает);
522 Connection Timed Out (соединение не отвечает);
523 Origin Is Unreachable (источник недоступен);
524 A Timeout Occurred (время ожидания истекло);
525 SSL Handshake Failed (SSL-рукопожатие не удалось);
526 Invalid SSL Certificate (недействительный сертификат SSL).

Коды состояний, которые не должны были существовать
218 This Is Fine - Отсылка к мему, означает, что ошибка не должна перехватываться сервером и отправляться клиенту.
418 I’m A Teapot – Введен в 1998 году как первоапрельская шутка (4/1/8). Означает, что чайник не может сварить кофе.
420 Enhance Your Calm – Нестандартный ответ, предлагающий клиенту «остыть». Сейчас заменён кодом 429.
451 Unavailable For Legal Reasons – Доступ к ресурсу закрыт по юридическим причинам, например, по требованию органов государственной власти или по требованию правообладателя в случае нарушения авторских прав. Является отсылкой к роману Рэя Брэдбери «451 градус по Фаренгейту».
530 Site Frozen – Сайт работает, но заморожен провайдером (например, за неоплату).

Источники:
-
https://github.com/ByteByteGoHq/system-design-101
-
https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP
👍19
День 2350. #ЗаметкиНаПолях
Разбираем Генераторы Исходного Кода. Начало
Генераторы исходного кода, представленные в C# 9, стали мощным инструментом для метапрограммирования в .NET, позволяя разработчикам генерировать дополнительный исходный код. Они запускаются во время компиляции для проверки кода и генерации дополнительных файлов кода C#. Затем эти файлы компилируются вместе с остальным кодом, что позволяет динамически создавать код на основе существующей кодовой базы. Генератор исходного кода можно использовать для различных целей, таких как скафолдинг, проверка и повышение читаемости и удобства обслуживания кода.

В C# 12 генераторы исходного кода получили дальнейшее развитие, позволяя реализовывать более сложные сценарии и повышая производительность за счёт сокращения шаблонного кода и улучшения проверок во время компиляции.
1. Инкрементные генераторы
Регенерируют код только при необходимости, что значительно повышает производительность. Кэшируют результаты предыдущих запусков и повторно генерируют код только при изменении базовых данных.

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

3. Улучшенная диагностика
Позволяет лучше сообщать об ошибках и предупреждениях непосредственно в сгенерированном коде. Разработчики получают чёткую обратную связь в процессе разработки, что упрощает отладку и поддержку сгенерированного кода.

4. Улучшения API Roslyn
Больше возможностей для анализа и изменения синтаксического дерева, позволяющих реализовывать более сложные сценарии генерации кода.

Простой генератор кода
1. Настройка проекта
Создадим проект библиотеки и добавим нужные NuGet-пакеты
dotnet new classlib -n MySourceGenerator
cd MySourceGenerator
dotnet add package Microsoft.CodeAnalysis.CSharp


2. Генератор кода
Понадобится класс, реализующий IIncrementalGenerator:
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

[Generator]
public class HelloWorldGenerator : IIncrementalGenerator
{
public void Initialize(
IncrementalGeneratorInitializationContext context)
{
var src =
"""
using System;
namespace HelloGenerated;
public static class HelloWorld
{
public static void SayHello()
=> Console.WriteLine("Hello from the generated code!");
}
""";

context.RegisterPostInitializationOutput(
ctx => ctx.AddSource(
"HelloWorldGenerated",
SourceText.From(src, Encoding.UTF8)));
}
}

Этот простой генератор добавляет класс HelloWorld с методом SayHello в ваш проект. Сгенерированный код будет скомпилирован с остальной частью проекта, что позволит вызывать HelloWorldGenerated.HelloWorld.SayHello() из вашего кода.

3. Интеграция с проектом
Создадим консольный проект:
dotnet new console -n UseSourceGenerator

Добавим ссылку на проект генератора из другого проекта:
<ProjectReference Include="..\MySourceGenerator\MySourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />

Заметьте два нестандартных атрибута:
- OutputItemType="Analyzer" - позволяет целевому проекту просматривать указанный проект в качестве анализатора;
- ReferenceOutputAssembly="false" - гарантирует, что целевой проект не будет ссылаться на DLL генератора кода во время компиляции.

Теперь сгенерированный класс HelloWorld доступен в консольном проекте.

4. Сборка и запуск
Соберём проект и запустим его. Мы увидим в консоли вывод из сгенерированного метода HelloWorld.SayHello():
// Program.cs

HelloGenerated.HelloWorld.SayHello();


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

Источник:
https://thecodeman.net/posts/source-generators-deep-dive
👍19
День 2351. #ЗаметкиНаПолях
Разбираем Генераторы Исходного Кода. Окончание

Начало

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

Предположим, у есть файл MyClass.cs со следующим содержимым:
// MyClass.cs
namespace MyNamespace;
public class MyClass
{
public void MyMethod()
{
// реализация метода
}
}


В проекте генератора кода читаем содержимое этого файла и генерируем на его основе дополнительный код:
using System.Text;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

[Generator]
public class FileBasedGenerator
: IIncrementalGenerator
{
public void Initialize(
IncrementalGeneratorInitializationContext context)
{
var srcFile = context
.AdditionalTextsProvider
.Where(f => f.Path.EndsWith("MyClass.cs"));

var content = srcFile
.Select((f, ct) => f.GetText(ct)?.ToString());

// используем код из файла
// для генерации нового кода
}
}

В клиентский проект нужно добавить файл MyClass.cs и ссылку на проект генератора кода, как показано в предыдущем посте.

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

2. Поддерживаемость
Сгенерированный код должен быть понятным и поддерживаемым. Убедитесь, что сгенерированный код соответствует тем же стандартам кодирования, что и остальная часть проекта. Рассмотрите возможность предоставления документации или комментариев в сгенерированном коде для облегчения будущего обслуживания.

3. Отладка и диагностика
Используйте расширенные возможности диагностики в C#12, чтобы предоставлять понятные сообщения об ошибках и предупреждения в генераторах исходного кода. Это поможет другим разработчикам понять и исправить проблемы, возникающие из-за сгенерированного кода.

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

5. Версионирование
При обновлении генераторов кода убедитесь, что сгенерированный код остаётся совместимым с предыдущими версиями. Рассмотрите возможность предоставления путей миграции, если сгенерированный код значительно изменится.

Источник: https://thecodeman.net/posts/source-generators-deep-dive
👍9
День 2352. #TipsAndTricks
Используем Roslyn Для Улучшения Кода. Начало

Следующий пример проверит все публичные типы решения на предмет, можно ли сделать их internal.

Создадим консольное приложение, и добавим следующие ссылки в .csproj:
<PackageReference Include="Microsoft.Build.Locator" Version="1.9.1" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="17.14.8" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.14.0" />


Код перебирает типы в решении, проверяет, есть ли ссылки на тип за пределами проекта. Если нет, тип может быть internal:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;

var path = @"Sample.sln";

Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();
var ws = MSBuildWorkspace.Create();
var sln = await
ws.OpenSolutionAsync(path);

// Перебираем проекты в решении
foreach (var proj in sln.Projects)
{
if (!proj.SupportsCompilation)
continue;

var comp = await proj.GetCompilationAsync();
if (comp is null)
continue;

// Проверяем, может ли тип быть internal
foreach (var symb in GetTypes(comp.Assembly))
{
// Вычисляем видимость
var visibility = GetVisibility(symb);
if (visibility is not Visibility.Public)
continue;

var canBeInternal = true;

// Проверяем внешние ссылки
var refs = await SymbolFinder
.FindReferencesAsync(symb, sln);
foreach (var rf in refs)
{
foreach (var loc in rf.Locations)
{
if (loc.Document.Project != proj)
canBeInternal = false;
}
}

if (canBeInternal)
Console.WriteLine(
$"{symb.ToDisplayString()} может быть internal");
}
}

static IEnumerable<ITypeSymbol> GetTypes(IAssemblySymbol assembly)
{
var result = new List<ITypeSymbol>();
foreach (var module in assembly.Modules)
DoNS(result, module.GlobalNamespace);

return result;

static void DoNS(List<ITypeSymbol> result, INamespaceSymbol ns)
{
foreach (var type in ns.GetTypeMembers())
DoType(result, type);

foreach (var nestedNs in ns.GetNamespaceMembers())
DoNS(result, nestedNs);
}

static void DoType(List<ITypeSymbol> result, ITypeSymbol s)
{
result.Add(s);
foreach (var type in s.GetTypeMembers())
DoType(result, type);
}
}

static Visibility GetVisibility(ISymbol s)
{
var vis = Visibility.Public;
switch (s.Kind)
{
case SymbolKind.Alias:
return Visibility.Private;
case SymbolKind.Parameter:
return GetVisibility(s.ContainingSymbol);
case SymbolKind.TypeParameter:
return Visibility.Private;
}

while (s is not null &&
s.Kind != SymbolKind.Namespace)
{
switch (s.DeclaredAccessibility)
{
case Accessibility.NotApplicable:
case Accessibility.Private:
return Visibility.Private;
case Accessibility.Internal:
case Accessibility.ProtectedAndInternal:
vis = Visibility.Internal;
break;
}

s = s.ContainingSymbol;
}

return vis;
}

enum Visibility
{
Public,
Internal,
Private,
}


Источник: https://www.meziantou.net/how-to-find-public-symbols-that-can-be-internal-using-roslyn.htm
👍11
День 2353. #TipsAndTricks
Используем Roslyn Для Улучшения Кода. Окончание
Начало
Вчера мы рассмотрели, как использовать Roslyn для поиска всех типов, которые могут быть обозначены внутренними, вместо публичных. Продолжим эту серию, и сегодня посмотрим, как найти все типы, которые могут быть отмечены как запечатанные (sealed). Обозначение типа как запечатанного может повысить производительность и безопасность, предотвращая дальнейшее наследование. Обратите внимание, что удаление модификатора sealed не является критическим изменением, поэтому вы можете спокойно помечать типы как запечатанные, не беспокоясь о проблемах совместимости, если позже решите удалить модификатор.

Создадим консольное приложение и добавим необходимые NuGet-пакеты в файл .csproj:
<PackageReference Include="Microsoft.Build.Locator" Version="1.9.1" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="17.14.8" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.14.0" />


Используем следующий код для анализа решения и поиска всех типов, которые можно запечатать. Код переберёт все типы в решении и попросит Roslyn найти производные классы для каждого. Если их нет, тип можно запечатать:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;

var path = @"Sample.sln";

Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();
var ws = MSBuildWorkspace.Create();
var sln = await ws.OpenSolutionAsync(path);

foreach (var proj in sln.Projects)
{
if (!proj.SupportsCompilation)
continue;

var comp = await proj.GetCompilationAsync();
if (comp is null)
continue;

foreach (var symb in GetTypes(comp.Assembly))
{
if (symb is not INamedTypeSymbol namedType)
continue;

if (namedType.TypeKind is not TypeKind.Class)
continue;

if (namedType.IsSealed)
continue;

var derivedClasses = await
SymbolFinder.FindDerivedClassesAsync(namedType, sln);
if (!derivedClasses.Any())
Console.WriteLine(
$"{symb.ToDisplayString()} может быть sealed");
}
}

static IEnumerable<ITypeSymbol>
GetTypes(IAssemblySymbol assembly)
{
var result = new List<ITypeSymbol>();
foreach (var module in assembly.Modules)
DoNS(result, module.GlobalNamespace);

return result;

static void DoNS(
List<ITypeSymbol> result,
INamespaceSymbol ns)
{
foreach (var t in ns.GetTypeMembers())
DoType(result, t);

foreach (var ns in ns.GetNamespaceMembers())
DoNS(result, ns);
}

static void DoType(
List<ITypeSymbol> result,
ITypeSymbol symb)
{
result.Add(symb);
foreach (var type in symb.GetTypeMembers())
DoType(result, type);
}
}


Источник:
https://www.meziantou.net/how-to-find-all-types-that-can-be-sealed-using-roslyn.htm
👍8
День 2354. #ЧтоНовенького
ToListAsync в Entity Framework Снова Быстрый

Если вы извлекаете очень большую строку NVARCHAR(MAX) через await ToListAsync(), Entity Framework будет делать что-то непонятное, что приводит к медленному запросу и большому объёму выделения памяти. На самом деле, виновник не совсем Entity Framework. Основную работу выполняет базовый Microsoft.Data.SqlClient. Проблема в том, что он неправильно использует SqlDataReader.

Замечание: это касается в основном пакета/реализации для SqlServer, поскольку он использует пакет Microsoft.Data.SqlClient.

Вот вырезка из бенчмарка от @Wraith2:
| Method | Mean      | Allocated |
|------- |----------:|----------:|
| Async | 757.51 ms | 101.49 MB |
| Sync | 39.40 ms | 80.14 MB |


Microsoft.Data.SqlClient 6.1.0
@Wraith2 исправил проблему серией пул-реквестов, на протяжении более 5 лет! Это невероятно. Конечно, он не работал над исправлениями непрерывно 5 лет, но всё равно это очень впечатляет. Последние заметки о выпуске можно прочитать здесь. Обратите внимание на материалы "Added packet multiplexing support to improve large data read performance" (Добавлена поддержка мультиплексирования пакетов для повышения производительности чтения больших объёмов данных).

А пул-реквест, исправляющий проблему, находится здесь.
Результаты такие:
| Async  |  49.45 ms | 101.51 MB |
| Sync | 40.09 ms | 80.14 MB |

Разрыв в выделении памяти в 20% всё ещё сохраняется, но время уже сопоставимо. Wraith2 и команда проделали потрясающую работу. Вы можете протестировать превью версию пакета, даже используя EF, поскольку прямые зависимости переопределяют транзитивные. Либо подождите следующего релиза EF, включающего новую версию Microsoft.Data.SqlClient 6.1.0, который должен уже скоро выйти.

Источник: https://steven-giesel.com/blogPost/dd7ab934-c311-45e0-9a04-9a28c624b957/tolistasync-is-fast-again-in-entity-framework-kind-of
👍20
ХОЧЕШЬ ПОВЫСИТЬ ГРЕЙД В 2025 ГОДУ? 🚀

Чтобы стать Senior C# разработчиком сегодня, нужно не только знать язык программирования и фреймворки. Нужно уметь строить гибкую архитектуру приложения, которую легко тестировать и менять под задачи бизнеса. Стань экспертом в построении гибкой архитектуры приложения!

👉 Стартуем 14 июля.

Курс ведет действующий архитектор и Principal Engineer Кирилл Ветчинкин.

Что будет на курсе:
Создадим полноценный микросервис
Разберем все тактические паттерны DDD
Реализуем Use Case и Domain Service
Напишем много тестов
Реализуем HTTP, gRPC и Kafka адаптеры

Полная программа ТУТ 👉 https://microarch.ru/courses/ddd?utm_source=posev&utm_medium=erid:2Vtzqwm7tdD&utm_campaign=3

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

А еще:
— Проверим все домашки
— Поддержим в чате
— Проведем живые разборы
— Ответим на все вопросы

🔥 Не откладывай свой рост на потом: https://microarch.ru/courses/ddd?utm_source=posev&utm_medium=erid:2Vtzqwm7tdD&utm_campaign=3

Реклама. ИП Ветчинкин К.Е. ИНН: 773376451099 Erid: 2Vtzqwm7tdD
#реклама
👍2
День 2355. #УрокиРазработки
Уроки 50 Лет Разработки ПО

Урок 57. Адаптируйте готовые шаблоны документов. Начало

Простые списки функций, запрашиваемых клиентами – хорошее начало для упорядочивания спецификации. Однако, есть шаблон спецификации требований к ПО (Software Requirements Specification, SRS), описанный в уже устаревшем стандарте IEEE 830. Шаблон содержит множество разделов, которые помогут систематизировать разнообразную информацию о требованиях. Однако, это не догма. Его можно и нужно менять, чтобы он лучше подходил для разрабатываемых вами систем.

РАСШИРЕННЫЙ ШАБЛОН СПЕЦИФИКАЦИИ ТРЕБОВАНИЙ К ПО
1. Введение.
1.1. Цель.
1.2. Условные обозначения.
1.3. Сфера применения проекта.
1.4. Ссылки.

2. Общее описание.
2.1. Перспектива продукта.
2.2. Классы и характеристики пользователей.
2.3. Операционная среда.
2.4. Ограничения и реализация.
2.5. Допущения и зависимости.

3. Системные функции.
3.x. Системная функция X.
3.x.1. Описание.
3.x.2. Функциональные требования.

4. Требования к данным.
4.1. Логическая модель данных.
4.2. Словарь данных.
4.3. Отчеты.
4.4. Целостность, хранение и удаление данных.

5. Требования к внешнему интерфейсу.
5.1. Пользовательские интерфейсы.
5.2. Программные интерфейсы.
5.3. Аппаратные интерфейсы.
5.4. Коммуникационные интерфейсы.

6. Атрибуты качества.
6.1. Удобство использования.
6.2. Производительность.
6.3. Безопасность.
6.4. Защищенность.
6.x. [другие].

7. Требования к интернационализации и локализации.

8. Другие требования.

Приложение A. Глоссарий.
Приложение Б. Модели анализа.


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

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

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

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

Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍4
День 2356. #УрокиРазработки
Уроки 50 Лет Разработки ПО

Урок 57. Адаптируйте готовые шаблоны документов. Окончание
Начало

Создание подходящего шаблона с чистого листа идёт медленно и бессистемно. Лучше начать с универсального шаблона, а затем адаптировать его к размеру, характеру и потребностям каждого проекта. Многие технические стандарты описывают шаблоны документов. К организациям, выпускающим технические стандарты по разработке ПО, относятся:
- Институт инженеров по электротехнике и электронике (Institute of Electrical and Electronics Engineers, IEEE);
- Международная организация по стандартизации (International Organization for Standardization, ISO);
- Международная электротехническая комиссия (International Electrotechnical Commission, IEC)

Например, международный стандарт ISO/IEC/IEEE 29148 содержит предлагаемые шаблоны для описания ПО, заинтересованных сторон и спецификаций системных требований (ISO/IEC/IEEE 2018). В сети вы найдёте множество шаблонов различных документов.

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

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

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

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

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

Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
День 2357. #ЧтоНовенького #NET10
Разбираем Возможности dotnet run app.cs. Начало
В этой серии подробно разберём новую функцию, появившуюся в .NET 10, для сборки и запуска одного C#-файла без необходимости предварительного создания проекта .csproj. Похоже, у неё пока нет окончательного названия. В некоторых источниках её называют однофайловым приложением (file-based app), иногда - «runfile».

Что это?
В .NET 10 добавлена возможность сохранить код в один файл .cs и запустить его, выполнив команду
dotnet run app.cs

См. представление новой функции здесь.

Доступные функции
Пока возможности относительно ограничены, но есть несколько точек расширения. Следующий пример демонстрирует простое хост-приложение Aspire без операций, реализованное в виде однофайлового приложения. Он ничего не делает, а просто демонстрирует все функции, доступные в .NET 10 превью 5:
#!/usr/bin/dotnet run

#:sdk Microsoft.NET.Sdk
#:sdk Aspire.AppHost.Sdk 9.3.0

#:package [email protected]

#:property UserSecretsId 2eec9746-c21a-4933-90af-c22431f35459

using Microsoft.Extensions.Configuration;

var builder = DistributedApplication.CreateBuilder(args);
builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
{ "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL", "https://localhost:21049" },
{ "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL", "https://localhost:22001" },
{ "ASPNETCORE_URLS", "https://localhost:17246" },
});

builder.Build().Run();

Этот скрипт демонстрирует все новые директивы, доступные в режиме запуска однофайлового приложения.

1. Создание исполняемого файла с помощью шебанг
#! (шебанг) и представляет директиву для систем *nix, позволяющую запускать файл напрямую. См. подробнее.

2. Добавление ссылок на SDK
Возможно с помощью директивы #:sdk. Также, как видите, можно указать версию. Заметьте, что в превью 5 она указывается через пробел, но, возможно, синтаксис поменяется для соответствия синтаксису добавления NuGet-пакетов.

3. Добавление ссылок на NuGet-пакеты
Возможно с помощью директивы #:package. Версия указывается после @. Можно использовать подстановочный знак (*) для версий:
#:package Aspire.Hosting.AppHost@*
#:package Aspire.Hosting.AppHost@9.*
#:package [email protected].*

Подстановочный знак обычно выберет наивысшую версию пакета.

4. Обновление свойств MSBuild
#:property используется для определения свойств MSBuild для приложения. Можно добавить любые свойства, которые обычно определяются в <PropertyGroup> файла .csproj. Здесь синтаксис, скорее всего тоже изменится. Вместо пробела нужно будет использовать =.

5. Ссылки на проекты (скоро)
В .NET 10 превью 6 должна появиться возможность ссылаться на проекты с помощью директивы #:project
#:project ../src/MyProject
#:project ../src/MyProject/MyProject.csproj

Возможность ссылаться на каталог проекта вместо полного пути к файлу .csproj — отличный способ уменьшить дублирование.

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

Источник:
https://andrewlock.net/exploring-dotnet-10-preview-features-1-exploring-the-dotnet-run-app.cs/
👍6
HTML Embed Code:
2025/07/14 16:37:49
Back to Top