День 1910. #ВопросыНаСобеседовании #ASP.NET #Architecture
Самые часто задаваемые вопросы на собеседовании по C#
31. Как бы вы подошли к обработке ошибок и отладке в распределённом приложении .NET Core с несколькими микросервисами?
Обработка ошибок и отладка в таком приложении может оказаться сложной задачей. Можно использовать несколько стратегий:
1. Централизованные логи.
Все микросервисы должны отправлять свои логи (естественно, структурированные) в централизованное место, где они сопоставляются и индексируются. Это позволит искать и визуализировать логи всех сервисов в одном месте.
2. Использование идентификаторов корреляции.
Идентификаторы корреляции (CorrelationId) — это уникальные идентификаторы, присваиваемые запросу. Затем этот идентификатор передаётся всем сервисам, участвующим в обработке этого запроса. Это позволяет отслеживать всю цепочку запросов и ответов.
3. Проверки работоспособности.
Проверки работоспособности можно реализовать для мониторинга состояния микросервисов. Они могут сообщать такие показатели, как время безотказной работы, загрузка ЦП, использование памяти и т. д.
4. Промежуточное ПО для обработки исключений.
В архитектуре микросервисов ошибки должны обрабатываться на уровне сервиса. Каждый сервис должен обрабатывать свои собственные исключения и возвращать подходящее сообщение об ошибке или код ответа.
Можно создать промежуточное ПО, которое обрабатывает каждый запрос микросервиса. Если во время выполнения запроса возникает исключение, это промежуточное ПО перехватит исключение и ответит подходящим сообщением об ошибке.
См. также «Улучшенная Обработка Исключений в ASP.NET Core 8.»
5. Использовать распределённую систему трассировки.
Она собирает данные и показатели от каждого микросервиса, а затем сопоставляет эти данные в комплексный визуальный обзор производительности системы. См. документацию.
Источник: https://dev.to/bytehide/net-core-interview-question-answers-4bc1
Самые часто задаваемые вопросы на собеседовании по C#
31. Как бы вы подошли к обработке ошибок и отладке в распределённом приложении .NET Core с несколькими микросервисами?
Обработка ошибок и отладка в таком приложении может оказаться сложной задачей. Можно использовать несколько стратегий:
1. Централизованные логи.
Все микросервисы должны отправлять свои логи (естественно, структурированные) в централизованное место, где они сопоставляются и индексируются. Это позволит искать и визуализировать логи всех сервисов в одном месте.
2. Использование идентификаторов корреляции.
Идентификаторы корреляции (CorrelationId) — это уникальные идентификаторы, присваиваемые запросу. Затем этот идентификатор передаётся всем сервисам, участвующим в обработке этого запроса. Это позволяет отслеживать всю цепочку запросов и ответов.
3. Проверки работоспособности.
Проверки работоспособности можно реализовать для мониторинга состояния микросервисов. Они могут сообщать такие показатели, как время безотказной работы, загрузка ЦП, использование памяти и т. д.
4. Промежуточное ПО для обработки исключений.
В архитектуре микросервисов ошибки должны обрабатываться на уровне сервиса. Каждый сервис должен обрабатывать свои собственные исключения и возвращать подходящее сообщение об ошибке или код ответа.
Можно создать промежуточное ПО, которое обрабатывает каждый запрос микросервиса. Если во время выполнения запроса возникает исключение, это промежуточное ПО перехватит исключение и ответит подходящим сообщением об ошибке.
См. также «Улучшенная Обработка Исключений в ASP.NET Core 8.»
5. Использовать распределённую систему трассировки.
Она собирает данные и показатели от каждого микросервиса, а затем сопоставляет эти данные в комплексный визуальный обзор производительности системы. См. документацию.
Источник: https://dev.to/bytehide/net-core-interview-question-answers-4bc1
👍21
День 1911. #ЗаметкиНаПолях
Реализуем Пессимистическую Блокировку в EF Core. Начало
Иногда, особенно в сценариях с высоким трафиком, вам абсолютно необходимо убедиться, что только один процесс может одновременно изменять какую-то часть данных.
Стандартный пример - система продажи билетов на популярное событие. При большом трафике билеты на одно место могут быть куплены одновременно несколькими людьми. В EF Core нет прямого механизма пессимистичной блокировки. Оптимистическая блокировка (с использованием версий) может работать, но в сценариях с высоким уровнем конфликтов это может привести к множеству повторных попыток.
Вот упрощённый фрагмент кода, иллюстрирующий проблему с билетами:
Пример выше надуманный, но суть понятна. Во время оформления заказа мы проверяем доступное количество для каждого типа билетов. Что, если мы получим одновременные запросы на покупку одного и того же билета? В худшем случае мы продадим билеты несколько раз. Одновременные запросы могут увидеть доступность билета и оба завершить оформление заказа.
Поскольку EF Core не предлагает пессимистическую блокировку напрямую, немного углубимся в старый добрый SQL. Заменим вызов GetAsync для получения билета на GetWithLockAsync:
Вызов GetWithLockAsync нужно обернуть в try-catch, чтобы корректно обрабатывать сбои блокировки, либо повторяя попытку, либо уведомляя пользователя.
Поскольку в EF Core нет встроенного способа добавления подсказок к запросам, приходится писать чистый SQL-запрос. Мы можем использовать оператор
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
Реализуем Пессимистическую Блокировку в EF Core. Начало
Иногда, особенно в сценариях с высоким трафиком, вам абсолютно необходимо убедиться, что только один процесс может одновременно изменять какую-то часть данных.
Стандартный пример - система продажи билетов на популярное событие. При большом трафике билеты на одно место могут быть куплены одновременно несколькими людьми. В EF Core нет прямого механизма пессимистичной блокировки. Оптимистическая блокировка (с использованием версий) может работать, но в сценариях с высоким уровнем конфликтов это может привести к множеству повторных попыток.
Вот упрощённый фрагмент кода, иллюстрирующий проблему с билетами:
public async Task Checkout(ShopCart cart)
{
await using var trans = await
context.BeginTransactionAsync();
…
var order = new Order();
foreach (CartItem item in cart.Items)
{
// Проверяем доступность билета
// Что, если два запроса проверят его в одно время?
var ticket = await ticketRepo.GetAsync(
item.TicketId);
ticket.UpdateQuantity(item.Quantity);
order.Add(ticket, item.Quantity, item.Price);
}
orderRepo.Insert(order);
await context.SaveChangesAsync();
await trans.CommitAsync();
…
}
Пример выше надуманный, но суть понятна. Во время оформления заказа мы проверяем доступное количество для каждого типа билетов. Что, если мы получим одновременные запросы на покупку одного и того же билета? В худшем случае мы продадим билеты несколько раз. Одновременные запросы могут увидеть доступность билета и оба завершить оформление заказа.
Поскольку EF Core не предлагает пессимистическую блокировку напрямую, немного углубимся в старый добрый SQL. Заменим вызов GetAsync для получения билета на GetWithLockAsync:
public async Task<Ticket> GetWithLockAsync(Guid id)
{
return await context
.Tickets
.FromSql(
$@"SELECT id, event_id, price, quantity
FROM tickets WHERE id = {id}
FOR UPDATE NOWAIT")
.SingleAsync();
}
FOR UPDATE NOWAIT
- суть пессимистической блокировки в PostgreSQL (и Oracle). Он сообщает базе данных: «Захвати эту строку, заблокируй её для меня, и, если она уже заблокирована, прямо сейчас выдай ошибку».Вызов GetWithLockAsync нужно обернуть в try-catch, чтобы корректно обрабатывать сбои блокировки, либо повторяя попытку, либо уведомляя пользователя.
Поскольку в EF Core нет встроенного способа добавления подсказок к запросам, приходится писать чистый SQL-запрос. Мы можем использовать оператор
SELECT FOR UPDATE
, чтобы получить блокировку на уровне выбранных строк. Любые конкурирующие транзакции будут заблокированы до тех пор, пока текущая транзакция не снимет блокировку. Это очень простой способ реализовать пессимистическую блокировку.Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
👍40
День 1912. #ЗаметкиНаПолях
Реализуем Пессимистическую Блокировку в EF Core. Окончание
Начало
Варианты блокировки и когда их использовать
Чтобы операция не ждала, пока другие транзакции освободят заблокированные строки, вы можете объединить
-
-
В SQL Server для аналогичного эффекта можно использовать подсказку запроса
А затем запросить блокировку только тех нужных строк:
Пессимистическая блокировка или сериализуемые транзакции
Сериализуемые транзакции - наивысший уровень согласованности данных. Они гарантируют, что транзакции выполняются так, как если бы они происходили строго последовательно, даже если происходят одновременно.
Когда транзакция начинается на уровне изоляции Serializable, БД блокирует все данные, к которым может получить доступ транзакция. Эти блокировки удерживаются до тех пор, пока вся транзакция не будет зафиксирована или отменена. Любая другая транзакция, пытающаяся получить доступ к заблокированным данным, будет заблокирована до тех пор, пока первая транзакция не снимет блокировки.
Хотя сериализуемые транзакции обеспечивают максимальную изоляцию, они сопряжены со значительными затратами:
- Блокировка большого объёма данных может серьезно повлиять на производительность, особенно в сценариях с высоким уровнем параллелизма.
- При большом количестве блокировок существует более высокий риск возникновения взаимоблокировок, когда две или более транзакции ожидают блокировок, удерживаемых друг другом.
Пессимистическая блокировка с помощью
Когда что использовать, зависит от ваших конкретных потребностей:
- Сериализуемые транзакции: идеально подходят для сценариев, связанных с конфиденциальными данными, где даже малейшее несоответствие недопустимо: финансовые операции или обновления медицинской документации.
- Пессимистическая блокировка: отличный выбор для большинства случаев использования, особенно в приложениях с высоким трафиком. Она обеспечивает высокую согласованность, сохраняя при этом хорошую производительность и снижая риски взаимоблокировок.
Итого
И сериализуемые транзакции, и пессимистическая блокировка с помощью
Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
Реализуем Пессимистическую Блокировку в EF Core. Окончание
Начало
Варианты блокировки и когда их использовать
Чтобы операция не ждала, пока другие транзакции освободят заблокированные строки, вы можете объединить
FOR UPDATE
с:-
NO WAIT
— вместо ожидания снятия блокировки, сообщает об ошибке, если строку невозможно заблокировать.-
SKIP LOCKED
— пропускает любые выбранные строки, которые нельзя заблокировать. Заметьте, что в этом случае вы будете получать противоречивые результаты из БД. Однако это может быть полезно, чтобы избежать конфликта блокировок, когда несколько потребителей обращаются к таблице, похожей на очередь. Реализация паттерна Outbox является отличным примером.В SQL Server для аналогичного эффекта можно использовать подсказку запроса
WITH (UPDLOCK, READPAST)
. Однако SQL Server блокирует все строки, которые ему необходимо прочитать, чтобы получить нужную. Таким образом, если не определить индекс для прямого доступа к строке, все предшествующие строки будут заблокированы. Допустим, есть таблица TBL с полем id. Вы хотите заблокировать строку с id=10. Необходимо определить индекс для id (или других полей, по которым выбираете):CREATE INDEX TBLINDEX ON TBL ( id );
А затем запросить блокировку только тех нужных строк:
SELECT * FROM TBL WITH (UPDLOCK, INDEX(TBLINDEX)) WHERE id=10;
Пессимистическая блокировка или сериализуемые транзакции
Сериализуемые транзакции - наивысший уровень согласованности данных. Они гарантируют, что транзакции выполняются так, как если бы они происходили строго последовательно, даже если происходят одновременно.
Когда транзакция начинается на уровне изоляции Serializable, БД блокирует все данные, к которым может получить доступ транзакция. Эти блокировки удерживаются до тех пор, пока вся транзакция не будет зафиксирована или отменена. Любая другая транзакция, пытающаяся получить доступ к заблокированным данным, будет заблокирована до тех пор, пока первая транзакция не снимет блокировки.
Хотя сериализуемые транзакции обеспечивают максимальную изоляцию, они сопряжены со значительными затратами:
- Блокировка большого объёма данных может серьезно повлиять на производительность, особенно в сценариях с высоким уровнем параллелизма.
- При большом количестве блокировок существует более высокий риск возникновения взаимоблокировок, когда две или более транзакции ожидают блокировок, удерживаемых друг другом.
Пессимистическая блокировка с помощью
SELECT FOR UPDATE
явно блокирует определённые строки, которые необходимо изменить. Другие транзакции, пытающиеся получить доступ к заблокированным строкам, блокируются до тех пор, пока блокировка не будет снята. Т.к. вы блокируете меньше ресурсов, вероятность взаимоблокировок снижается.Когда что использовать, зависит от ваших конкретных потребностей:
- Сериализуемые транзакции: идеально подходят для сценариев, связанных с конфиденциальными данными, где даже малейшее несоответствие недопустимо: финансовые операции или обновления медицинской документации.
- Пессимистическая блокировка: отличный выбор для большинства случаев использования, особенно в приложениях с высоким трафиком. Она обеспечивает высокую согласованность, сохраняя при этом хорошую производительность и снижая риски взаимоблокировок.
Итого
И сериализуемые транзакции, и пессимистическая блокировка с помощью
SELECT FOR UPDATE
— отличные варианты обеспечения согласованности данных. При выборе учитывайте требуемый уровень изоляции, потенциальное влияние на производительность и вероятность взаимоблокировок.Источник: https://www.milanjovanovic.tech/blog/a-clever-way-to-implement-pessimistic-locking-in-ef-core
👍18
День 1913. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Начало
Многие компании, занимающиеся разработкой ПО, используют методы Agile. Бизнес-аналитики и владельцы продуктов иногда применяют термин «Agile-требования». Но они не отличаются от требований в проектах с другим подходом.
Agile подразумевает, что мы адаптируемся к неизбежным изменениям, а не воображаем, что все требования можно досконально понять на раннем этапе и они будут оставаться неизменными на протяжении всего проекта. Но проекты требуют выполнения одних и тех же шагов по работе требованиями. Кто-то должен составить список заинтересованных сторон, собрать требования из различных источников и подтвердить, что решение, основанное на этих требованиях, достигнет бизнес-целей проекта. Основные различия в обработке требований в Agile- и традиционных проектах можно разделить на несколько категорий.
1. Роли и обязанности
В состав большинства традиционных проектных групп входит один или несколько бизнес-аналитиков, которые отвечают за работу по выявлению требований к проекту, анализу, спецификации, проверке и управлению или возглавляют её. Во многих Agile-проектах отсутствует официальная должность бизнес-аналитика. Разработка требований — совместный процесс, в котором участвуют владелец продукта, представители пользователей и другие заинтересованные стороны. Но за полноту информации в историях ответственность несут разработчики, а не бизнес-аналитики.
2. Терминология
Традиционные подходы обычно основаны на вариантах использования и функциональных требованиях. В Agile используют пользовательские истории, обобщенные описания функций или задач, разбитые на более мелкие пользовательские истории, приёмочные тесты и пожелания клиентов. Но это те же самые знания о требованиях, просто они по-другому называются.
3. Детальность документации
Agile-методы полагаются на доступность документации в нужный момент. Благодаря тесному сотрудничеству клиентов с разработчиками в Agile-проектах требования могут содержать меньше деталей, чем в традиционных проектах. Заинтересованные стороны могут сообщить все необходимые детали, когда это действительно потребуется, на встречах и в соответствующей документации. Некоторые пользовательские истории могут содержать мало подробностей, а сложные или важные функции могут прорабатываться более детально. Но не стоит чрезмерно полагаться только на устное общение. Каждой проектной группе необходимо создать достаточный объём документации, позволяющей решать задачи поддержки и совершенствования системы, но при этом не тратить время на запись информации, которую никто не будет использовать.
4. Время выполнения действий
Традиционные подходы предполагают создание довольно полного списка требований на ранней стадии проекта. Agile-команды предпочитают детализировать требования непосредственно перед реализацией определённой части функциональности. Это снижает риск того, что информация устареет или требования станут неактуальны, но затрудняет выявление зависимостей между требованиями и потенциальными архитектурными последствиями, которые желательно устранять как можно раньше, чтобы обеспечить стабильное развитие продукта. Agile-команды должны на ранних итерациях рассмотреть широкий спектр вопросов и подумать, какие важные архитектурные решения могут потребоваться. Также как можно раньше нужно начать изучение нефункциональных требований, чтобы проект достиг высокой производительности, доступности и других важных целей.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Начало
Многие компании, занимающиеся разработкой ПО, используют методы Agile. Бизнес-аналитики и владельцы продуктов иногда применяют термин «Agile-требования». Но они не отличаются от требований в проектах с другим подходом.
Agile подразумевает, что мы адаптируемся к неизбежным изменениям, а не воображаем, что все требования можно досконально понять на раннем этапе и они будут оставаться неизменными на протяжении всего проекта. Но проекты требуют выполнения одних и тех же шагов по работе требованиями. Кто-то должен составить список заинтересованных сторон, собрать требования из различных источников и подтвердить, что решение, основанное на этих требованиях, достигнет бизнес-целей проекта. Основные различия в обработке требований в Agile- и традиционных проектах можно разделить на несколько категорий.
1. Роли и обязанности
В состав большинства традиционных проектных групп входит один или несколько бизнес-аналитиков, которые отвечают за работу по выявлению требований к проекту, анализу, спецификации, проверке и управлению или возглавляют её. Во многих Agile-проектах отсутствует официальная должность бизнес-аналитика. Разработка требований — совместный процесс, в котором участвуют владелец продукта, представители пользователей и другие заинтересованные стороны. Но за полноту информации в историях ответственность несут разработчики, а не бизнес-аналитики.
2. Терминология
Традиционные подходы обычно основаны на вариантах использования и функциональных требованиях. В Agile используют пользовательские истории, обобщенные описания функций или задач, разбитые на более мелкие пользовательские истории, приёмочные тесты и пожелания клиентов. Но это те же самые знания о требованиях, просто они по-другому называются.
3. Детальность документации
Agile-методы полагаются на доступность документации в нужный момент. Благодаря тесному сотрудничеству клиентов с разработчиками в Agile-проектах требования могут содержать меньше деталей, чем в традиционных проектах. Заинтересованные стороны могут сообщить все необходимые детали, когда это действительно потребуется, на встречах и в соответствующей документации. Некоторые пользовательские истории могут содержать мало подробностей, а сложные или важные функции могут прорабатываться более детально. Но не стоит чрезмерно полагаться только на устное общение. Каждой проектной группе необходимо создать достаточный объём документации, позволяющей решать задачи поддержки и совершенствования системы, но при этом не тратить время на запись информации, которую никто не будет использовать.
4. Время выполнения действий
Традиционные подходы предполагают создание довольно полного списка требований на ранней стадии проекта. Agile-команды предпочитают детализировать требования непосредственно перед реализацией определённой части функциональности. Это снижает риск того, что информация устареет или требования станут неактуальны, но затрудняет выявление зависимостей между требованиями и потенциальными архитектурными последствиями, которые желательно устранять как можно раньше, чтобы обеспечить стабильное развитие продукта. Agile-команды должны на ранних итерациях рассмотреть широкий спектр вопросов и подумать, какие важные архитектурные решения могут потребоваться. Также как можно раньше нужно начать изучение нефункциональных требований, чтобы проект достиг высокой производительности, доступности и других важных целей.
Окончание следует…
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍3
Разожжём вечный спор вечером в пятницу с подачи Ника)))
Не учитывая кодстайл компании, какой вариант лично вам больше по душе (см. картинку в первом комментарии)?
Не учитывая кодстайл компании, какой вариант лично вам больше по душе (см. картинку в первом комментарии)?
Anonymous Poll
32%
1
11%
2
9%
3
49%
4
👍2
День 1914. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Окончание
Начало
5. Итоговое оформление требований
В общем случае пользовательские истории похожи на сценарии использования. Разница лишь в том, насколько тщательно вы их детализируете и записываете ли информацию. В традиционном проекте бизнес-аналитик может разработать набор функциональных требований на основе сценариев использования. Agile-команды конкретизируют каждую пользовательскую историю, определяя критерии приёмки и тесты, которые покажут, правильно ли разработчики реализовали её.
Функциональные требования и соответствующие им тесты — альтернативные варианты представления одной и той же информации. Требования определяют, что создавать; тесты описывают, как выяснить, демонстрирует ли система ожидаемое поведение. Наилучшие результаты получаются, когда разные люди пишут требования и тесты на основе одного и того же источника информации, например сценария использования.
Можно прибегнуть к альтернативной стратегии — записывать детали пользовательской истории в форме приёмочных тестов, которые затем проверяет тестировщик. Когда создаётся несколько представлений требований, нестыковки между ними помогают выявить проблемы. Если вы создаёте только одно представление, то независимо от выбранного метода будете вынуждены доверять его точности.
6. Расстановка приоритетов
Расстановка приоритетов учитывает относительную ценность каждого требования для клиента по сравнению с усилиями, риском и стоимостью его реализации. Традиционные проекты могут определить приоритеты требований на раннем этапе и в дальнейшем почти не пересматривать их. В Agile-проекте задачи приоритизируются непрерывно. Вы должны постоянно выбирать, что добавить в ближайшие итерации, а что может быть вообще исключено. На самом деле все команды, а не только те, кто практикует Agile, должны управлять оставшимися задачами, чтобы как можно быстрее передать клиенту максимально ценный для него продукт.
Есть ли разница?
Большинству клиентов неинтересно, как создаются приложения. Они хотят, чтобы продукты отвечали их потребностям, были эффективными, удобными и легко расширяемыми, а также удовлетворяли другие ожидания в отношении качества. Большинство методов разработки требований и управления ими в традиционных проектах в равной степени применимы и к Agile-проектам. Любая команда должна адаптировать методы разработки, чтобы они соответствовали их целям, культуре, среде и ограничениям.
В Agile всякое изменение добавляет независимую часть функциональности. Продукт — это система, которую вы итеративно совершенствуете, извлекая уроки из неудачных изменений и отыскивая лучшие способы реализации каждой его части. Выделение небольших требований, каждое из которых определяет ограниченное и функционирующее изменение, — совсем другой вид анализа, отличающийся от дробления большого интегрированного решения на фрагменты, вписывающиеся в итерации разработки.
Процесс бизнес-анализа в Agile-проектах тоже несколько иной. Несмотря на то, что устаревшие методы бизнес-анализа все ещё находят применение (анализ заинтересованных сторон и бизнес-правил, моделирование процессов и многое другое), их интеграция в поэтапный гибкий процесс оказывается большой проблемой для многих бизнес-аналитиков.
Успешный переход требует развития нового мышления. Роль бизнес-аналитика в Agile-проекте заключается не столько в том, чтобы заранее определить, что будет сделано, сколько в постоянном пересмотре условий в процессе разработки. Происходит постоянная оценка того, что должна или не должна делать команда, — компромиссов, необходимых для максимизации доставляемой ценности.
Однако в целом сведения о требованиях, используемые в Agile-проекте, качественно не отличаются от сведений в традиционном проекте. Разработка требований по-прежнему сводится к выявлению и передаче точной информации, чтобы участники проекта могли благополучно создать определённую часть продукта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 6. Agile-требования не отличаются от других. Окончание
Начало
5. Итоговое оформление требований
В общем случае пользовательские истории похожи на сценарии использования. Разница лишь в том, насколько тщательно вы их детализируете и записываете ли информацию. В традиционном проекте бизнес-аналитик может разработать набор функциональных требований на основе сценариев использования. Agile-команды конкретизируют каждую пользовательскую историю, определяя критерии приёмки и тесты, которые покажут, правильно ли разработчики реализовали её.
Функциональные требования и соответствующие им тесты — альтернативные варианты представления одной и той же информации. Требования определяют, что создавать; тесты описывают, как выяснить, демонстрирует ли система ожидаемое поведение. Наилучшие результаты получаются, когда разные люди пишут требования и тесты на основе одного и того же источника информации, например сценария использования.
Можно прибегнуть к альтернативной стратегии — записывать детали пользовательской истории в форме приёмочных тестов, которые затем проверяет тестировщик. Когда создаётся несколько представлений требований, нестыковки между ними помогают выявить проблемы. Если вы создаёте только одно представление, то независимо от выбранного метода будете вынуждены доверять его точности.
6. Расстановка приоритетов
Расстановка приоритетов учитывает относительную ценность каждого требования для клиента по сравнению с усилиями, риском и стоимостью его реализации. Традиционные проекты могут определить приоритеты требований на раннем этапе и в дальнейшем почти не пересматривать их. В Agile-проекте задачи приоритизируются непрерывно. Вы должны постоянно выбирать, что добавить в ближайшие итерации, а что может быть вообще исключено. На самом деле все команды, а не только те, кто практикует Agile, должны управлять оставшимися задачами, чтобы как можно быстрее передать клиенту максимально ценный для него продукт.
Есть ли разница?
Большинству клиентов неинтересно, как создаются приложения. Они хотят, чтобы продукты отвечали их потребностям, были эффективными, удобными и легко расширяемыми, а также удовлетворяли другие ожидания в отношении качества. Большинство методов разработки требований и управления ими в традиционных проектах в равной степени применимы и к Agile-проектам. Любая команда должна адаптировать методы разработки, чтобы они соответствовали их целям, культуре, среде и ограничениям.
В Agile всякое изменение добавляет независимую часть функциональности. Продукт — это система, которую вы итеративно совершенствуете, извлекая уроки из неудачных изменений и отыскивая лучшие способы реализации каждой его части. Выделение небольших требований, каждое из которых определяет ограниченное и функционирующее изменение, — совсем другой вид анализа, отличающийся от дробления большого интегрированного решения на фрагменты, вписывающиеся в итерации разработки.
Процесс бизнес-анализа в Agile-проектах тоже несколько иной. Несмотря на то, что устаревшие методы бизнес-анализа все ещё находят применение (анализ заинтересованных сторон и бизнес-правил, моделирование процессов и многое другое), их интеграция в поэтапный гибкий процесс оказывается большой проблемой для многих бизнес-аналитиков.
Успешный переход требует развития нового мышления. Роль бизнес-аналитика в Agile-проекте заключается не столько в том, чтобы заранее определить, что будет сделано, сколько в постоянном пересмотре условий в процессе разработки. Происходит постоянная оценка того, что должна или не должна делать команда, — компромиссов, необходимых для максимизации доставляемой ценности.
Однако в целом сведения о требованиях, используемые в Agile-проекте, качественно не отличаются от сведений в традиционном проекте. Разработка требований по-прежнему сводится к выявлению и передаче точной информации, чтобы участники проекта могли благополучно создать определённую часть продукта.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Как бы вы реализовали класс Calculator таким образом, чтобы впоследствии можно было бы добавлять другие операции по желанию?
#Quiz #BestPractices
#Quiz #BestPractices
Anonymous Quiz
17%
Передавать операции в метод Compute как выражения или делегаты
12%
Сделать класс Calculator абстрактным и наследовать классы с нужным набором операций от него
50%
Использовать паттерн Команда для инкапсуляции операций как команд
4%
Определить дополнительные операции в новом классе и внедрить его в класс Calculator
16%
Использовать паттерн Декоратор для добавления новой функциональности
👍19👎2
День 1915. #Оффтоп
Сегодня порекомендую очередное видео с ютуба, чтобы расслабиться после 6-дневной рабочей недели.
Мне всё больше и больше нравится этот чувак, ThePrimeTime)))
На этот раз он читает статью из 2016 года, где автор рассказывает о своей маме, программистке на COBOL для мейнфреймов. Рассказ об эпохе раннего программирования, где разработчики сталкивались с такими задачами, о которых нам не приходится и думать сейчас. Проблема в том, что до сих пор (!!!) есть крупные компании (например, банки), которые в своё время создали себе огромные системы на COBOL, и до сих пор поддерживают их за огромные деньги, потому что переписать это с нуля либо в принципе невозможно, либо стоит нереально дорого.
Мудрость дня: «То, что вы сейчас пишете либо будет выкинуто в течение полугода, либо останется жить на десятилетия.»
В общем, приятного просмотра https://youtu.be/qNytWcW38us.
Сегодня порекомендую очередное видео с ютуба, чтобы расслабиться после 6-дневной рабочей недели.
Мне всё больше и больше нравится этот чувак, ThePrimeTime)))
На этот раз он читает статью из 2016 года, где автор рассказывает о своей маме, программистке на COBOL для мейнфреймов. Рассказ об эпохе раннего программирования, где разработчики сталкивались с такими задачами, о которых нам не приходится и думать сейчас. Проблема в том, что до сих пор (!!!) есть крупные компании (например, банки), которые в своё время создали себе огромные системы на COBOL, и до сих пор поддерживают их за огромные деньги, потому что переписать это с нуля либо в принципе невозможно, либо стоит нереально дорого.
Мудрость дня: «То, что вы сейчас пишете либо будет выкинуто в течение полугода, либо останется жить на десятилетия.»
В общем, приятного просмотра https://youtu.be/qNytWcW38us.
YouTube
The Plight Of Cobol Mainframe Programmers
Recorded live on twitch, GET IN
### Article
https://ezalii.substack.com/p/interviewing-my-mother-a-mainframe
By: Tom Jordell
### My Stream
https://twitch.tv/ThePrimeagen
### Best Way To Support Me
Become a backend engineer. Its my favorite site
http…
### Article
https://ezalii.substack.com/p/interviewing-my-mother-a-mainframe
By: Tom Jordell
### My Stream
https://twitch.tv/ThePrimeagen
### Best Way To Support Me
Become a backend engineer. Its my favorite site
http…
👍6
День 1916. #ЧтоНовенького
Новый Формат Файлов Решений в Visual Studio
В превью версии Visual Studio 17.10 добавлен новый формат файла решения с расширением файла .slnx.
На протяжении десятилетий файл решения .sln основывался на собственном формате файла от Microsoft, многословном, трудночитаемом с кучей GUID. Вот пример:
Видно, что папки решений рассматриваются как проекты, конфигурация проекта дублируется для всех проектов, каждому проекту присваивается GUID, что делает файл неудобным для пользователя.
Оптимизированный формат файлов .slnx – отличное изменение:
Очевидно проще будет обрабатывать конфликты слияния. Поскольку GUID ссылается на другие GUID, традиционный формат .sln делает разрешение этих конфликтов кошмарным. В нашей компании мы даже не включаем файлы решений в систему контроля версий именно из-за этой проблемы.
Изменение перекликается с более ранним упрощением Microsoft формата файла проекта .csproj, включающим теперь только важную информацию, которую IDE не может вывести сама. Конечно, при изменении стандартных настроек конфигурации в файл будут добавлены дополнительные строки.
Пока формат в предварительной версии и рекомендуется избегать его использования в производственной среде. Он всё ещё может подвергаться изменениям на основе отзывов сообщества.
Чтобы попробовать его в Visual Studio 2022 17.10 превью 3 или более поздней версии, в меню Tools > Options > Preview Features (Инструменты > Параметры > Предварительные функции) найдите Use Solution File Persistence Model. Затем в меню File > Save YourSolution.sln As… (Файл > Сохранить YourSolution.sln как…) выберите тип файла .slnx. Заметьте, что этот тип файлов пока не связан с Visual Studio в Windows, поэтому привязку придётся настроить вручную.
Источник: https://blog.ndepend.com/slnx-the-new-net-solution-xml-file-format/
Новый Формат Файлов Решений в Visual Studio
В превью версии Visual Studio 17.10 добавлен новый формат файла решения с расширением файла .slnx.
На протяжении десятилетий файл решения .sln основывался на собственном формате файла от Microsoft, многословном, трудночитаемом с кучей GUID. Вот пример:
# Visual Studio Version 17
VisualStudioVersion = 17.10.34814.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "App\App.csproj", "{F95781B3-A973-4D19-9585-974DA143E6A1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{6EC5A7A1-CA0C-42AC-BB97-19EF01B3C68C}"
EndProject
…
Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {85AD0F43-BB53-4378-94F7-8A7DF5A990D5}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{06F979AA-0ABF-4B86-91D5-7E32B7F2A081} = {6C6714E6-D117-405B-9FFD-C4AF0643EA29}
{F95781B3-A973-4D19-9585-974DA143E6A1} = {6EC5A7A1-CA0C-42AC-BB97-19EF01B3C68C}
EndGlobalSection
…
EndGlobal
Видно, что папки решений рассматриваются как проекты, конфигурация проекта дублируется для всех проектов, каждому проекту присваивается GUID, что делает файл неудобным для пользователя.
Оптимизированный формат файлов .slnx – отличное изменение:
<Solution>
<Folder Name="/Test/">
<Project Path="UnitTests\UnitTests.csproj" Type="Classic C#" />
</Folder>
<Folder Name="/Application/">
<Project Path="App\App.csproj" Type="Classic C#" />
</Folder>
</Solution>
Очевидно проще будет обрабатывать конфликты слияния. Поскольку GUID ссылается на другие GUID, традиционный формат .sln делает разрешение этих конфликтов кошмарным. В нашей компании мы даже не включаем файлы решений в систему контроля версий именно из-за этой проблемы.
Изменение перекликается с более ранним упрощением Microsoft формата файла проекта .csproj, включающим теперь только важную информацию, которую IDE не может вывести сама. Конечно, при изменении стандартных настроек конфигурации в файл будут добавлены дополнительные строки.
Пока формат в предварительной версии и рекомендуется избегать его использования в производственной среде. Он всё ещё может подвергаться изменениям на основе отзывов сообщества.
Чтобы попробовать его в Visual Studio 2022 17.10 превью 3 или более поздней версии, в меню Tools > Options > Preview Features (Инструменты > Параметры > Предварительные функции) найдите Use Solution File Persistence Model. Затем в меню File > Save YourSolution.sln As… (Файл > Сохранить YourSolution.sln как…) выберите тип файла .slnx. Заметьте, что этот тип файлов пока не связан с Visual Studio в Windows, поэтому привязку придётся настроить вручную.
Источник: https://blog.ndepend.com/slnx-the-new-net-solution-xml-file-format/
👍24👎1
День 1917. #ЗаметкиНаПолях
Обмен Сообщениями с Помощью MassTransit
Создание распределённых приложений – дело непростое. Есть ряд потенциальных проблем, которые необходимо учитывать. Что делать, если в сети произошел сбой или сервис неожиданно прекратил работу? Способ взаимодействия частей распределённой системы становится критически важным.
Синхронная связь, когда сервисы напрямую обращаются друг к другу, хрупка. Она создаёт тесную связь, делая всё приложение уязвимым для отдельных точек отказа. Мы можем использовать распределённый обмен сообщениями. Одна из известных утилит для этого в мире .NET – MassTransit.
Шаблон обмена сообщениями запрос-ответ
Шаблон запрос-ответ аналогичен традиционному вызову функции, но по сети. Одна служба, запрашивающая сторона, отправляет сообщение запроса и ожидает соответствующего ответного сообщения.
Достоинства
1. Слабая связь: сервисам не требуются знания друг о друге, а только контракты сообщений. Это упрощает внесение изменений и масштабирование.
2. Прозрачность местоположения: запрашивающей стороне не нужно знать, где находится отвечающая сторона, что обеспечивает повышенную гибкость.
Недостатки
1. Задержка: накладные расходы на обмен сообщениями добавляют дополнительную задержку.
2. Сложность: внедрение системы обмена сообщениями и управление дополнительной инфраструктурой могут повысить сложность проекта.
MassTransit поддерживает шаблон запрос-ответ «из коробки». Мы можем использовать клиент запросов для отправки запросов и ожидания ответа. Клиент запроса является асинхронным. По умолчанию запрос также будет иметь тайм-аут 30 секунд, чтобы не допустить слишком длительного ожидания ответа.
Например, у нас система обработки заказов и необходимо получить статус заказа из сервиса управления заказами. С помощью MassTransit создадим клиента, реализующего
Он отправит на шину сообщение GetOrderStatusRequest:
И будет ожидать ответа:
В сервисе управления заказами ответчик (
Полный код примера есть в документации MassTransit.
Итого
Шаблон запрос-ответ — мощный инструмент при обмене сообщениями между сервисами. MassTransit значительно упрощает реализацию, гарантируя надежную доставку запросов и ответов.
Мы можем использовать запрос-ответ для реализации связи между модулями в модульном монолите. Однако не стоит доводить это до крайности, иначе система может страдать от увеличения задержки.
Источник: https://www.milanjovanovic.tech/blog/request-response-messaging-pattern-with-masstransit
Обмен Сообщениями с Помощью MassTransit
Создание распределённых приложений – дело непростое. Есть ряд потенциальных проблем, которые необходимо учитывать. Что делать, если в сети произошел сбой или сервис неожиданно прекратил работу? Способ взаимодействия частей распределённой системы становится критически важным.
Синхронная связь, когда сервисы напрямую обращаются друг к другу, хрупка. Она создаёт тесную связь, делая всё приложение уязвимым для отдельных точек отказа. Мы можем использовать распределённый обмен сообщениями. Одна из известных утилит для этого в мире .NET – MassTransit.
Шаблон обмена сообщениями запрос-ответ
Шаблон запрос-ответ аналогичен традиционному вызову функции, но по сети. Одна служба, запрашивающая сторона, отправляет сообщение запроса и ожидает соответствующего ответного сообщения.
Достоинства
1. Слабая связь: сервисам не требуются знания друг о друге, а только контракты сообщений. Это упрощает внесение изменений и масштабирование.
2. Прозрачность местоположения: запрашивающей стороне не нужно знать, где находится отвечающая сторона, что обеспечивает повышенную гибкость.
Недостатки
1. Задержка: накладные расходы на обмен сообщениями добавляют дополнительную задержку.
2. Сложность: внедрение системы обмена сообщениями и управление дополнительной инфраструктурой могут повысить сложность проекта.
MassTransit поддерживает шаблон запрос-ответ «из коробки». Мы можем использовать клиент запросов для отправки запросов и ожидания ответа. Клиент запроса является асинхронным. По умолчанию запрос также будет иметь тайм-аут 30 секунд, чтобы не допустить слишком длительного ожидания ответа.
Например, у нас система обработки заказов и необходимо получить статус заказа из сервиса управления заказами. С помощью MassTransit создадим клиента, реализующего
IRequestClient<T>
, для инициирования запроса:public class RequestController :
Controller
{
IRequestClient<StatusRequest> _client;
…
public async Task<IActionResult>
Get(string id, CancellationToken ct)
{
var response = await
_client.GetResponse<StatusResponse>(
new { id }, ct);
return Ok(response.Message);
}
}
Он отправит на шину сообщение GetOrderStatusRequest:
public record StatusRequest(string OrderId);
И будет ожидать ответа:
public record StatusResponse(
string OrderId,
short StatusCode,
string StatusText
}
В сервисе управления заказами ответчик (
IConsumer<T>
) будет прослушивать сообщения StatusRequest
. Он получает запрос, возможно запрашивает БД и отправляет сообщение StatusResponse
обратно на шину. Клиент будет ждать этого ответа и затем сможет обработать его соответствующим образом:public class StatusRequestConsumer :
IConsumer<StatusRequest>
{
public async Task Consume(
ConsumeContext<StatusRequest> ctx)
{
…
await ctx
.RespondAsync<StatusResponse>(new
{
// задаём свойства ответа
});
}
}
Полный код примера есть в документации MassTransit.
Итого
Шаблон запрос-ответ — мощный инструмент при обмене сообщениями между сервисами. MassTransit значительно упрощает реализацию, гарантируя надежную доставку запросов и ответов.
Мы можем использовать запрос-ответ для реализации связи между модулями в модульном монолите. Однако не стоит доводить это до крайности, иначе система может страдать от увеличения задержки.
Источник: https://www.milanjovanovic.tech/blog/request-response-messaging-pattern-with-masstransit
👍10
День 1918. #Шпаргалка
Шпаргалка по Форматированию Дат
Структура System.DateTime, доступная только для чтения, определённая в библиотеке базовых классов .NET (BCL), является ключом к обработке дат и времени в C#. Отформатировать дату и время для вывода можно, указав формат в методе ToString("…"). Например:
Выведет:
Ниже приведены краткие пояснения некоторых часто используемых спецификаторов формата:
Символы
Также есть несколько стандартных спецификаторов формата, каждый из которых представлен одной буквой
* - зависит от культуры, ниже примеры для культуры "en-US":
Любой другой символ приведёт к исключению FormatException во время выполнения.
Источник: https://blog.ndepend.com/csharp-datetime-format/
Шпаргалка по Форматированию Дат
Структура System.DateTime, доступная только для чтения, определённая в библиотеке базовых классов .NET (BCL), является ключом к обработке дат и времени в C#. Отформатировать дату и время для вывода можно, указав формат в методе ToString("…"). Например:
csharp
Console.WriteLine(
DateTime.Now.ToString("ddd, dd MMM yyyy h:mm"));
Выведет:
Wed 01 May 2024 8:01
Ниже приведены краткие пояснения некоторых часто используемых спецификаторов формата:
d
– день месяца от 1 до 31.dd
– день месяца от 01 до 31.ddd
- аббревиатура дня недели (Mon, Tue, …).dddd
- полный день недели (Monday, Tuesday, …).h
- 12-часовой формат часов.hh
- 12-часовой формат часов с ведущим 0.H
- 24-часовой формат часов.HH
- 24-часовой формат часов с ведущим 0.m
- минуты.mm
- минуты с ведущим 0.M
- номер месяца.MM
- номер месяца с ведущим 0.MMM
- краткое имя месяца (Dec).MMMM
- полное имя месяца (December).s
- секунды.ss
- секунды с ведущим 0.f
- десятые доли секунды.ff
- сотые доли секунды.t
- краткое AM/PM (A или P).tt
- AM/PM (AM или PM).yyyy
- год.z
- часов от UTC (+3).zz
- часов от UTC с ведущим 0 (+03).zzz
- часов и минут от UTC (+03:00).K
- аналогично zzz
, но адаптирует вывод в зависимости от типа времени (местное, UTC или не указано), поэтому может не вывести ничего.Символы
FHKMdfghmstyz%:/\"'
зарезервированы в строке формата даты и времени. Они интерпретируются как символы форматирования, за исключением случаев, когда используются внутри одинарных или двойных кавычек, либо экранированы \
. Все остальные символы последовательно интерпретируются как символьные литералы и остаются неизменными при выводе во время операции форматирования.Также есть несколько стандартных спецификаторов формата, каждый из которых представлен одной буквой
* - зависит от культуры, ниже примеры для культуры "en-US":
"d"
- короткая дата* (05/01/2024)"D"
- полная дата* (Wednesday, May 01, 2024)"f"
- полная дата, короткое время* (Wednesday, May 01, 2024 8:01 AM)"F"
- полная дата, полное время* (Wednesday, May 01, 2024 8:01:03 AM)"g"
- короткая дата, короткое время* (05/01/2024 8:01 AM)"G"
- короткая дата, полное время* (05/01/2024 8:01:03 AM)"m"
или "M"
- день/месяц* (May 1)"o"
или "O"
- полные дата/время по ISO 8601 (2024-05-01T08:01:03.7300000+04:00)"s"
- сортируемые дата/время по ISO 8601 (2024-05-01T08:03:01)"r"
или "R"
- дата/время по RFC1123 (Wed, 01 May 2024 08:01:03 GMT)"t"
- короткое время* (8:01 AM)"T"
- длинное время* (8:01:03 AM)"u"
- универсальный сортируемый формат даты/времени (2024-05-01 05:01:03Z)"U"
- универсальный полный формат даты/времени (Wednesday, May 01, 2024 5:01:03 AM)"y"
или "Y"
- месяц/год* (May 2024)Любой другой символ приведёт к исключению FormatException во время выполнения.
Источник: https://blog.ndepend.com/csharp-datetime-format/
👍34
День 1919. #ЧтоНовенького
Вышла Бета-Версия pl/dotnet
Пакет pl/dotnet добавляет в PostgreSQL полную поддержку C# и F#.
В первой открытой для публики бета-версии (версия 0.99) поддерживаются все операции PL: функции, процедуры, DO, SPI, триггеры, записи, SRF, OUT/INOUT, табличные функции и т. д. Также поддерживаются 40 из 46 стандартных пользовательских типов. Пакет полностью совместим с NPGSQL, а SPI предоставляется через API NPGSQL для максимальной совместимости. Это 100% бесплатное ПО под лицензией PostgreSQL.
pl/dotnet предоставляет вам всю мощь C# и F# в процедурах, функциях и триггерах PostgreSQL. Например:
C#:
F#
Поддержка функций
Поддерживаются все типы функций SQL:
- обычные процедуры и функции;
- полная поддержка функций триггера: аргументы триггера, старая/новая строка, перезапись строки (где это разрешено) и вся стандартная информация о триггере;
- функции, возвращающие множество, сопоставлены с итераторами в C# и последовательностями в F#;
- табличные функции, а также функции, возвращающие записи или наборы записей;
- полная поддержка функций IN/OUT/INOUT.
Поддержка типов данных
Поддерживаются 40 типов PostgreSQL, все из которых сопоставлены со стандартными типами dotnet NPGSQL. Единственными исключениями являются типы multirange, enum и struct, которые планируют добавить в будущем. Все типы данных допускают значение NULL, имеют полную поддержку массивов и полностью протестированы на C# и F#.
SPI (Server Programming Interface)
SPI pl/dotnet использует клиентскую библиотеку NPGSQL для обеспечения собственной реализации dotnet, максимально совместимой с существующим клиентским кодом. Вызовы NPGSQL перехватываются на очень низком уровне, чтобы заменить обработку клиентского протокола вызовами SPI; в остальном NPGSQL не был изменен. Авторы использовали набор тестов NPGSQL для тестирования пакета, что дало им хорошее представление об уровне совместимости.
Инструкции по установке находятся здесь.
Проект на GitHub.
Авторы приветствуют участие и отзывы сообщества в дискуссиях на GitHub.
Источник: https://www.postgresql.org/about/news/announcing-pldotnet-version-099-beta-2838/
Вышла Бета-Версия pl/dotnet
Пакет pl/dotnet добавляет в PostgreSQL полную поддержку C# и F#.
В первой открытой для публики бета-версии (версия 0.99) поддерживаются все операции PL: функции, процедуры, DO, SPI, триггеры, записи, SRF, OUT/INOUT, табличные функции и т. д. Также поддерживаются 40 из 46 стандартных пользовательских типов. Пакет полностью совместим с NPGSQL, а SPI предоставляется через API NPGSQL для максимальной совместимости. Это 100% бесплатное ПО под лицензией PostgreSQL.
pl/dotnet предоставляет вам всю мощь C# и F# в процедурах, функциях и триггерах PostgreSQL. Например:
C#:
CREATE OR REPLACE FUNCTION dynamic_record_generator_srf(lim INT8)
RETURNS SETOF record
AS $$
upperLimit = lim.HasValue ? lim : System.Int32.MaxValue;
for(long i = 0; i < upperLimit; i++)
{
yield return new object?[] {
i, $"Number is {i}" };
}
$$ LANGUAGE plcsharp;
F#
CREATE OR REPLACE FUNCTION dynamic_record_generator_srf_fsharp(lim INT8)
RETURNS SETOF record
AS $$
let upperLimit = Option.defaultValue (int64 System.Int32.MaxValue) lim
seq { for i in 0L .. upperLimit - 1L do yield [| box i; $"Number is {i}" |] }
$$ LANGUAGE plfsharp;
Поддержка функций
Поддерживаются все типы функций SQL:
- обычные процедуры и функции;
- полная поддержка функций триггера: аргументы триггера, старая/новая строка, перезапись строки (где это разрешено) и вся стандартная информация о триггере;
- функции, возвращающие множество, сопоставлены с итераторами в C# и последовательностями в F#;
- табличные функции, а также функции, возвращающие записи или наборы записей;
- полная поддержка функций IN/OUT/INOUT.
Поддержка типов данных
Поддерживаются 40 типов PostgreSQL, все из которых сопоставлены со стандартными типами dotnet NPGSQL. Единственными исключениями являются типы multirange, enum и struct, которые планируют добавить в будущем. Все типы данных допускают значение NULL, имеют полную поддержку массивов и полностью протестированы на C# и F#.
SPI (Server Programming Interface)
SPI pl/dotnet использует клиентскую библиотеку NPGSQL для обеспечения собственной реализации dotnet, максимально совместимой с существующим клиентским кодом. Вызовы NPGSQL перехватываются на очень низком уровне, чтобы заменить обработку клиентского протокола вызовами SPI; в остальном NPGSQL не был изменен. Авторы использовали набор тестов NPGSQL для тестирования пакета, что дало им хорошее представление об уровне совместимости.
Инструкции по установке находятся здесь.
Проект на GitHub.
Авторы приветствуют участие и отзывы сообщества в дискуссиях на GitHub.
Источник: https://www.postgresql.org/about/news/announcing-pldotnet-version-099-beta-2838/
👍31👎1
День 1920. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 7. Запись знаний дешевле, чем повторное их обретение
Приходилось ли вам исследовать существующие системы, чтобы выяснить, как их изменить? А кто из вас записывал всё, что узнал, для дальнейшего использования?
Это утомительное занятие. Но когда вы записываете всё, что узнали, эта информация может пригодиться вам или кому-то ещё, если придётся вернуться к ней. Лучше записывать знания о плохо документированной системе, чтобы постепенно накапливать их в процессе работы.
Боязнь рутины
Некоторые отказываются тратить время на документирование требований. Но самое сложное не в их записи, а в том, чтобы понять, что они собой представляют. То же с планом проекта. Самое сложное — продумать все действия, необходимые для завершения: определить результаты, задачи, необходимые ресурсы и т. д. Это ручная работа, требующая времени. Но на это уйдёт меньше времени, чем на передачу той же информации нескольким людям на протяжении всего времени существования проекта.
Преимущества письменного общения
Команды, практикующие методику гибкой разработки Scrum, проводят короткие ежедневные митинги, чтобы уточнить информацию о состоянии дел, выявить препятствия и согласовать действия на следующие 24 часа. Но после таких встреч не остаётся документов, что не способствует хоть сколько-нибудь долгосрочному планированию. Если вы уверены, что никому и никогда не понадобится пересматривать решения или сведения, которыми участники обменивались на собрании, то нет причин записывать их. В противном случае время на документирование этой информации не будет потрачено впустую.
Документация играет роль постоянной групповой памяти, ресурса, к которому члены команды могут обращаться в любой момент. В будущем записи помогут освежить воспоминания о намерениях и сравнить их с тем, что получилось на самом деле. Если впоследствии кому-то, кто не участвовал в разработке с самого начала, потребуется внести изменения в продукт, то хорошая документация позволит сэкономить время. А если кто-то до вас уже подготовил документацию, обязательно используйте эти сведения.
Чтобы не ждать, когда пользователи увидят работающее ПО и смогут предоставить полезные отзывы, можно передать задокументированные требования экспертам в предметной области и с их помощью выявить проблемы до того, как они будут реализованы в коде. Такая документация пригодится и для организации тестирования.
Иногда необходимо задокументировать определённую информацию в интересах самого разработчика. Если команда пишет ПО для организации, не задокументировавшей свои бизнес-правила, то код, работающий на основе этих правил, становится окончательным источником знаний бизнес-уровня. Разработчик, реализовавший код на основе этих бизнес-правил, становится экспертом в предметной области, к которому бизнес должен обращаться при изменении политики. Люди не должны извлекать знания бизнес-уровня из кода приложения.
Разумный баланс
Даже лучшие требования не могут заменить человеческое общение, но они, безусловно, оказывают существенную помощь. Запись информации не гарантирует её точности, полноты или неизменности. Однако наличие письменных документов увеличивает вероятность, что люди, получившие доступ к информации, придут к единому пониманию и впоследствии смогут освежить свои знания. Документация должна быть актуальной, точной и доступной для тех, кто в ней нуждается. Записывать информацию нужно, выдерживая соответствующий (не обязательно минимальный) уровень детализации. Когда детали известны и необходима точность, их обязательно нужно фиксировать в документации.
С опытом вы поймете, что мир далеко не черно-белый. Почти в любой ситуации глупо выбирать крайнюю позицию. Две крайности — описывать каждую часть проектной информации в мельчайших подробностях или вообще не иметь письменной документации — одинаково глупы. Помня, что запись знаний обходится дешевле, чем повторное их обретение, вы сохраняете свободу выбора в отношении того, какую информацию записать.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
Уроки 50 Лет Разработки ПО
Урок 7. Запись знаний дешевле, чем повторное их обретение
Приходилось ли вам исследовать существующие системы, чтобы выяснить, как их изменить? А кто из вас записывал всё, что узнал, для дальнейшего использования?
Это утомительное занятие. Но когда вы записываете всё, что узнали, эта информация может пригодиться вам или кому-то ещё, если придётся вернуться к ней. Лучше записывать знания о плохо документированной системе, чтобы постепенно накапливать их в процессе работы.
Боязнь рутины
Некоторые отказываются тратить время на документирование требований. Но самое сложное не в их записи, а в том, чтобы понять, что они собой представляют. То же с планом проекта. Самое сложное — продумать все действия, необходимые для завершения: определить результаты, задачи, необходимые ресурсы и т. д. Это ручная работа, требующая времени. Но на это уйдёт меньше времени, чем на передачу той же информации нескольким людям на протяжении всего времени существования проекта.
Преимущества письменного общения
Команды, практикующие методику гибкой разработки Scrum, проводят короткие ежедневные митинги, чтобы уточнить информацию о состоянии дел, выявить препятствия и согласовать действия на следующие 24 часа. Но после таких встреч не остаётся документов, что не способствует хоть сколько-нибудь долгосрочному планированию. Если вы уверены, что никому и никогда не понадобится пересматривать решения или сведения, которыми участники обменивались на собрании, то нет причин записывать их. В противном случае время на документирование этой информации не будет потрачено впустую.
Документация играет роль постоянной групповой памяти, ресурса, к которому члены команды могут обращаться в любой момент. В будущем записи помогут освежить воспоминания о намерениях и сравнить их с тем, что получилось на самом деле. Если впоследствии кому-то, кто не участвовал в разработке с самого начала, потребуется внести изменения в продукт, то хорошая документация позволит сэкономить время. А если кто-то до вас уже подготовил документацию, обязательно используйте эти сведения.
Чтобы не ждать, когда пользователи увидят работающее ПО и смогут предоставить полезные отзывы, можно передать задокументированные требования экспертам в предметной области и с их помощью выявить проблемы до того, как они будут реализованы в коде. Такая документация пригодится и для организации тестирования.
Иногда необходимо задокументировать определённую информацию в интересах самого разработчика. Если команда пишет ПО для организации, не задокументировавшей свои бизнес-правила, то код, работающий на основе этих правил, становится окончательным источником знаний бизнес-уровня. Разработчик, реализовавший код на основе этих бизнес-правил, становится экспертом в предметной области, к которому бизнес должен обращаться при изменении политики. Люди не должны извлекать знания бизнес-уровня из кода приложения.
Разумный баланс
Даже лучшие требования не могут заменить человеческое общение, но они, безусловно, оказывают существенную помощь. Запись информации не гарантирует её точности, полноты или неизменности. Однако наличие письменных документов увеличивает вероятность, что люди, получившие доступ к информации, придут к единому пониманию и впоследствии смогут освежить свои знания. Документация должна быть актуальной, точной и доступной для тех, кто в ней нуждается. Записывать информацию нужно, выдерживая соответствующий (не обязательно минимальный) уровень детализации. Когда детали известны и необходима точность, их обязательно нужно фиксировать в документации.
С опытом вы поймете, что мир далеко не черно-белый. Почти в любой ситуации глупо выбирать крайнюю позицию. Две крайности — описывать каждую часть проектной информации в мельчайших подробностях или вообще не иметь письменной документации — одинаково глупы. Помня, что запись знаний обходится дешевле, чем повторное их обретение, вы сохраняете свободу выбора в отношении того, какую информацию записать.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 2.
👍16
День 1921. #ЗаметкиНаПолях
Не Изменяйте Строки Подключения Вручную
Вам когда-нибудь приходилось изменять строку подключения в коде? Вы использовали регулярное выражение или другие манипуляции со строкой? Есть способ лучше.
Если вы делаете это в коде производственного приложения, лучше вообще пересмотреть то, как вы храните и используете строки подключения и должно ли быть более 1 значения конфигурации.
Но в какой-то момент вы можете столкнуться с такой необходимостью. У вас может быть настроена строка подключения, но вы хотите, например, изменить целевую базу данных. Это может быть связано с требованиями нескольких клиентов или интеграционным тестированием для динамических тестовых контейнеров, создаваемых «на лету», и т.д.
Поначалу вы можете подумать, что можно решить эту проблему, используя регулярное выражение. Это может сработать, но может и вызвать проблемы.
Лучше использовать построитель строки подключения. Это классы, которые наследуют от базового System.Data.Common.DbConnectionStringBuilder. Например, System.Data.SqlClient.SqlConnectionStringBuilder используется для подключения к Microsoft SQL Server, но есть версии и для других СУБД.
Сначала нам нужен доступ к значению строки подключения (она должна поступать из системы конфигурации приложения):
Это значение может быть использовано как аргумент конструктора построителя строк:
Мы можем изменять любые значения в строке подключения. Здесь обновим имя БД или исходный каталог:
Теперь можно получить доступ к обновлённой строке подключения и использовать её:
Обновлённое значение будет:
Как видите, изменился только исходный каталог. Остальная структура осталась прежней.
Источник: https://adamstorr.co.uk/blog/stop-using-regex-for-updating-connection-strings/
Не Изменяйте Строки Подключения Вручную
Вам когда-нибудь приходилось изменять строку подключения в коде? Вы использовали регулярное выражение или другие манипуляции со строкой? Есть способ лучше.
Если вы делаете это в коде производственного приложения, лучше вообще пересмотреть то, как вы храните и используете строки подключения и должно ли быть более 1 значения конфигурации.
Но в какой-то момент вы можете столкнуться с такой необходимостью. У вас может быть настроена строка подключения, но вы хотите, например, изменить целевую базу данных. Это может быть связано с требованиями нескольких клиентов или интеграционным тестированием для динамических тестовых контейнеров, создаваемых «на лету», и т.д.
Поначалу вы можете подумать, что можно решить эту проблему, используя регулярное выражение. Это может сработать, но может и вызвать проблемы.
Лучше использовать построитель строки подключения. Это классы, которые наследуют от базового System.Data.Common.DbConnectionStringBuilder. Например, System.Data.SqlClient.SqlConnectionStringBuilder используется для подключения к Microsoft SQL Server, но есть версии и для других СУБД.
Сначала нам нужен доступ к значению строки подключения (она должна поступать из системы конфигурации приложения):
var connStr = "Data Source=myServerAddress;Initial Catalog=db_1;User Id=my_user;Password=Pa55w0rd!;";
Это значение может быть использовано как аргумент конструктора построителя строк:
var builder =
new SqlConnectionStringBuilder(connStr);
Мы можем изменять любые значения в строке подключения. Здесь обновим имя БД или исходный каталог:
builder.InitialCatalog = "new_db";
Теперь можно получить доступ к обновлённой строке подключения и использовать её:
var newConnStr = builder.ConnectionString;
Обновлённое значение будет:
Data Source=myServerAddress;Initial Catalog=new_db_name;User ID=my_user;Password=Pa55w0rd!
Как видите, изменился только исходный каталог. Остальная структура осталась прежней.
Источник: https://adamstorr.co.uk/blog/stop-using-regex-for-updating-connection-strings/
👍20
День 1923. #ЗаметкиНаПолях
Отображаем Математические Формулы в HTML
Это довольно редкий случай (в зависимости от вашего домена), но иногда бывает нужно вывести на экран математическую формулу (и порой довольно сложную). На протяжении многих лет существовали различные рекомендации и спецификации W3C для языка математической разметки. MathML разработан как универсальная спецификация для математической записи во многих различных областях: браузеры, офисные пакеты, программы чтения EPUB, генераторы на основе LaTeX и т.п.
Самый ранний язык математической разметки (MathML) 1 был рекомендован в 1998 году и даже был включен в Mozilla 1.0. С тех пор появились ещё две версии MathML, причем второе издание MathML 3.0 было утверждено в качестве стандарта ISO в 2015 году.
К сожалению, широкая применимость, большая сложность и нежёсткие требования привели к тому, что поддержка MathML в браузерах была непоследовательной, а большие разделы спецификации были вообще нереализованы. Поэтому был разработан новый проект спецификации под названием MathML Core.
MathML Core — это попытка создать минимальную версию MathML, хорошо совместимую с современной веб-платформой с упором на тестируемость и совместимость. MathML 3 содержал 195 элементов; MathML Core ориентирован на около 30!
Язык представляет собой набор HTML элементов, заключённый в общего родителя – элемент <math>. Например, вот так будет выглядеть дробь «x в квадрате, делённое на 3» (к сожалению, Телеграм пока не поддерживает MathML 😊):
Поскольку это HTML-элементы, они позволяют включать в себя и другие HTML-элементы, например, поля для ввода (если вы, например, создаёте форму для теста по математике), а также позволяют использовать CSS для стилизации.
Единственная проблема в том, что писать элементы MathML некрасиво и довольно утомительно. Одной из самых популярных альтернатив является MathJax, который включает в себя целый движок отображения на JavaScript. Если вы разместите сценарий MathJax на своей странице, он просканирует HTML-код и заменит блоки с математическими выражениями эквивалентом в MathML. MathJax использует выражения TeX/LaTeX (внутри блоков $$..$$), которые гораздо короче и проще для понимания, чем MathML. Например, вот формула корней квадратного уравнения:
AsciiMath идёт ещё дальше, и позволяет писать более понятные выражения, как если бы мы писали их на одном из языков программирования. Например, вот та же формула корней квадратного уравнения в AsciiMath:
MathJax поддерживает и формат AsciiMath.
Если вам нужны более сложные уравнения, конечно, всё будет не так очевидно, но для большинства случаев это очень удобно. Единственная проблема в том, что используется не слишком удобное решение, когда код библиотеки сканирует весь HTML страницы и ищет там формулы. Сегодня так уже не делают.
Источник: https://andrewlock.net/rendering-math-in-html-mathml-mathml-core-and-asciimath/
Отображаем Математические Формулы в HTML
Это довольно редкий случай (в зависимости от вашего домена), но иногда бывает нужно вывести на экран математическую формулу (и порой довольно сложную). На протяжении многих лет существовали различные рекомендации и спецификации W3C для языка математической разметки. MathML разработан как универсальная спецификация для математической записи во многих различных областях: браузеры, офисные пакеты, программы чтения EPUB, генераторы на основе LaTeX и т.п.
Самый ранний язык математической разметки (MathML) 1 был рекомендован в 1998 году и даже был включен в Mozilla 1.0. С тех пор появились ещё две версии MathML, причем второе издание MathML 3.0 было утверждено в качестве стандарта ISO в 2015 году.
К сожалению, широкая применимость, большая сложность и нежёсткие требования привели к тому, что поддержка MathML в браузерах была непоследовательной, а большие разделы спецификации были вообще нереализованы. Поэтому был разработан новый проект спецификации под названием MathML Core.
MathML Core — это попытка создать минимальную версию MathML, хорошо совместимую с современной веб-платформой с упором на тестируемость и совместимость. MathML 3 содержал 195 элементов; MathML Core ориентирован на около 30!
Язык представляет собой набор HTML элементов, заключённый в общего родителя – элемент <math>. Например, вот так будет выглядеть дробь «x в квадрате, делённое на 3» (к сожалению, Телеграм пока не поддерживает MathML 😊):
<!-- родительский элемент -->
<math>
<!-- дробь: 1й дочерний элемент – числитель, 2й - знаменатель -->
<mfrac>
<!-- Число (1й дочерний) в степени (2й) -->
<msup>
<!-- mi - идентификатор (переменная или функция) -->
<mi>x</mi>
<!-- mn – числовая константа -->
<mn>2</mn>
</msup>
<mrow>
<mn>3</mn>
</mrow>
</mfrac>
</math>
Поскольку это HTML-элементы, они позволяют включать в себя и другие HTML-элементы, например, поля для ввода (если вы, например, создаёте форму для теста по математике), а также позволяют использовать CSS для стилизации.
Единственная проблема в том, что писать элементы MathML некрасиво и довольно утомительно. Одной из самых популярных альтернатив является MathJax, который включает в себя целый движок отображения на JavaScript. Если вы разместите сценарий MathJax на своей странице, он просканирует HTML-код и заменит блоки с математическими выражениями эквивалентом в MathML. MathJax использует выражения TeX/LaTeX (внутри блоков $$..$$), которые гораздо короче и проще для понимания, чем MathML. Например, вот формула корней квадратного уравнения:
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
AsciiMath идёт ещё дальше, и позволяет писать более понятные выражения, как если бы мы писали их на одном из языков программирования. Например, вот та же формула корней квадратного уравнения в AsciiMath:
`x = (-b-sqrt(b^2-4ac))/(2a)`
MathJax поддерживает и формат AsciiMath.
Если вам нужны более сложные уравнения, конечно, всё будет не так очевидно, но для большинства случаев это очень удобно. Единственная проблема в том, что используется не слишком удобное решение, когда код библиотеки сканирует весь HTML страницы и ищет там формулы. Сегодня так уже не делают.
Источник: https://andrewlock.net/rendering-math-in-html-mathml-mathml-core-and-asciimath/
👍12
День 1924. #Книги
Пособие по Основам Разработки
Тут в одном из чатов выложили преинтересную ссылку. В Майкрософт создали целое пособие по разработке и выложили его для всеобщего обозрения.
Это пособие призвано:
1. Повысить общую эффективность членов команды и всей команды в целом.
2. Уменьшить количество ошибок и избежать распространённых подводных камней.
3. Помочь стать лучшими инженерами и учиться на опыте других людей.
Здесь есть множество полезных статей, шпаргалок и чек-листов, например:
- Структура спринта: как подготовить проект и команду, какая работа делается на каждом этапе спринта.
- Чек-лист основ разработки: настроена ли система управления версиями, настроено ли тестирование и CI/CD, согласованы ли обзоры кода, учтена ли безопасность, настроен ли мониторинг системы
- Документация по Agile
- Документация по видам автоматизированного тестирования
- Советы и инструменты для проведения обзоров кода
- и многое, многое другое.
В общем, настоятельно советую к прочтению и себе отложил в закладки.
Пособие по Основам Разработки
Тут в одном из чатов выложили преинтересную ссылку. В Майкрософт создали целое пособие по разработке и выложили его для всеобщего обозрения.
Это пособие призвано:
1. Повысить общую эффективность членов команды и всей команды в целом.
2. Уменьшить количество ошибок и избежать распространённых подводных камней.
3. Помочь стать лучшими инженерами и учиться на опыте других людей.
Здесь есть множество полезных статей, шпаргалок и чек-листов, например:
- Структура спринта: как подготовить проект и команду, какая работа делается на каждом этапе спринта.
- Чек-лист основ разработки: настроена ли система управления версиями, настроено ли тестирование и CI/CD, согласованы ли обзоры кода, учтена ли безопасность, настроен ли мониторинг системы
- Документация по Agile
- Документация по видам автоматизированного тестирования
- Советы и инструменты для проведения обзоров кода
- и многое, многое другое.
В общем, настоятельно советую к прочтению и себе отложил в закладки.
microsoft.github.io
Engineering Fundamentals Playbook
ISE Engineering Fundamentals Engineering Playbook
👍28
День 1925. #ЗаметкиНаПолях
Полезные функции EF Core 8. Начало
Рассмотрим набор функций Entity Framework Core 8, которые могут быть полезны многим.
1. Поддержка сопоставления коллекций примитивов
Коллекция примитивов - это набор значений примитивного типа для провайдера БД (обычно это числа и строки, перечисления). Раньше этого можно было достичь с помощью специального кода, а теперь это доступно прямо из коробки. Например, теперь можно легко сопоставить свойство:
с его конфигурацией
Тогда для следующей таблицы:
EF сохранит коллекцию значений в (в данном случае) одной строке и распарсит их обратно в список объектов, которые вы ожидаете при запросе из БД, что довольно удобно. Это также будет работать для таких типов, как uint, bool, DateOnly, DateTime, Uri.
Uri? Да, функция будет работать и для типов, для которых в EF есть встроенные преобразователи!
2. Сложные типы
Говоря о типах объектов, которые хранятся и сопоставляются с реляционными БД с помощью Entity Framework, можно грубо выделить 3 категории:
- Типы с одним значением: int, string, Guid, DateTime, и т.п.
- Структурированные объекты, однозначно определённые с помощью ключа (сущности).
- Структурированные объекты, не определяемые ключом (типы-значения).
Начиная с EF Core 8 появился хороший способ сопоставления третьей категории объектов. Рассмотрим простой пример модели:
Конфигурация для сущности Product может выглядеть так:
Мы получим примерно такую таблицу:
Как видим, EF Core автоматически объединит свойства сложного объекта в соответствующее количество столбцов.
Примечание. В настоящее время невозможно сопоставить сложные типы с другой таблицей.
Пример выше может привести к проблемам из-за изменяемости объекта Price. Если продукт имеет две цены (например, розничную и оптовую), которым мы изначально назначили один и тот же экземпляр Price, при изменении значения одной цены результирующий оператор SQL фактически изменит обе. Эту проблему можно легко обойти, сделав базовую сущность Price неизменяемой (или записью). Вот тестовый пример этого поведения.
Окончание следует…
Источник: https://dateo-software.de/blog/entity-framework-8
Полезные функции EF Core 8. Начало
Рассмотрим набор функций Entity Framework Core 8, которые могут быть полезны многим.
1. Поддержка сопоставления коллекций примитивов
Коллекция примитивов - это набор значений примитивного типа для провайдера БД (обычно это числа и строки, перечисления). Раньше этого можно было достичь с помощью специального кода, а теперь это доступно прямо из коробки. Например, теперь можно легко сопоставить свойство:
public List<string> Tags { get; }
с его конфигурацией
builder.Property(o => o.Tags);
Тогда для следующей таблицы:
CREATE TABLE "Tweets" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Tweets" PRIMARY KEY AUTOINCREMENT,
"Name" TEXT NOT NULL,
"Tags" TEXT NOT NULL
);
EF сохранит коллекцию значений в (в данном случае) одной строке и распарсит их обратно в список объектов, которые вы ожидаете при запросе из БД, что довольно удобно. Это также будет работать для таких типов, как uint, bool, DateOnly, DateTime, Uri.
Uri? Да, функция будет работать и для типов, для которых в EF есть встроенные преобразователи!
2. Сложные типы
Говоря о типах объектов, которые хранятся и сопоставляются с реляционными БД с помощью Entity Framework, можно грубо выделить 3 категории:
- Типы с одним значением: int, string, Guid, DateTime, и т.п.
- Структурированные объекты, однозначно определённые с помощью ключа (сущности).
- Структурированные объекты, не определяемые ключом (типы-значения).
Начиная с EF Core 8 появился хороший способ сопоставления третьей категории объектов. Рассмотрим простой пример модели:
public class Price
{
public decimal Amount { get; set; }
public string Currency { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Price Price { get; set; }
}
Конфигурация для сущности Product может выглядеть так:
public void Configure(EntityTypeBuilder<Product> b)
{
b.ToTable("Products");
b.HasKey(p => p.Id);
…
b.ComplexProperty(p => p.Price);
}
Мы получим примерно такую таблицу:
CREATE TABLE "Products" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Products" PRIMARY KEY AUTOINCREMENT,
"Name" TEXT NOT NULL,
"Price_Amount" TEXT NOT NULL,
"Price_Currency" INTEGER NOT NULL
);
Как видим, EF Core автоматически объединит свойства сложного объекта в соответствующее количество столбцов.
Примечание. В настоящее время невозможно сопоставить сложные типы с другой таблицей.
Пример выше может привести к проблемам из-за изменяемости объекта Price. Если продукт имеет две цены (например, розничную и оптовую), которым мы изначально назначили один и тот же экземпляр Price, при изменении значения одной цены результирующий оператор SQL фактически изменит обе. Эту проблему можно легко обойти, сделав базовую сущность Price неизменяемой (или записью). Вот тестовый пример этого поведения.
Окончание следует…
Источник: https://dateo-software.de/blog/entity-framework-8
👍11
День 1926. #ЗаметкиНаПолях
Полезные функции EF Core 8. Окончание
Начало
3. Столбцы JSON
Сопоставление столбцов JSON уже было частью EF Core 7, поэтому оно не совсем новое, но есть некоторые улучшения. Предположим, мы создаём некий код авторизации с настраиваемыми ролями и политиками:
Чтобы сопоставить эти сущности с одной таблицей, а Policies - с одним столбцом, конфигурация будет такой:
При создании таблицы свойство Policies будет текстовым столбцом, содержащим JSON. Это было и в EF Core 7. В 8й версии поддерживаются запросы с использованием индексов массивов JSON, трансляция запросов к коллекциям JSON, содержащим сложные типы, запросы и обновления отдельных полей JSON. Также JSON колонки доступны в SQLite.
4. Контрольные значения
Контрольное значение заставляет EF Core проверять заданное значение вместо значения по умолчанию типа для свойства, которое необходимо установить. Предположим, что мы моделируем сущность ToDoItem:
По бизнес-правилам приоритет по умолчанию должен быть 100:
Т.к. свойство Priority не обнуляемое, а значение по умолчанию для int равно 0, у нас не будет возможности сохранить экземпляр ToDoItem со значением 0. EF Core идентифицировал бы 0 как значение по умолчанию, предположил, что свойство не установлено, и установил бы его в 100.
Если сделать свойство обнуляемым, то по умолчанию оно будет null. Но это заставит нас учитывать в коде, что Priority может null. В EF Core 8 можно настроить контрольное значение, т.е. значение, которое сообщает EF Core, что вместо него нужно вставить в БД значение по умолчанию:
Здесь мы проверяем контрольное значение -1 (которое не используется в бизнес-логике), поэтому сохранение экземпляра с приоритетом 0 фактически становится возможным без костылей в реальной модели объекта.
Источник: https://dateo-software.de/blog/entity-framework-8
Полезные функции EF Core 8. Окончание
Начало
3. Столбцы JSON
Сопоставление столбцов JSON уже было частью EF Core 7, поэтому оно не совсем новое, но есть некоторые улучшения. Предположим, мы создаём некий код авторизации с настраиваемыми ролями и политиками:
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
public IList<CustomPolicy>
Policies { get; set; };
}
public class CustomPolicy
{
public string Key { get; set; }
public bool Value { get; set; }
}
Чтобы сопоставить эти сущности с одной таблицей, а Policies - с одним столбцом, конфигурация будет такой:
public void Configure(EntityTypeBuilder<Role> b)
{
b.ToTable("Roles");
b.HasKey(o => o.Id);
…
b.OwnsMany(o => o.Policies, x =>
{
x.Property(p => p.Key);
x.Property(p => p.Value);
x.ToJson();
});
}
При создании таблицы свойство Policies будет текстовым столбцом, содержащим JSON. Это было и в EF Core 7. В 8й версии поддерживаются запросы с использованием индексов массивов JSON, трансляция запросов к коллекциям JSON, содержащим сложные типы, запросы и обновления отдельных полей JSON. Также JSON колонки доступны в SQLite.
4. Контрольные значения
Контрольное значение заставляет EF Core проверять заданное значение вместо значения по умолчанию типа для свойства, которое необходимо установить. Предположим, что мы моделируем сущность ToDoItem:
public class ToDoItem
{
public int Id { get; set; }
public string Name { get; set; }
public int Priority { get; set; }
}
По бизнес-правилам приоритет по умолчанию должен быть 100:
public void Configure(EntityTypeBuilder<ToDoItem> b)
{
b.ToTable("ToDoItems");
b.HasKey(o => o.Id);
…
b.Property(o => o.Priority)
.HasDefaultValueSql(100);
}
Т.к. свойство Priority не обнуляемое, а значение по умолчанию для int равно 0, у нас не будет возможности сохранить экземпляр ToDoItem со значением 0. EF Core идентифицировал бы 0 как значение по умолчанию, предположил, что свойство не установлено, и установил бы его в 100.
Если сделать свойство обнуляемым, то по умолчанию оно будет null. Но это заставит нас учитывать в коде, что Priority может null. В EF Core 8 можно настроить контрольное значение, т.е. значение, которое сообщает EF Core, что вместо него нужно вставить в БД значение по умолчанию:
…
b.Property(o => o.Priority)
.HasSentinel(-1)
.HasDefaultValueSql(100);
…
Здесь мы проверяем контрольное значение -1 (которое не используется в бизнес-логике), поэтому сохранение экземпляра с приоритетом 0 фактически становится возможным без костылей в реальной модели объекта.
Источник: https://dateo-software.de/blog/entity-framework-8
👍17