День 2404. #Карьера
8 Правил Прохождения Техсобеса. Начало
Советы от шведского разработчика/архитектора ПО Виктора 'viblo' Бломквиста. Советы, основаны на его опыте работы и собеседований на «обычные» должности разработчиков в Европе, особенно в Швеции, в небольших и средних технологических компаниях, где интервьюеры не стремятся вас унизить или подшутить над вами. Думаю, они подойдут и для многих наших компаний.
1. Практика — залог успеха
Главный совет - сначала попрактиковаться! Не в смысле сотни часов на LeetCode или заучивания документации по Kubernetes. В смысле «тренировочных собеседований», чтобы освоиться в обстановке собеседования. Многие (большинство?) разработчики просто не очень комфортно чувствуют себя на собеседованиях, и практика действительно помогает. Совершенно нормально нервничать, запинаться и т.п. Но нужно уметь рассказать интервьюеру, что вы знаете! Я как-то не смог рассказать, какими способами можно передавать данные между разными процессами. Да, просто нервничал и был неудачный день. Но при этом, несмотря на солидный опыт и резюме, такого кандидата сложно рекомендовать к найму, независимо от других качеств.
В начале карьеры собеседования – это стресс. А мы не любим делать то, что вызывает стресс, поэтому боимся практиковаться. Не повторяйте эту ошибку! Практика — залог успеха!
2. Резюме. Много коротких работ
У некоторых кандидатов много коротких работ (например, 3-5 работ продолжительностью год или меньше). Это не критично, и скорее всего, вас пригласят на собеседование в любом случае. Но вам нужно иметь веские аргументы, почему на этой работе будет по-другому. Если, конечно, компания специально не ищет человека на короткий срок. Продумайте свои доводы заранее. И, вероятно, лучше упомянуть об этом до того, как вас об этом спросят.
3. Резюме. Изменения ролей
Если ваша текущая должность отличается от той, на которую вы претендуете, необходимо это осветить и объяснить. Это также важно и тогда, когда вы претендуете на более «низкую» должность. Один из типичных случаев — кандидаты, которые сейчас возглавляют небольшую команду, но подают заявку на должность разработчика. Такие кандидаты и их опыт могут быть очень ценными, особенно при найме на должность старшего разработчика в небольшой компании, где от разработчиков ожидается больше ответственности, чем просто выполнение заранее спланированной задачи. В то же время есть несколько вещей, в которых вам следует убедить интервьюеров:
- что у вас всё ещё есть технические навыки. Руководители команд нередко теряют связь с технологиями, или, возможно, изначально не были так увлечены ими;
- объяснить, почему вы хотите вернуться к программированию на постоянной основе. То, что вы не можете найти работу тимлидом – не очень хорошее объяснение.
4. Не говорите слишком много
Особенно если вы в чём-то не уверены, длительное рассуждение не поможет. Звучит очевидно, правда? Но, видимо, на практике про это забывают! Бывают кандидаты, которые могут дать достойный ответ на простой вопрос, но затем заваливают свой собственный ответ, пускаясь в рассуждения.
Связанная с этим проблема: вы, как ни парадоксально, можете не дать интервьюеру достаточно узнать о вас. Часто лучший результат технического вопроса — это обсуждение с интервьюером(-ами) на равных. Это возможно только в том случае, если вы позволите интервьюеру говорить и не будете уходить в десятиминутный монолог на заданную тему. Это особенно важно, если у вас нет глубокого опыта в этой теме или вы не умеете хорошо выступать.
Окончание следует…
Источник: https://www.viblo.se/posts/interviewing/
8 Правил Прохождения Техсобеса. Начало
Советы от шведского разработчика/архитектора ПО Виктора 'viblo' Бломквиста. Советы, основаны на его опыте работы и собеседований на «обычные» должности разработчиков в Европе, особенно в Швеции, в небольших и средних технологических компаниях, где интервьюеры не стремятся вас унизить или подшутить над вами. Думаю, они подойдут и для многих наших компаний.
1. Практика — залог успеха
Главный совет - сначала попрактиковаться! Не в смысле сотни часов на LeetCode или заучивания документации по Kubernetes. В смысле «тренировочных собеседований», чтобы освоиться в обстановке собеседования. Многие (большинство?) разработчики просто не очень комфортно чувствуют себя на собеседованиях, и практика действительно помогает. Совершенно нормально нервничать, запинаться и т.п. Но нужно уметь рассказать интервьюеру, что вы знаете! Я как-то не смог рассказать, какими способами можно передавать данные между разными процессами. Да, просто нервничал и был неудачный день. Но при этом, несмотря на солидный опыт и резюме, такого кандидата сложно рекомендовать к найму, независимо от других качеств.
В начале карьеры собеседования – это стресс. А мы не любим делать то, что вызывает стресс, поэтому боимся практиковаться. Не повторяйте эту ошибку! Практика — залог успеха!
2. Резюме. Много коротких работ
У некоторых кандидатов много коротких работ (например, 3-5 работ продолжительностью год или меньше). Это не критично, и скорее всего, вас пригласят на собеседование в любом случае. Но вам нужно иметь веские аргументы, почему на этой работе будет по-другому. Если, конечно, компания специально не ищет человека на короткий срок. Продумайте свои доводы заранее. И, вероятно, лучше упомянуть об этом до того, как вас об этом спросят.
3. Резюме. Изменения ролей
Если ваша текущая должность отличается от той, на которую вы претендуете, необходимо это осветить и объяснить. Это также важно и тогда, когда вы претендуете на более «низкую» должность. Один из типичных случаев — кандидаты, которые сейчас возглавляют небольшую команду, но подают заявку на должность разработчика. Такие кандидаты и их опыт могут быть очень ценными, особенно при найме на должность старшего разработчика в небольшой компании, где от разработчиков ожидается больше ответственности, чем просто выполнение заранее спланированной задачи. В то же время есть несколько вещей, в которых вам следует убедить интервьюеров:
- что у вас всё ещё есть технические навыки. Руководители команд нередко теряют связь с технологиями, или, возможно, изначально не были так увлечены ими;
- объяснить, почему вы хотите вернуться к программированию на постоянной основе. То, что вы не можете найти работу тимлидом – не очень хорошее объяснение.
4. Не говорите слишком много
Особенно если вы в чём-то не уверены, длительное рассуждение не поможет. Звучит очевидно, правда? Но, видимо, на практике про это забывают! Бывают кандидаты, которые могут дать достойный ответ на простой вопрос, но затем заваливают свой собственный ответ, пускаясь в рассуждения.
Связанная с этим проблема: вы, как ни парадоксально, можете не дать интервьюеру достаточно узнать о вас. Часто лучший результат технического вопроса — это обсуждение с интервьюером(-ами) на равных. Это возможно только в том случае, если вы позволите интервьюеру говорить и не будете уходить в десятиминутный монолог на заданную тему. Это особенно важно, если у вас нет глубокого опыта в этой теме или вы не умеете хорошо выступать.
Окончание следует…
Источник: https://www.viblo.se/posts/interviewing/
👍17👎2
День 2405. #Карьера
8 Правил Прохождения Техсобеса. Окончание
Начало
5. Устаревший и неактуальный опыт
Как кандидату с опытом, вам нужно быть очень осторожным, говоря об устаревших/неактуальных технологиях или опыте, который не соответствует тому, что ищет интервьюер. Проблема не в том, что у вас есть такой опыт, а в том, что интервьюер опасается, что вы не знаете или не любите то, что требуется, и что вы не сможете адаптироваться к технологиям и процессам новой компании.
Например, ваши навыки написания скриптов для Linux могут быть всё ещё актуальны для компании, работающей с собственным Kubernetes, но нужно это объяснить! Не зацикливайтесь на том, как вы написали скрипт для установки 100 физических машин, потому что в данном контексте это бесполезно. Вместо этого вы можете рассказать о том, как глубокие знания Linux помогают вам писать оптимизированные и безопасные Docker-файлы или устранять сетевые неполадки при запуске в под.
6. Признавайте свои ограничения (но не слишком!)
Большинство кандидатов хорошо осознают свои возможности и знают свои границы. Это, в общем и целом, хорошо. В большинстве случаев, когда человек говорит о теме, в которой он не очень хорошо разбирается, это и так очевидно, так что можно прямо признать это. В то же время, не будьте слишком скромными и не нужно выставлять напоказ все свои слабости!
7. Примеры
Какой бы ни была тема, всегда полезно иметь возможность обратиться к реальному опыту. Будет здорово собрать несколько хороших примеров перед собеседованием — стоит подготовиться!
Например, вас спрашивают о вашем опыте в области событийно-управляемой архитектуры, но вы пока мало что сделали в этой области. Тем не менее, однажды вы внедрили очередь работ. Расскажите об этом и объясните, что вы сделали, как и почему. Другой вариант — вспомнить случай, когда вы рассматривали возможность использования событийно-управляемой архитектуры, но отказались от неё по разным причинам. А затем завершите разговор вопросом о том, как она работает в нанимающей вас компании. У всех технологий есть свои недостатки, но понимание этого часто отсутствует, поэтому это отличный способ продемонстрировать свою зрелость и дать им возможность рассказать о своей системе. Большинство интервьюеров любят рассказывать о том, как работает их уникальная система.
Но есть кое-что, на что стоит обратить внимание, если вы кандидат с опытом! Будьте очень осторожны, приводя примеры десятилетней давности. И будьте столь же осторожны, чтобы не использовать примеры, основанные на неправильных технологиях. Если вы претендуете на должность, связанную с микросервисами, не говорите о разработке приложений WinForms больше, чем это абсолютно необходимо, даже если вы думаете, что это в тему.
8. Вопросы
Едва ли не самый популярный совет для собеседований. Не забудьте задать несколько вопросов. В конце концов, возможно, вы будете там работать, и стоит попытаться заранее обнаружить какие-либо тревожные сигналы! Или, если не получится, хотя бы воспользуйтесь возможностью, чтобы интервьюеры рассказали о чём-то, что им интересно — почти все любят описывать свою текущую архитектуру, структуру команды или повседневную работу! Просто помните, что задаваемые вами вопросы отражают вас: что вас интересует, что вас волнует?
Собеседование окончено!
Получили работу?
Поздравляю! Вас наняли. Это значит, что они считают, что вы справитесь. Поначалу всё может быть очень запутанным и пугающим, особенно если вы не знакомы с этой ролью или типом компании. Со временем всё наладится, приложите все усилия и держитесь, и через пару месяцев вы почувствуете себя как дома.
Не получили работу?
Какой бы ни была причина, не расстраивайтесь! Иногда это выгодно обеим сторонам: возможно, вы не подошли, а может быть, компания оказалась не той, о которой вы мечтали. А может быть, это просто невезение. Однажды я не смог написать простой SQL-запрос, хотя имею огромный опыт написания и оптимизации гораздо более сложных запросов и хранимых процедур. Иногда звёзды просто не сходятся.
Источник: https://www.viblo.se/posts/interviewing/
8 Правил Прохождения Техсобеса. Окончание
Начало
5. Устаревший и неактуальный опыт
Как кандидату с опытом, вам нужно быть очень осторожным, говоря об устаревших/неактуальных технологиях или опыте, который не соответствует тому, что ищет интервьюер. Проблема не в том, что у вас есть такой опыт, а в том, что интервьюер опасается, что вы не знаете или не любите то, что требуется, и что вы не сможете адаптироваться к технологиям и процессам новой компании.
Например, ваши навыки написания скриптов для Linux могут быть всё ещё актуальны для компании, работающей с собственным Kubernetes, но нужно это объяснить! Не зацикливайтесь на том, как вы написали скрипт для установки 100 физических машин, потому что в данном контексте это бесполезно. Вместо этого вы можете рассказать о том, как глубокие знания Linux помогают вам писать оптимизированные и безопасные Docker-файлы или устранять сетевые неполадки при запуске в под.
6. Признавайте свои ограничения (но не слишком!)
Большинство кандидатов хорошо осознают свои возможности и знают свои границы. Это, в общем и целом, хорошо. В большинстве случаев, когда человек говорит о теме, в которой он не очень хорошо разбирается, это и так очевидно, так что можно прямо признать это. В то же время, не будьте слишком скромными и не нужно выставлять напоказ все свои слабости!
7. Примеры
Какой бы ни была тема, всегда полезно иметь возможность обратиться к реальному опыту. Будет здорово собрать несколько хороших примеров перед собеседованием — стоит подготовиться!
Например, вас спрашивают о вашем опыте в области событийно-управляемой архитектуры, но вы пока мало что сделали в этой области. Тем не менее, однажды вы внедрили очередь работ. Расскажите об этом и объясните, что вы сделали, как и почему. Другой вариант — вспомнить случай, когда вы рассматривали возможность использования событийно-управляемой архитектуры, но отказались от неё по разным причинам. А затем завершите разговор вопросом о том, как она работает в нанимающей вас компании. У всех технологий есть свои недостатки, но понимание этого часто отсутствует, поэтому это отличный способ продемонстрировать свою зрелость и дать им возможность рассказать о своей системе. Большинство интервьюеров любят рассказывать о том, как работает их уникальная система.
Но есть кое-что, на что стоит обратить внимание, если вы кандидат с опытом! Будьте очень осторожны, приводя примеры десятилетней давности. И будьте столь же осторожны, чтобы не использовать примеры, основанные на неправильных технологиях. Если вы претендуете на должность, связанную с микросервисами, не говорите о разработке приложений WinForms больше, чем это абсолютно необходимо, даже если вы думаете, что это в тему.
8. Вопросы
Едва ли не самый популярный совет для собеседований. Не забудьте задать несколько вопросов. В конце концов, возможно, вы будете там работать, и стоит попытаться заранее обнаружить какие-либо тревожные сигналы! Или, если не получится, хотя бы воспользуйтесь возможностью, чтобы интервьюеры рассказали о чём-то, что им интересно — почти все любят описывать свою текущую архитектуру, структуру команды или повседневную работу! Просто помните, что задаваемые вами вопросы отражают вас: что вас интересует, что вас волнует?
Собеседование окончено!
Получили работу?
Поздравляю! Вас наняли. Это значит, что они считают, что вы справитесь. Поначалу всё может быть очень запутанным и пугающим, особенно если вы не знакомы с этой ролью или типом компании. Со временем всё наладится, приложите все усилия и держитесь, и через пару месяцев вы почувствуете себя как дома.
Не получили работу?
Какой бы ни была причина, не расстраивайтесь! Иногда это выгодно обеим сторонам: возможно, вы не подошли, а может быть, компания оказалась не той, о которой вы мечтали. А может быть, это просто невезение. Однажды я не смог написать простой SQL-запрос, хотя имею огромный опыт написания и оптимизации гораздо более сложных запросов и хранимых процедур. Иногда звёзды просто не сходятся.
Источник: https://www.viblo.se/posts/interviewing/
👍18
День 2406. #Книги
«.NET 8: приложения и сервисы. Практика создания проектов с использованием Blazor, .NET MAUI, gRPC, GraphQL.» 2-е изд. (Прайс М. — Астана: «Спринт Бук», 2025).
С днём знаний всех!
От издательства «Питер» мне пришла ещё одна книга на обзор.
750-страничный фолиант «обо всём». Просто по главам:
1. Обзор .NET.
2. SQL Server
3. EF Core
4. NoSQL
5. Конкурентность
6. Популярные NuGet-библиотеки
7. Дата и интернационализация
8. Минимальные API
9. Кэширование
10. Azure Functions
11. SignalR
12. GraphQL
13. gRPC
14. ASP.NET Core
15. Blazor
16. MAUI
По правде сказать, я всегда с подозрением относился к произведениям издательства <Packt> (они выпустили оригинал этой книги в 2023г.). Дело в том, что несколько лет назад я глянул пару их книг, которые выходили чуть ли не сразу после релиза какой-либо технологии, и те книги показались мне довольно поверхностными. А ещё часто они быстро переиздавали книгу, например, по очередной версии .NET, просто наспех обновляя информацию (и далеко не всегда корректно).
Но эта книга меня приятно удивила. Не обращайте внимания, что оригинал выпущен в 2023 году. В переводе (что редкость) встречаются вставки и комментарии с более актуальными данными (например, что VS 2022 с августа 2024 года не поддерживается для Mac).
Конечно, учитывая то, что книга сразу обо всём, глубокого погружения в темы от неё ждать не стоит. Но, мне кажется, она подойдёт для старших джунов/мидлов (людей, знакомых с языком и основами разработки приложений) как обзор технологий. Просто узнать, что есть в мире .NET, «что это и с чем его едят», чтобы, к примеру, встретив где-то название технологии, примерно понимать, о чём идет речь. Кроме того, в каждой главе есть ссылки на документацию и материалы для более подробного изучения. Также много внимания уделяется практике создания небольших приложений и утилит для демонстрации материала. Отдельная «фишка» - блиц-опрос в конце каждой главы для проверки, как вы усвоили материал (в конце книги есть ответы).
В общем, для знакомства с обширным миром .NET рекомендую.
PS
Это вторая книга из «трилогии» Марка Прайса.
Первая называется «C#12 and .NET 8. Modern Cross-Platform Development Fundamentals». Это «основы основ». Я не нашёл перевода книги на русский язык.
А третья книга также доступна в издательстве Питер «.NET 8: инструменты и навыки. Лучшие практики и паттерны проектирования, отладки и тестирования».
Ещё раз спасибо за подарок издательству «Питер». Присылайте что-нибудь ещё 😊
«.NET 8: приложения и сервисы. Практика создания проектов с использованием Blazor, .NET MAUI, gRPC, GraphQL.» 2-е изд. (Прайс М. — Астана: «Спринт Бук», 2025).
С днём знаний всех!
От издательства «Питер» мне пришла ещё одна книга на обзор.
750-страничный фолиант «обо всём». Просто по главам:
1. Обзор .NET.
2. SQL Server
3. EF Core
4. NoSQL
5. Конкурентность
6. Популярные NuGet-библиотеки
7. Дата и интернационализация
8. Минимальные API
9. Кэширование
10. Azure Functions
11. SignalR
12. GraphQL
13. gRPC
14. ASP.NET Core
15. Blazor
16. MAUI
По правде сказать, я всегда с подозрением относился к произведениям издательства <Packt> (они выпустили оригинал этой книги в 2023г.). Дело в том, что несколько лет назад я глянул пару их книг, которые выходили чуть ли не сразу после релиза какой-либо технологии, и те книги показались мне довольно поверхностными. А ещё часто они быстро переиздавали книгу, например, по очередной версии .NET, просто наспех обновляя информацию (и далеко не всегда корректно).
Но эта книга меня приятно удивила. Не обращайте внимания, что оригинал выпущен в 2023 году. В переводе (что редкость) встречаются вставки и комментарии с более актуальными данными (например, что VS 2022 с августа 2024 года не поддерживается для Mac).
Конечно, учитывая то, что книга сразу обо всём, глубокого погружения в темы от неё ждать не стоит. Но, мне кажется, она подойдёт для старших джунов/мидлов (людей, знакомых с языком и основами разработки приложений) как обзор технологий. Просто узнать, что есть в мире .NET, «что это и с чем его едят», чтобы, к примеру, встретив где-то название технологии, примерно понимать, о чём идет речь. Кроме того, в каждой главе есть ссылки на документацию и материалы для более подробного изучения. Также много внимания уделяется практике создания небольших приложений и утилит для демонстрации материала. Отдельная «фишка» - блиц-опрос в конце каждой главы для проверки, как вы усвоили материал (в конце книги есть ответы).
В общем, для знакомства с обширным миром .NET рекомендую.
PS
Это вторая книга из «трилогии» Марка Прайса.
Первая называется «C#12 and .NET 8. Modern Cross-Platform Development Fundamentals». Это «основы основ». Я не нашёл перевода книги на русский язык.
А третья книга также доступна в издательстве Питер «.NET 8: инструменты и навыки. Лучшие практики и паттерны проектирования, отладки и тестирования».
Ещё раз спасибо за подарок издательству «Питер». Присылайте что-нибудь ещё 😊
👍12
День 2407. #ЧтоНовенького
Самая Мощная Новинка .NET 10
Вам знакомо чувство, когда то, чем вы пользовались годами, всегда казалось… незаконченным? Например, методы-расширения. Они, конечно, крутые, но редко когда по-настоящему нужны. Это костыли, скрывающиеся за маской чистого синтаксиса. C# 14 исправляет это с помощью членов-расширений.
Методы расширения всегда были полусырыми. Какой-то статический метод, замаскированный под что-то более интересное. Ни свойств, ни операторов, никакой логической группировки связанных расширений, кроме неуклюжих статических классов. Они никогда не ощущались как принадлежащие к типу. Члены-расширения - взрослая версия того, чем всегда хотели быть методы расширения.
Пример 1: Переписывание ToObservable
Если вы использовали MVVM с WPF, Xamarin, MAUI и т.д., вы, вероятно, писали это сотню раз:
Это работает, но выглядит странно; это не похоже на расширение существующего типа. А вот то же с использованием члена-расширения:
Видите разницу? Никакого беспорядка. Никаких странных «статических методов, притворяющихся реальными членами класса». Такое ощущение, что этим поведением владеет IEnumerable<T>.
Синтаксис
Пример 2: Добавляем свойства
Простой способ проверки на пустую коллекцию вместо !col.Any() или col.Count == 0 везде:
Использование:
То, чего методы расширения никогда не могли сделать чисто, теперь кажется естественной частью системы типов.
Пример 3: Статические Методы-Расширения
Вы можете добавлять статические члены к типам, которыми вы не владеете:
Как это работает изнутри
- Они не изменяют исходный тип.
- Компилятор и метаданные рассматривают их как «присоединённые» члены.
- Инструменты (например, IntelliSense) отображают их так, как будто они принадлежат типу.
- В основе всё по-прежнему безопасно и независимо, просто умнее.
Ограничения
- Никакой магии во время выполнения, они работают только во время компиляции.
- Нельзя добавлять поля или взаимодействовать с закрытыми членами.
- Поддержка инструментов вне современных IDE может немного отставать (пока).
Итого
Члены-расширения наконец-то делают расширения полноценными гражданами. Они позволяют API развиваться естественно. Они уменьшают беспорядок. Они делают код читаемым так, как будто он всегда был разработан таким образом. Это не просто синтаксический сахар, это корректировка курса. Они берут то, что начали методы расширения, и завершают работу. Более чистые API, легко обнаруживаемые функции, меньше служебных классов, скрывающихся в случайных пространствах имён, всё это просто кажется… правильным. Они не заставляют вас переосмысливать, как вы пишете часть кода. Они заставляют вас переосмыслить, как вы в целом проектируете его.
См. также «Используем Расширения C# 14 для Парсинга Enum»
Источник: https://blog.stackademic.com/net-10s-most-powerful-feature-isn-t-what-you-think-7d507dd254dc
Самая Мощная Новинка .NET 10
Вам знакомо чувство, когда то, чем вы пользовались годами, всегда казалось… незаконченным? Например, методы-расширения. Они, конечно, крутые, но редко когда по-настоящему нужны. Это костыли, скрывающиеся за маской чистого синтаксиса. C# 14 исправляет это с помощью членов-расширений.
Методы расширения всегда были полусырыми. Какой-то статический метод, замаскированный под что-то более интересное. Ни свойств, ни операторов, никакой логической группировки связанных расширений, кроме неуклюжих статических классов. Они никогда не ощущались как принадлежащие к типу. Члены-расширения - взрослая версия того, чем всегда хотели быть методы расширения.
Пример 1: Переписывание ToObservable
Если вы использовали MVVM с WPF, Xamarin, MAUI и т.д., вы, вероятно, писали это сотню раз:
public static class ObservableExtensions
{
public static ObservableCollection<T>
ToObservable<T>(this IEnumerable<T> source)
=> new ObservableCollection<T>(source);
}
Это работает, но выглядит странно; это не похоже на расширение существующего типа. А вот то же с использованием члена-расширения:
public static class EnumerableExtensions
{
extension(IEnumerable<T> collection)
{
public ObservableCollection<T> ToObservable()
=> new ObservableCollection<T>(collection);
}
}
Видите разницу? Никакого беспорядка. Никаких странных «статических методов, притворяющихся реальными членами класса». Такое ощущение, что этим поведением владеет IEnumerable<T>.
Синтаксис
public static class NameOfExtensionClass
{
extension(YourType obj)
{
// Методы, свойства,
// операторы и вложенные типы
}
}
Пример 2: Добавляем свойства
Простой способ проверки на пустую коллекцию вместо !col.Any() или col.Count == 0 везде:
public static class CollectionExtensions
{
extension(ICollection<T> collection)
{
public bool IsEmpty => this.Count == 0;
}
}
Использование:
if (myList.IsEmpty)
{
// Наконец-то код читается, как надо
}
То, чего методы расширения никогда не могли сделать чисто, теперь кажется естественной частью системы типов.
Пример 3: Статические Методы-Расширения
Вы можете добавлять статические члены к типам, которыми вы не владеете:
public static class DateTimeExtensions
{
extension(DateTime)
{
public static DateTime UnixEpoch
=> new DateTime(1970, 1, 1);
}
}
Как это работает изнутри
- Они не изменяют исходный тип.
- Компилятор и метаданные рассматривают их как «присоединённые» члены.
- Инструменты (например, IntelliSense) отображают их так, как будто они принадлежат типу.
- В основе всё по-прежнему безопасно и независимо, просто умнее.
Ограничения
- Никакой магии во время выполнения, они работают только во время компиляции.
- Нельзя добавлять поля или взаимодействовать с закрытыми членами.
- Поддержка инструментов вне современных IDE может немного отставать (пока).
Итого
Члены-расширения наконец-то делают расширения полноценными гражданами. Они позволяют API развиваться естественно. Они уменьшают беспорядок. Они делают код читаемым так, как будто он всегда был разработан таким образом. Это не просто синтаксический сахар, это корректировка курса. Они берут то, что начали методы расширения, и завершают работу. Более чистые API, легко обнаруживаемые функции, меньше служебных классов, скрывающихся в случайных пространствах имён, всё это просто кажется… правильным. Они не заставляют вас переосмысливать, как вы пишете часть кода. Они заставляют вас переосмыслить, как вы в целом проектируете его.
См. также «Используем Расширения C# 14 для Парсинга Enum»
Источник: https://blog.stackademic.com/net-10s-most-powerful-feature-isn-t-what-you-think-7d507dd254dc
👍31
День 2408. #Архитектура #БазыДанных
Postgres Слишком Хорош. Начало
Разные инди-разработчики и основатели стартапов лихорадочно собирают технологические стеки с Redis для кэширования, RabbitMQ для очередей, Elasticsearch для поиска и MongoDB, потому что… так надо? Оказывается, есть слон в комнате, которого никто не хочет замечать: Postgres может буквально всё это. И он делает это лучше, чем вы думаете.
Миф о том, что Postgres не масштабируется
Часто говорят, что Postgres — это «всего лишь РСУБД», и для решения специализированных задач нужны специализированные инструменты. Но Instagram масштабируется до 14 миллионов пользователей на одном экземпляре Postgres. Discord обрабатывает миллиарды сообщений. Notion построил весь свой продукт на Postgres. Только они не используют Postgres так, будто на дворе 2005 год.
1. Системы Очередей
В Postgres есть нативная поддержка LISTEN/NOTIFY, и он может обрабатывать очереди заданий лучше, чем многие специализированные решения:
Это обеспечивает обработку «ровно один раз» без дополнительной инфраструктуры.
2. Хранилище Ключ-значение
В Postgres есть JSONB, который выполняет большую часть того, что вам нужно:
Оператор @> - секретное оружие Postgres'а. Он быстрее большинства запросов NoSQL, и ваши данные остаются согласованными.
3. Полнотекстовый поиск
Кластеры Elasticsearch дороги и сложны. В Postgres есть встроенный полнотекстовый поиск, который поразительно хорош:
Это позволяет без проблем обрабатывать нечёткое соответствие, стемминг и ранжирование по релевантности.
4. Функции Реального Времени
Postgres LISTEN/NOTIFY обеспечивает обновления в реальном времени без дополнительных сервисов:
Ваше приложение отслеживает эти уведомления и отправляет обновления пользователям.
Окончание следует…
Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
Postgres Слишком Хорош. Начало
Разные инди-разработчики и основатели стартапов лихорадочно собирают технологические стеки с Redis для кэширования, RabbitMQ для очередей, Elasticsearch для поиска и MongoDB, потому что… так надо? Оказывается, есть слон в комнате, которого никто не хочет замечать: Postgres может буквально всё это. И он делает это лучше, чем вы думаете.
Миф о том, что Postgres не масштабируется
Часто говорят, что Postgres — это «всего лишь РСУБД», и для решения специализированных задач нужны специализированные инструменты. Но Instagram масштабируется до 14 миллионов пользователей на одном экземпляре Postgres. Discord обрабатывает миллиарды сообщений. Notion построил весь свой продукт на Postgres. Только они не используют Postgres так, будто на дворе 2005 год.
1. Системы Очередей
В Postgres есть нативная поддержка LISTEN/NOTIFY, и он может обрабатывать очереди заданий лучше, чем многие специализированные решения:
-- Простая очередь на Postgres
CREATE TABLE job_queue (
id SERIAL PRIMARY KEY,
job_type VARCHAR(50),
payload JSONB,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT NOW(),
processed_at TIMESTAMP
);
-- ACID-совместимая обработка заданий
BEGIN;
UPDATE job_queue
SET status = 'processing', processed_at = NOW()
WHERE id = (
SELECT id FROM job_queue
WHERE status = 'pending'
ORDER BY created_at
FOR UPDATE SKIP LOCKED
LIMIT 1
)
RETURNING *;
COMMIT;
Это обеспечивает обработку «ровно один раз» без дополнительной инфраструктуры.
2. Хранилище Ключ-значение
В Postgres есть JSONB, который выполняет большую часть того, что вам нужно:
-- Альтернатива Redis
CREATE TABLE kv_store (
key VARCHAR(255) PRIMARY KEY,
value JSONB,
expires_at TIMESTAMP
);
-- GIN индекс для запросов к JSON
CREATE INDEX idx_kv_value ON kv_store USING GIN (value);
SELECT * FROM kv_store
WHERE value @> '{"user_id": 12345}';
Оператор @> - секретное оружие Postgres'а. Он быстрее большинства запросов NoSQL, и ваши данные остаются согласованными.
3. Полнотекстовый поиск
Кластеры Elasticsearch дороги и сложны. В Postgres есть встроенный полнотекстовый поиск, который поразительно хорош:
-- Добавляем поиск к любой таблице
ALTER TABLE posts ADD COLUMN search_vector tsvector;
-- Авто-обновляемый индекс поиска
CREATE OR REPLACE FUNCTION update_search_vector()
RETURNS trigger AS $$
BEGIN
NEW.search_vector := to_tsvector('english',
COALESCE(NEW.title, '') || ' ' ||
COALESCE(NEW.content, '')
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Ранжированные результаты поиска
SELECT title, ts_rank(search_vector, query) as rank
FROM posts, to_tsquery('startup & postgres') query
WHERE search_vector @@ query
ORDER BY rank DESC;
Это позволяет без проблем обрабатывать нечёткое соответствие, стемминг и ранжирование по релевантности.
4. Функции Реального Времени
Postgres LISTEN/NOTIFY обеспечивает обновления в реальном времени без дополнительных сервисов:
-- Уведомления клиентов об изменениях
CREATE OR REPLACE FUNCTION notify_changes()
RETURNS trigger AS $$
BEGIN
PERFORM pg_notify('table_changes',
json_build_object(
'table', TG_TABLE_NAME,
'action', TG_OP,
'data', row_to_json(NEW)
)::text
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Ваше приложение отслеживает эти уведомления и отправляет обновления пользователям.
Окончание следует…
Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
👍49
День 2409. #Архитектура #БазыДанных
Postgres Слишком Хорош. Окончание
Начало
Скрытая стоимость «специализированных» инструментов
Помимо собственно платы за каждый специализированный сервис, есть много скрытых расходов на них.
Операционные расходы
- Мониторинг, обновления и отладка разных сервисов;
- Разные шаблоны масштабирования и режимы сбоев;
- Необходимость поддержки нескольких конфигураций;
- Раздельные процедуры резервного копирования и аварийного восстановления;
- Разные аспекты безопасности для каждого сервиса.
Сложности разработки
- Разные клиентские библиотеки и шаблоны подключения;
- Координация развёртываний нескольких сервисов;
- Несогласованность данных между системами;
- Сложные сценарии тестирования;
- Разные подходы к настройке производительности.
Если вы размещаете сервер самостоятельно, добавьте управление сервером, исправления безопасности и неизбежные сеансы отладки, когда Redis решает израсходовать всю вашу память, и т.п. Postgres делает всё это в одном сервисе, которым вы уже управляете.
Единая масштабируемая БД
Большинство людей не осознаёт, что один экземпляр Postgres может справиться с огромными объёмами данных. Речь идёт о миллионах транзакций в день, терабайтах данных и тысячах одновременных подключений. Вся магия кроется в архитектуре Postgres. Она невероятно хорошо масштабируется вертикально, а когда вам наконец понадобится горизонтальное масштабирование, у вас есть проверенные решения, такие как:
- Реплики чтения для масштабирования запросов;
- Партиционирование для больших таблиц;
- Организация пулов подключений для конкурентности;
- Логическая репликация для распределённых конфигураций.
Большинство компаний никогда до этого не доходят. Вас, вероятно, устроит один экземпляр, пока вы не начнёте обслуживать миллионы пользователей или сложные аналитические задачи. Сравните это с управлением отдельными сервисами, каждый из которых масштабируется по-разному.
Остановите оверинжиниринг с первого дня
Главная ловушка современной разработки — архитектурная астронавтика. Мы проектируем системы для задач, которых у нас нет, с трафиком, которого мы никогда не видели, для масштаба, которого, возможно, никогда не достигнем.
Начните с простого, с Postgres. Отслеживайте реальные узкие места, а не воображаемые. Масштабируйте конкретные компоненты, когда достигаете реальных ограничений. Добавляйте сложность только тогда, когда это решает реальные проблемы. Пользователям не важна ваша архитектура. Им важно, работает ли ваш продукт и решает ли он их проблемы.
Postgres может быть вашей основной БД, кэшем, очередью, поисковой системой и системой реального времени одновременно. И всё это с поддержкой ACID-транзакций во всех областях:
Итого
Postgres может быть слишком хорош сам по себе. Он настолько мощен, что делает большинство других сервисов ненужными для 90% приложений. Индустрия убедила нас, что нам нужны специализированные инструменты для всего, но, возможно, мы просто усложняем задачу.
Ваш стартап не должен быть витриной распределённых систем. Он должен решать реальные проблемы для реальных людей. Postgres позволяет вам сосредоточиться на этом. Поэтому в следующий раз, когда кто-то предложит добавить Redis «для производительности» или MongoDB «для гибкости», спросите: «Вы попробовали сначала сделать это в Postgres?»
Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
Postgres Слишком Хорош. Окончание
Начало
Скрытая стоимость «специализированных» инструментов
Помимо собственно платы за каждый специализированный сервис, есть много скрытых расходов на них.
Операционные расходы
- Мониторинг, обновления и отладка разных сервисов;
- Разные шаблоны масштабирования и режимы сбоев;
- Необходимость поддержки нескольких конфигураций;
- Раздельные процедуры резервного копирования и аварийного восстановления;
- Разные аспекты безопасности для каждого сервиса.
Сложности разработки
- Разные клиентские библиотеки и шаблоны подключения;
- Координация развёртываний нескольких сервисов;
- Несогласованность данных между системами;
- Сложные сценарии тестирования;
- Разные подходы к настройке производительности.
Если вы размещаете сервер самостоятельно, добавьте управление сервером, исправления безопасности и неизбежные сеансы отладки, когда Redis решает израсходовать всю вашу память, и т.п. Postgres делает всё это в одном сервисе, которым вы уже управляете.
Единая масштабируемая БД
Большинство людей не осознаёт, что один экземпляр Postgres может справиться с огромными объёмами данных. Речь идёт о миллионах транзакций в день, терабайтах данных и тысячах одновременных подключений. Вся магия кроется в архитектуре Postgres. Она невероятно хорошо масштабируется вертикально, а когда вам наконец понадобится горизонтальное масштабирование, у вас есть проверенные решения, такие как:
- Реплики чтения для масштабирования запросов;
- Партиционирование для больших таблиц;
- Организация пулов подключений для конкурентности;
- Логическая репликация для распределённых конфигураций.
Большинство компаний никогда до этого не доходят. Вас, вероятно, устроит один экземпляр, пока вы не начнёте обслуживать миллионы пользователей или сложные аналитические задачи. Сравните это с управлением отдельными сервисами, каждый из которых масштабируется по-разному.
Остановите оверинжиниринг с первого дня
Главная ловушка современной разработки — архитектурная астронавтика. Мы проектируем системы для задач, которых у нас нет, с трафиком, которого мы никогда не видели, для масштаба, которого, возможно, никогда не достигнем.
Начните с простого, с Postgres. Отслеживайте реальные узкие места, а не воображаемые. Масштабируйте конкретные компоненты, когда достигаете реальных ограничений. Добавляйте сложность только тогда, когда это решает реальные проблемы. Пользователям не важна ваша архитектура. Им важно, работает ли ваш продукт и решает ли он их проблемы.
Postgres может быть вашей основной БД, кэшем, очередью, поисковой системой и системой реального времени одновременно. И всё это с поддержкой ACID-транзакций во всех областях:
-- Одна транзакция, несколько операций
BEGIN;
INSERT INTO users (email) VALUES ('user@example.com');
INSERT INTO job_queue (job_type, payload)
VALUES ('send_welcome_email', '{"user_id": 123}');
UPDATE kv_store SET value = '{"last_signup": "2024-01-15"}'
WHERE key = 'stats';
COMMIT;
Итого
Postgres может быть слишком хорош сам по себе. Он настолько мощен, что делает большинство других сервисов ненужными для 90% приложений. Индустрия убедила нас, что нам нужны специализированные инструменты для всего, но, возможно, мы просто усложняем задачу.
Ваш стартап не должен быть витриной распределённых систем. Он должен решать реальные проблемы для реальных людей. Postgres позволяет вам сосредоточиться на этом. Поэтому в следующий раз, когда кто-то предложит добавить Redis «для производительности» или MongoDB «для гибкости», спросите: «Вы попробовали сначала сделать это в Postgres?»
Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
👍23
День 2410. #TipsAndTricks
Улучшаем Отладку EF Core с Помощью Тегов Запросов
Отладка запросов к БД в EF Core иногда напоминает поиск иголки в стоге сена. Когда ваше приложение генерирует десятки или сотни SQL-запросов, определить, какое LINQ-выражение сгенерировало тот или иной SQL-запрос, становится настоящей проблемой. К счастью, есть элегантное решение: теги запросов.
Теги запросов
Теги запросов позволяют добавлять пользовательские комментарии к SQL-запросам, сгенерированным LINQ-выражениями. Эти комментарии отображаются непосредственно в сгенерированном SQL-коде, что позволяет легко сопоставлять SQL-запрос с кодом, который его создал. Чтобы использовать эту функцию, необходимо применить метод TagWith к любому объекту IQueryable и передать описательный комментарий:
Это сгенерирует примерно такой SQL-запрос:
Вместо того, чтобы пытаться определить, какой код сгенерировал тот или иной SQL-запрос, вы можете сразу увидеть цель и источник каждого запроса в логах БД или профилировщике.
Вы можете объединить несколько вызовов TagWith для добавления дополнительного контекста, а также добавлять значения переменных во время выполнения:
Результат:
*CorrelationId помогает проследить весь путь пользовательского запроса (см. подробнее).
Примечания:
1. Хотя влияние TagWith на производительность минимально, избегайте чрезмерно длинных тегов или сложной интерполяции строк в горячих путях.
2. Теги запросов должны быть строковыми литералами, и не могут принимать параметры. Однако можно использовать интерполяцию строк (как видно выше), а также многострочные строковые литералы.
Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
Улучшаем Отладку EF Core с Помощью Тегов Запросов
Отладка запросов к БД в EF Core иногда напоминает поиск иголки в стоге сена. Когда ваше приложение генерирует десятки или сотни SQL-запросов, определить, какое LINQ-выражение сгенерировало тот или иной SQL-запрос, становится настоящей проблемой. К счастью, есть элегантное решение: теги запросов.
Теги запросов
Теги запросов позволяют добавлять пользовательские комментарии к SQL-запросам, сгенерированным LINQ-выражениями. Эти комментарии отображаются непосредственно в сгенерированном SQL-коде, что позволяет легко сопоставлять SQL-запрос с кодом, который его создал. Чтобы использовать эту функцию, необходимо применить метод TagWith к любому объекту IQueryable и передать описательный комментарий:
var оrders = context.Orders
.TagWith("Заказы больше $1000")
.Where(o => o.Total > 1000)
.Include(o => o.Customer)
.ToList();
Это сгенерирует примерно такой SQL-запрос:
-- Заказы больше $1000
SELECT [o].[Id], [o].[CustomerId], [o].[Total], [c].[Id], [c].[Name]
FROM [Orders] AS [o]
INNER JOIN [Customers] AS [c] ON [o].[CustomerId] = [c].[Id]
WHERE [o].[Total] > 1000.0
Вместо того, чтобы пытаться определить, какой код сгенерировал тот или иной SQL-запрос, вы можете сразу увидеть цель и источник каждого запроса в логах БД или профилировщике.
Вы можете объединить несколько вызовов TagWith для добавления дополнительного контекста, а также добавлять значения переменных во время выполнения:
var userOrders = context.Orders
.TagWith("Запрос с дэшборда")
.TagWith($"User ID: {userId}")
.TagWith($"CorrelationId: {correlationId}")
.Where(o => o.CustomerId == userId)
.OrderByDescending(o => o.OrderDate)
.Take(10)
.ToList();
Результат:
-- Запрос с дэшборда
-- User ID: 12345
-- CorrelationId: 987654321
SELECT TOP(10) [o].[Id], [o].[CustomerId], [o].[OrderDate]
FROM [Orders] AS [o]
WHERE [o].[CustomerId] = 12345
ORDER BY [o].[OrderDate] DESC
*CorrelationId помогает проследить весь путь пользовательского запроса (см. подробнее).
Примечания:
1. Хотя влияние TagWith на производительность минимально, избегайте чрезмерно длинных тегов или сложной интерполяции строк в горячих путях.
2. Теги запросов должны быть строковыми литералами, и не могут принимать параметры. Однако можно использовать интерполяцию строк (как видно выше), а также многострочные строковые литералы.
Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
1👍34
День 2411. #SystemDesign101 #Testing
9 Видов Тестирования API
1. Дымовое (Smoke) тестирование
Проводится после завершения разработки API. Просто проверяется работоспособность API и отсутствие сбоев.
2. Функциональное тестирование
Составление плана тестирования на основе функциональных требований и сравнение результатов с ожидаемыми.
3. Интеграционное тестирование
Тестирование объединяет несколько вызовов API для выполнения сквозных тестов. Тестируются внутрисервисные коммуникации и передача данных.
4. Регрессионное тестирование
Тестирование гарантирует, что исправления ошибок или новые функции не нарушат текущее поведение API.
5. Нагрузочное тестирование
Тестирование производительности приложений путем моделирования различных нагрузок. Затем мы можем рассчитать пропускную способность приложения.
6. Стресс-тестирование
Мы намеренно создаем высокие нагрузки на API и проверяем его работоспособность.
7. Тестирование безопасности
Тестирование API на предмет всех возможных внешних угроз.
8. Тестирование пользовательского интерфейса
Тестирование взаимодействия пользовательского интерфейса с API для обеспечения корректного отображения данных.
9. Фаззинг-тестирование
Этот метод внедряет недействительные или неожиданные входные данные в API и пытается вызвать сбой в его работе. Таким образом, выявляются уязвимости API.
Источник: https://blog.bytebytego.com/
9 Видов Тестирования API
1. Дымовое (Smoke) тестирование
Проводится после завершения разработки API. Просто проверяется работоспособность API и отсутствие сбоев.
2. Функциональное тестирование
Составление плана тестирования на основе функциональных требований и сравнение результатов с ожидаемыми.
3. Интеграционное тестирование
Тестирование объединяет несколько вызовов API для выполнения сквозных тестов. Тестируются внутрисервисные коммуникации и передача данных.
4. Регрессионное тестирование
Тестирование гарантирует, что исправления ошибок или новые функции не нарушат текущее поведение API.
5. Нагрузочное тестирование
Тестирование производительности приложений путем моделирования различных нагрузок. Затем мы можем рассчитать пропускную способность приложения.
6. Стресс-тестирование
Мы намеренно создаем высокие нагрузки на API и проверяем его работоспособность.
7. Тестирование безопасности
Тестирование API на предмет всех возможных внешних угроз.
8. Тестирование пользовательского интерфейса
Тестирование взаимодействия пользовательского интерфейса с API для обеспечения корректного отображения данных.
9. Фаззинг-тестирование
Этот метод внедряет недействительные или неожиданные входные данные в API и пытается вызвать сбой в его работе. Таким образом, выявляются уязвимости API.
Источник: https://blog.bytebytego.com/
👍10
День 2412. #Оффтоп
Berghain-Челлендж
Вот такой мистический билборд увидели на улицах Сан-Франциско. Попробуйте расшифровать.
Если у вас (как и у меня) ничего не получилось, то, видимо, вы мало знаете про AI 😊 На самом деле, это набор o200k токенов, которые все вместе складываются в URL listenlabs.ai/puzzle
Там вас ждёт следующий челлендж.
Berghain*-Челлендж
Berghain — ночной техно-клуб в Берлине. Вы — вышибала в ночном клубе. Ваша цель — заполнить заведение N=1000 людьми, соблюдая ограничения, например, «не менее 40% местных жителей Берлина» или «не менее 80% одеты в чёрное». Люди приходят по одному, и вам нужно сразу же решить, впускать их или нет. Ваша задача — заполнить заведение, получив как можно меньше отказов, соблюдая при этом все минимальные требования.
Как это работает
- Люди приходят последовательно с бинарными признаками (например, женщина/мужчина, молодой/старый, постоянный/новичок).
- Вы должны немедленно принимать решения о принятии/отклонении.
- Игра заканчивается, когда:
(a) заведение заполнено (1000 человек).
(b) вы отклонили 20 000 человек.
Сценарии и подсчёт очков
Возможно 3 различных сценария. Для каждого из них вам предоставляется список ограничений и статистика распределения признаков. Можно предположить, что участники отбираются независимо друг от друга, то есть распределение характеристик не изменится в течение вечера. Вы знаете общую относительную частоту встречаемости каждой характеристики и корреляцию между ними. Точное распределение вам неизвестно.
Ваш результат — это количество людей, которым вы отказали до заполнения площадки (чем меньше, тем лучше).
Приз
Человек, занявший первое место в таблице лидеров на 15 сентября в 6:00 по тихоокеанскому времени, станет победителем и получит билет в Berghain за счёт оргазизаторов! Также вы сможете пройти собеседование с Listen.
Все подробности тут.
PS: Если вдруг кто решит принять участие, пожалуйста, отпишитесь в комментариях о результатах.
Berghain-Челлендж
Вот такой мистический билборд увидели на улицах Сан-Франциско. Попробуйте расшифровать.
Там вас ждёт следующий челлендж.
Berghain*-Челлендж
Berghain — ночной техно-клуб в Берлине. Вы — вышибала в ночном клубе. Ваша цель — заполнить заведение N=1000 людьми, соблюдая ограничения, например, «не менее 40% местных жителей Берлина» или «не менее 80% одеты в чёрное». Люди приходят по одному, и вам нужно сразу же решить, впускать их или нет. Ваша задача — заполнить заведение, получив как можно меньше отказов, соблюдая при этом все минимальные требования.
Как это работает
- Люди приходят последовательно с бинарными признаками (например, женщина/мужчина, молодой/старый, постоянный/новичок).
- Вы должны немедленно принимать решения о принятии/отклонении.
- Игра заканчивается, когда:
(a) заведение заполнено (1000 человек).
(b) вы отклонили 20 000 человек.
Сценарии и подсчёт очков
Возможно 3 различных сценария. Для каждого из них вам предоставляется список ограничений и статистика распределения признаков. Можно предположить, что участники отбираются независимо друг от друга, то есть распределение характеристик не изменится в течение вечера. Вы знаете общую относительную частоту встречаемости каждой характеристики и корреляцию между ними. Точное распределение вам неизвестно.
Ваш результат — это количество людей, которым вы отказали до заполнения площадки (чем меньше, тем лучше).
Приз
Человек, занявший первое место в таблице лидеров на 15 сентября в 6:00 по тихоокеанскому времени, станет победителем и получит билет в Berghain за счёт оргазизаторов! Также вы сможете пройти собеседование с Listen.
Все подробности тут.
PS: Если вдруг кто решит принять участие, пожалуйста, отпишитесь в комментариях о результатах.
👍5
День 2413. #BestPractices
Сегодня порекомендую вам для воскресного просмотра выступление Скотта Заубера на недавней NDC Conference в Осло "10 Things I Do On Every .NET App" (10 вещей, которые я делаю в каждом .NET приложении)
По мере того, как приложение добавляет всё больше и больше функций, если вы не будете осторожны, оно может быстро превратиться в приложение, над которым никто в команде не хочет работать.
Выступление структурировано как серия коротких докладов на различные темы, которые помогут вам улучшить поддержку ваших .NET-приложений. Разговор пойдёт о библиотеках и передовые практиках, которые помогут в организации кода, валидации, ORM, автоматизированном тестировании, безопасности и многом другом. Вы сможете почерпнуть несколько идей, которые сможете сразу же начать реализовывать, вернувшись к работе над улучшением кодовых баз .NET.
Приятного просмотра.
PS: 20 звёзд, и я разберу все советы на канале😉
Сегодня порекомендую вам для воскресного просмотра выступление Скотта Заубера на недавней NDC Conference в Осло "10 Things I Do On Every .NET App" (10 вещей, которые я делаю в каждом .NET приложении)
По мере того, как приложение добавляет всё больше и больше функций, если вы не будете осторожны, оно может быстро превратиться в приложение, над которым никто в команде не хочет работать.
Выступление структурировано как серия коротких докладов на различные темы, которые помогут вам улучшить поддержку ваших .NET-приложений. Разговор пойдёт о библиотеках и передовые практиках, которые помогут в организации кода, валидации, ORM, автоматизированном тестировании, безопасности и многом другом. Вы сможете почерпнуть несколько идей, которые сможете сразу же начать реализовывать, вернувшись к работе над улучшением кодовых баз .NET.
Приятного просмотра.
31👍27
День 2414. #Книги
«C# Concurrency. Асинхронное программирование и многопоточность» (Добовицки Н. — «Питер», 2026).
Очередная книга, над переводом которой довелось поработать совместно с сообществом DotNetRu Translate.
Многопоточность и асинхронность, наверное, всегда будут главными темами вопросов на собеседованиях, а также рассуждений и споров в командах разработчиков. Тема неисчерпаема, и полностью её понимают, кажется, очень немногие. Эта книга - довольно компактное (всего 270 страниц), но при этом полезное руководство по тому, как работает конкурентность в C#, и как вам работать с ней. Автор неплохо раскрывает все особенности и нюансы. Для начинающих в начале книги на доступных аналогиях из жизни разбираются основы многопоточности и асинхронности. Если для вас async/await до сих пор было магией, из первых глав книги вы узнаете, что ничего волшебного там нет, и как это всё устроено "под капотом". Для опытных разработчиков, уже знакомых с основами, в последующих главах разбираются более продвинутые способы применения. Поэтому независимо от того, только начинаете вы изучение конкурентности, либо просто хотите освежить материал и закрепить знания, книга вам подойдёт.
PS
А ещё внезапно так получилось, что на конференции DotNext в Питере в конце первого дня я поучаствую в проведении BoF-сессии «Перевод IT-книг. От идеи до книжной полки» совместно с представителями издательства «Питер». Приглашаю всех, кому интересно узнать про сообщество переводчиков, зачем вообще мы этим занимаемся, как проходит процесс перевода, какие скиллы требуются, чтобы поучаствовать, и как вообще издаются переводы книг на русском языке. Буду рад всех видеть.
«C# Concurrency. Асинхронное программирование и многопоточность» (Добовицки Н. — «Питер», 2026).
Очередная книга, над переводом которой довелось поработать совместно с сообществом DotNetRu Translate.
Многопоточность и асинхронность, наверное, всегда будут главными темами вопросов на собеседованиях, а также рассуждений и споров в командах разработчиков. Тема неисчерпаема, и полностью её понимают, кажется, очень немногие. Эта книга - довольно компактное (всего 270 страниц), но при этом полезное руководство по тому, как работает конкурентность в C#, и как вам работать с ней. Автор неплохо раскрывает все особенности и нюансы. Для начинающих в начале книги на доступных аналогиях из жизни разбираются основы многопоточности и асинхронности. Если для вас async/await до сих пор было магией, из первых глав книги вы узнаете, что ничего волшебного там нет, и как это всё устроено "под капотом". Для опытных разработчиков, уже знакомых с основами, в последующих главах разбираются более продвинутые способы применения. Поэтому независимо от того, только начинаете вы изучение конкурентности, либо просто хотите освежить материал и закрепить знания, книга вам подойдёт.
PS
А ещё внезапно так получилось, что на конференции DotNext в Питере в конце первого дня я поучаствую в проведении BoF-сессии «Перевод IT-книг. От идеи до книжной полки» совместно с представителями издательства «Питер». Приглашаю всех, кому интересно узнать про сообщество переводчиков, зачем вообще мы этим занимаемся, как проходит процесс перевода, какие скиллы требуются, чтобы поучаствовать, и как вообще издаются переводы книг на русском языке. Буду рад всех видеть.
👍37
День 2415. #ЗаметкиНаПолях
Реальная Цена Абстракций в .NET. Начало
Мы, разработчики, любим абстракции. Репозитории, сервисы, конвертеры, обёртки. Они делают наш код «чистым», обещают тестируемость и дают нам ощущение гибкости. Некоторые абстракции оправдывают себя, изолируя реальную волатильность и защищая систему от изменений. Другие же незаметно увеличивают сложность, замедляют внедрение и скрывают проблемы производительности за слоями косвенности. Рассмотрим, когда абстракции приносят дивиденды, а когда они становятся техническим долгом.
Когда абстракции окупаются
Лучшие абстракции изолируют реальную волатильность — те части вашей системы, которые вы действительно ожидаете изменить. Пример: обработка платежей. Ваша бизнес-логика не должна напрямую зависеть от API или SDK платёжной системы. Если вы когда-нибудь перейдёте на другую, вы не хотите, чтобы это повлияло на множество мест вашей кодовой базы. Здесь абстракция имеет смысл:
Теперь бизнес-логика может сфокусироваться на домене:
Эта абстракция изолирует действительно нестабильную зависимость (платёжного провайдера), сохраняя при этом независимость логики оформления заказа. Когда Stripe поменяет свой API или вы поменяете провайдера, нужно изменить только один класс. Это хорошая абстракция. Она даёт опциональность там, где она действительно нужна.
Когда абстракции становятся техническим долгом
Проблемы возникают, когда мы абстрагируем то, что на самом деле не является изменчивым. В итоге мы оборачиваем стабильные библиотеки или создаём слои, которые не приносят реальной ценности. «Чистый» слой, добавленный вами сегодня, завтра становится обузой для обслуживания.
Большинство команд начинают с чего-то разумного:
Но по мере изменения требований, растёт и интерфейс:
Внезапно репозиторий начинает пропускать логику запросов в свой интерфейс. Каждый новый способ получения пользователей означает новый метод, и «абстракция» становится сборищем всевозможных запросов.
Между тем, Entity Framework уже предоставляет всё это через LINQ: строго типизированные запросы, которые напрямую соответствуют SQL. Вместо того, чтобы использовать эту мощь, вы ввели слой косвенности. Паттерн репозитория имел смысл, когда ORM были незрелыми. Сегодня это часто просто формальность.
Частью взросления разработчика является умение распознавать, когда паттерны становятся антипаттернами. Репозитории имеют смысл, когда они инкапсулируют сложную логику запросов или предоставляют унифицированный API для нескольких источников данных. Но вы должны стремиться, чтобы они были сосредоточены на логике предметной области. Как только они разрастаются в мириады методов для каждого возможного запроса, это признак того, что абстракция дала сбой.
Продолжение следует…
Источник: https://www.milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet
Реальная Цена Абстракций в .NET. Начало
Мы, разработчики, любим абстракции. Репозитории, сервисы, конвертеры, обёртки. Они делают наш код «чистым», обещают тестируемость и дают нам ощущение гибкости. Некоторые абстракции оправдывают себя, изолируя реальную волатильность и защищая систему от изменений. Другие же незаметно увеличивают сложность, замедляют внедрение и скрывают проблемы производительности за слоями косвенности. Рассмотрим, когда абстракции приносят дивиденды, а когда они становятся техническим долгом.
Когда абстракции окупаются
Лучшие абстракции изолируют реальную волатильность — те части вашей системы, которые вы действительно ожидаете изменить. Пример: обработка платежей. Ваша бизнес-логика не должна напрямую зависеть от API или SDK платёжной системы. Если вы когда-нибудь перейдёте на другую, вы не хотите, чтобы это повлияло на множество мест вашей кодовой базы. Здесь абстракция имеет смысл:
public interface IPaymentProcessor
{
Task ProcessAsync(
Order order, CancellationToken ct);
}
public class StripePaymentProcessor
: IPaymentProcessor
{
public async Task ProcessAsync(
Order order, CancellationToken ct)
{
// Реализация для Stripe
}
}
Теперь бизнес-логика может сфокусироваться на домене:
public class CheckoutService(
IPaymentProcessor processor)
{
public Task CheckoutAsync(
Order order, CancellationToken ct) =>
processor.ProcessAsync(order, ct);
}
Эта абстракция изолирует действительно нестабильную зависимость (платёжного провайдера), сохраняя при этом независимость логики оформления заказа. Когда Stripe поменяет свой API или вы поменяете провайдера, нужно изменить только один класс. Это хорошая абстракция. Она даёт опциональность там, где она действительно нужна.
Когда абстракции становятся техническим долгом
Проблемы возникают, когда мы абстрагируем то, что на самом деле не является изменчивым. В итоге мы оборачиваем стабильные библиотеки или создаём слои, которые не приносят реальной ценности. «Чистый» слой, добавленный вами сегодня, завтра становится обузой для обслуживания.
Большинство команд начинают с чего-то разумного:
public interface IUserRepository
{
Task<IEnumerable<User>> GetAllAsync();
}
Но по мере изменения требований, растёт и интерфейс:
public interface IUserRepository
{
Task<IEnumerable<User>> GetAllAsync();
Task<User?> GetByEmailAsync(string email);
Task<IEnumerable<User>> GetActiveUsersAsync();
Task<IEnumerable<User>> GetUsersByRoleAsync(string role);
Task<IEnumerable<User>> SearchAsync(string keyword, int page, int pageSize);
// ...и т.д.
}
Внезапно репозиторий начинает пропускать логику запросов в свой интерфейс. Каждый новый способ получения пользователей означает новый метод, и «абстракция» становится сборищем всевозможных запросов.
Между тем, Entity Framework уже предоставляет всё это через LINQ: строго типизированные запросы, которые напрямую соответствуют SQL. Вместо того, чтобы использовать эту мощь, вы ввели слой косвенности. Паттерн репозитория имел смысл, когда ORM были незрелыми. Сегодня это часто просто формальность.
Частью взросления разработчика является умение распознавать, когда паттерны становятся антипаттернами. Репозитории имеют смысл, когда они инкапсулируют сложную логику запросов или предоставляют унифицированный API для нескольких источников данных. Но вы должны стремиться, чтобы они были сосредоточены на логике предметной области. Как только они разрастаются в мириады методов для каждого возможного запроса, это признак того, что абстракция дала сбой.
Продолжение следует…
Источник: https://www.milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet
👍22
День 2416. #ЗаметкиНаПолях
Реальная Цена Абстракций в .NET. Продолжение
Начало
Обёртки Сервисов: контекст имеет значение
✅ Хороший пример
При интеграции с внешними API обёртка действительно полезна, поскольку централизует задачи:
Эта обёртка изолирует детали API GitHub. При изменении аутентификации или развитии конечных точек вы обновляете одно место. Вашей бизнес-логике не нужно разбираться с HTTP-заголовками, базовыми URL или JSON-сериализацией.
❌ Плохой пример
Проблемы начинаются, когда мы обёртываем наши собственные стабильные сервисы, не добавляя им ценности:
Этот UserService только добавляет косвенности. Всё, что он делает, — перенаправляет вызовы в IUserRepository. Он не обеспечивает соблюдение бизнес-правил, не добавляет валидацию, не реализует кэширование и не предоставляет никакой реальной функциональности. Это слой, существующий только потому, что «сервисы — это хорошая архитектура».
По мере того, как эти атрофированные обёртки множатся, ваша кодовая база превращается в лабиринт. Разработчики тратят время на перемещение по слоям вместо того, чтобы сосредоточиться на том, где на самом деле находится бизнес-логика.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet
Реальная Цена Абстракций в .NET. Продолжение
Начало
Обёртки Сервисов: контекст имеет значение
✅ Хороший пример
При интеграции с внешними API обёртка действительно полезна, поскольку централизует задачи:
public interface IGitHubClient
{
Task<UserDto?> GetUserAsync(string username);
Task<IReadOnlyList<RepoDto>>
GetRepositoriesAsync(string username);
}
public class GitHubClient(HttpClient httpClient)
: IGitHubClient
{
public Task<UserDto?> GetUserAsync(string username) =>
httpClient
.GetFromJsonAsync<UserDto>($"/users/{username}");
public Task<IReadOnlyList<RepoDto>>
GetRepositoriesAsync(string username) =>
httpClient
.GetFromJsonAsync<IReadOnlyList<RepoDto>>(
$"/users/{username}/repos");
}
Эта обёртка изолирует детали API GitHub. При изменении аутентификации или развитии конечных точек вы обновляете одно место. Вашей бизнес-логике не нужно разбираться с HTTP-заголовками, базовыми URL или JSON-сериализацией.
❌ Плохой пример
Проблемы начинаются, когда мы обёртываем наши собственные стабильные сервисы, не добавляя им ценности:
public class UserService(IUserRepository userRepository)
{
// Просто перенаправляем вызовы
public Task<User?> GetByIdAsync(Guid id)
=> userRepository.GetByIdAsync(id);
public Task<IEnumerable<User>> GetAllAsync()
=> userRepository.GetAllAsync();
public Task SaveAsync(User user)
=> userRepository.SaveAsync(user);
}
Этот UserService только добавляет косвенности. Всё, что он делает, — перенаправляет вызовы в IUserRepository. Он не обеспечивает соблюдение бизнес-правил, не добавляет валидацию, не реализует кэширование и не предоставляет никакой реальной функциональности. Это слой, существующий только потому, что «сервисы — это хорошая архитектура».
По мере того, как эти атрофированные обёртки множатся, ваша кодовая база превращается в лабиринт. Разработчики тратят время на перемещение по слоям вместо того, чтобы сосредоточиться на том, где на самом деле находится бизнес-логика.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet
👍16👎1
День 2417. #ЗаметкиНаПолях
Реальная Цена Абстракций в .NET. Окончание
Начало
Продолжение
Принимаем более взвешенные решения
Вот как следует понимать, когда абстракции стоят того:
1. Абстрактные политики, а не механизмы
Политики — решения, которые могут измениться: какой платёжный сервис использовать, как обрабатывать кэширование, стратегии повторных попыток для внешних вызовов.
Механизмы — стабильные детали реализации: LINQ в EF Core, конфигурация HttpClient, сериализация JSON.
Абстрагируйте политики, т.к. они обеспечивают гибкость. Не абстрагируйте механизмы — это уже стабильные API, которые редко меняются критически.
2. Дождитесь второй реализации
Если у вас только одна реализация, не поддавайтесь соблазну создать интерфейс. Одна реализация не оправдывает абстрагирование, это преждевременное обобщение, которое добавляет сложности без какой-либо пользы.
Абстракция возникает естественным образом, когда она действительно нужна. Интерфейс раскрывается через реальные требования, а не воображаемые.
3. Реализации внутри, абстракции на границах
Внутри приложения отдавайте предпочтение конкретным типам. Используйте EF напрямую, настраивайте HttpClient как типизированные клиенты, работайте с сущностями домена. Вводите абстракции только там, где система взаимодействует с внешним миром: внешними API, сторонними SDK, инфраструктурными сервисами. Именно там изменения наиболее вероятны, и там абстракции оправдывают себя.
Рефакторинг плохих абстракций
Регулярно задавайте себе вопрос: если я уберу эту абстракцию, код станет проще или сложнее? Если удаление интерфейса или сервисного уровня сделает код более понятным и прямолинейным, эта абстракция, вероятно, стоит больше, чем приносит пользы. Не бойтесь удалять ненужные уровни.
Выявив проблемные абстракции, вот как их безопасно удалить:
1. Определите реальных потребителей. Кому на самом деле нужна абстракция?
2. Встройте интерфейс. Замените абстрактные вызовы конкретными реализациями.
3. Удалите обёртку - ненужные косвенные обращения.
4. Упростите вызывающий код. Воспользуйтесь возможностями конкретного API.
Например, замените репозиторий прямым использованием EF:
Конкретная версия более явно описывает, какие данные она извлекает и как. Если вам нужен один и тот же запрос в нескольких местах, вы можете перенести его в метод расширения, чтобы сделать его общим.
Итого
Абстракции — мощные инструменты для управления сложностью и изменениями, но они не бесплатны. Каждая добавляет косвенные издержки, когнитивные накладные расходы и нагрузку на поддержку. Самая чистая архитектура — та, где каждый слой имеет чёткое и обоснованное назначение.
Прежде чем добавлять следующую абстракцию, спросите себя:
- Я абстрагирую политику или просто механизм?
- У меня две реализации, или я размышляю о будущих потребностях?
- Сделает ли это мою систему более адаптивной или просто более сложной для понимания?
- Если я уберу этот слой, станет ли код проще?
Помните: абстракции — это кредиты, по которым со временем начисляются проценты. Убедитесь, что вы берёте их по правильным причинам, а не просто по привычке.
Источник: https://www.milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet
Реальная Цена Абстракций в .NET. Окончание
Начало
Продолжение
Принимаем более взвешенные решения
Вот как следует понимать, когда абстракции стоят того:
1. Абстрактные политики, а не механизмы
Политики — решения, которые могут измениться: какой платёжный сервис использовать, как обрабатывать кэширование, стратегии повторных попыток для внешних вызовов.
Механизмы — стабильные детали реализации: LINQ в EF Core, конфигурация HttpClient, сериализация JSON.
Абстрагируйте политики, т.к. они обеспечивают гибкость. Не абстрагируйте механизмы — это уже стабильные API, которые редко меняются критически.
2. Дождитесь второй реализации
Если у вас только одна реализация, не поддавайтесь соблазну создать интерфейс. Одна реализация не оправдывает абстрагирование, это преждевременное обобщение, которое добавляет сложности без какой-либо пользы.
// 1: Начинаем с конкретного
public class EmailNotifier
{
public async Task SendAsync(
string to, string subject, string body)
{
// Реализация в SMTP
}
}
// 2: Нужны SMS? Теперь абстрагируемся
public interface INotifier
{
Task SendAsync(string to, string subject, string body);
}
public class EmailNotifier : INotifier { … }
public class SmsNotifier : INotifier { … }
Абстракция возникает естественным образом, когда она действительно нужна. Интерфейс раскрывается через реальные требования, а не воображаемые.
3. Реализации внутри, абстракции на границах
Внутри приложения отдавайте предпочтение конкретным типам. Используйте EF напрямую, настраивайте HttpClient как типизированные клиенты, работайте с сущностями домена. Вводите абстракции только там, где система взаимодействует с внешним миром: внешними API, сторонними SDK, инфраструктурными сервисами. Именно там изменения наиболее вероятны, и там абстракции оправдывают себя.
Рефакторинг плохих абстракций
Регулярно задавайте себе вопрос: если я уберу эту абстракцию, код станет проще или сложнее? Если удаление интерфейса или сервисного уровня сделает код более понятным и прямолинейным, эта абстракция, вероятно, стоит больше, чем приносит пользы. Не бойтесь удалять ненужные уровни.
Выявив проблемные абстракции, вот как их безопасно удалить:
1. Определите реальных потребителей. Кому на самом деле нужна абстракция?
2. Встройте интерфейс. Замените абстрактные вызовы конкретными реализациями.
3. Удалите обёртку - ненужные косвенные обращения.
4. Упростите вызывающий код. Воспользуйтесь возможностями конкретного API.
Например, замените репозиторий прямым использованием EF:
// До: Скрыто за репозиторием
var users = await _userRepo
.GetActiveUsersWithRecentOrders();
// После: Прямой запрос
var users = await _context.Users
.Where(u => u.IsActive)
.Where(u => u.Orders.Any(o => o.CreatedAt > DateTime.Now.AddDays(-30)))
.Include(u => u.Orders.Take(5))
.ToListAsync();
Конкретная версия более явно описывает, какие данные она извлекает и как. Если вам нужен один и тот же запрос в нескольких местах, вы можете перенести его в метод расширения, чтобы сделать его общим.
Итого
Абстракции — мощные инструменты для управления сложностью и изменениями, но они не бесплатны. Каждая добавляет косвенные издержки, когнитивные накладные расходы и нагрузку на поддержку. Самая чистая архитектура — та, где каждый слой имеет чёткое и обоснованное назначение.
Прежде чем добавлять следующую абстракцию, спросите себя:
- Я абстрагирую политику или просто механизм?
- У меня две реализации, или я размышляю о будущих потребностях?
- Сделает ли это мою систему более адаптивной или просто более сложной для понимания?
- Если я уберу этот слой, станет ли код проще?
Помните: абстракции — это кредиты, по которым со временем начисляются проценты. Убедитесь, что вы берёте их по правильным причинам, а не просто по привычке.
Источник: https://www.milanjovanovic.tech/blog/the-real-cost-of-abstractions-in-dotnet
👍15👎2
День 2418. #ЧтоНовенького
Visual Studio 2026
Вышла Insiders (для предварительной оценки) версия Visual Studio 2026. В этой версии VS ИИ становится неотъемлемой частью рабочего процесса разработчика, улучшена производительность, которая меняет ожидания относительно скорости, а современный дизайн делает рабочую среду более лёгкой и сфокусированной.
Новый канал предварительной оценки (Insiders Channel), представленный Microsoft, призван заменить канал превью (Preview Channel) и позволяет разработчикам получать ранний доступ к новым функциям.
Скачать и попробовать новую VS 2026 можно отсюда, подробные примечания к выпуску тут. Также попробуйте бесплатную версию Copilot, чтобы раскрыть всю мощь ИИ в Visual Studio 2026.
Вот некоторые новинки, которые вы найдёте в новой версии:
1. Интеграция ИИ в разработку
ИИ в Visual Studio 2026 вплетён в повседневный кодинг. Вы заметите это, когда перейдёте к новой кодовой базе: IDE поможет вам понять, что вы видите, предложит типы тестов, которые обычно пишутся в вашем репозитории, и будет поддерживать документацию и комментарии в соответствии с вашим кодом. Вы почувствуете, что «адаптивная вставка» (Shift+Alt+V) станет вашим вариантом вставки кода по умолчанию, потому что редактор адаптирует фрагмент к шаблонам и соглашениям вашего проекта. А когда возникнут вопросы по производительности, вам не придётся гадать — рекомендации основаны на реальных трассировках и проверены бенчмарками.
Аудит кода начинается с чётких, применимых на практике данных о корректности, производительности и безопасности — на вашем компьютере, ещё до того, как вы откроете пул-реквест. Всё это время вы контролируете ситуацию. IDE берёт на себя всю рутинную работу, а за вами остаётся окончательное решение. Результат прост: вы работаете быстрее, а ваш код становится лучше.
2. Производительность
Скорость определяет то, что вы можете создать за день. В VS 2026 операции, которые вы чаще всего запускаете — открытие решений, навигация по коду, сборка и нажатие F5 — стали быстрее. Вы заметите, что первый запуск происходит быстрее, крупные решения — легче, а время между идеей и запуском приложения продолжает сокращаться. Выигрыш заметен на больших кодовых базах и сохраняется как на x64, так и на Arm64, так что мощность вашего компьютера напрямую влияет на скорость разработки.
3. Современный внешний вид
Ясность важна, когда вы работаете в IDE. VS 2026 представляет более чистый и современный дизайн. В результате рабочее пространство ощущается спокойным и продуманным. Вы заметите более четкие линии, улучшенные иконки и оптимальное расположение визуальных элементов. Настройки не перегружены, поэтому настройка IDE в соответствии с вашими предпочтениями выполняется быстро. Управление расширениями упрощено, а множество новых цветовых тем делают вашу среду персонализированной — комфортной для длительных сеансов кодинга и позволяющей сосредоточиться в критические моменты. Этот дизайн учитывает ваше внимание и помогает оставаться сконцентрированным.
Это только начало. В Microsoft обещают ежемесячные обновления с последними улучшениями производительности, дизайна и инновациями в ИИ.
PS
Поскольку это только предварительная версия, она, конечно, не лишена косяков. У меня, например, часто не подгружалась подсветка синтаксиса и навигация по коду в декомпилированных файлах. Нажимаешь, например, F12 на классе Task, и открывается простой текстовый файл. Поэтому использовать VS 2026 в проде пока рано. Но скорость, по сравнению с VS 2022, действительно впечатляет.
Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2026-insiders-is-here/
Visual Studio 2026
Вышла Insiders (для предварительной оценки) версия Visual Studio 2026. В этой версии VS ИИ становится неотъемлемой частью рабочего процесса разработчика, улучшена производительность, которая меняет ожидания относительно скорости, а современный дизайн делает рабочую среду более лёгкой и сфокусированной.
Новый канал предварительной оценки (Insiders Channel), представленный Microsoft, призван заменить канал превью (Preview Channel) и позволяет разработчикам получать ранний доступ к новым функциям.
Скачать и попробовать новую VS 2026 можно отсюда, подробные примечания к выпуску тут. Также попробуйте бесплатную версию Copilot, чтобы раскрыть всю мощь ИИ в Visual Studio 2026.
Вот некоторые новинки, которые вы найдёте в новой версии:
1. Интеграция ИИ в разработку
ИИ в Visual Studio 2026 вплетён в повседневный кодинг. Вы заметите это, когда перейдёте к новой кодовой базе: IDE поможет вам понять, что вы видите, предложит типы тестов, которые обычно пишутся в вашем репозитории, и будет поддерживать документацию и комментарии в соответствии с вашим кодом. Вы почувствуете, что «адаптивная вставка» (Shift+Alt+V) станет вашим вариантом вставки кода по умолчанию, потому что редактор адаптирует фрагмент к шаблонам и соглашениям вашего проекта. А когда возникнут вопросы по производительности, вам не придётся гадать — рекомендации основаны на реальных трассировках и проверены бенчмарками.
Аудит кода начинается с чётких, применимых на практике данных о корректности, производительности и безопасности — на вашем компьютере, ещё до того, как вы откроете пул-реквест. Всё это время вы контролируете ситуацию. IDE берёт на себя всю рутинную работу, а за вами остаётся окончательное решение. Результат прост: вы работаете быстрее, а ваш код становится лучше.
2. Производительность
Скорость определяет то, что вы можете создать за день. В VS 2026 операции, которые вы чаще всего запускаете — открытие решений, навигация по коду, сборка и нажатие F5 — стали быстрее. Вы заметите, что первый запуск происходит быстрее, крупные решения — легче, а время между идеей и запуском приложения продолжает сокращаться. Выигрыш заметен на больших кодовых базах и сохраняется как на x64, так и на Arm64, так что мощность вашего компьютера напрямую влияет на скорость разработки.
3. Современный внешний вид
Ясность важна, когда вы работаете в IDE. VS 2026 представляет более чистый и современный дизайн. В результате рабочее пространство ощущается спокойным и продуманным. Вы заметите более четкие линии, улучшенные иконки и оптимальное расположение визуальных элементов. Настройки не перегружены, поэтому настройка IDE в соответствии с вашими предпочтениями выполняется быстро. Управление расширениями упрощено, а множество новых цветовых тем делают вашу среду персонализированной — комфортной для длительных сеансов кодинга и позволяющей сосредоточиться в критические моменты. Этот дизайн учитывает ваше внимание и помогает оставаться сконцентрированным.
Это только начало. В Microsoft обещают ежемесячные обновления с последними улучшениями производительности, дизайна и инновациями в ИИ.
PS
Поскольку это только предварительная версия, она, конечно, не лишена косяков. У меня, например, часто не подгружалась подсветка синтаксиса и навигация по коду в декомпилированных файлах. Нажимаешь, например, F12 на классе Task, и открывается простой текстовый файл. Поэтому использовать VS 2026 в проде пока рано. Но скорость, по сравнению с VS 2022, действительно впечатляет.
Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2026-insiders-is-here/
👍13
День 2419. #SystemDesign101 #Docker
9 Рекомендаций по Docker, Которые Стоит Знать
1. Используйте официальные образы
Это обеспечивает безопасность, надежность и регулярные обновления.
2. Используйте конкретную версию образа
Тег по умолчанию (latest) непредсказуем и приводит к непредвиденному поведению.
3. Многоэтапные сборки
Уменьшает размер конечного образа за счет исключения инструментов сборки и зависимостей.
4. Используйте .dockerignore
Исключает ненужные файлы, ускоряет сборку и уменьшает размер образа.
5. Используйте пользователя с минимальными привилегиями
Повышает безопасность за счёт ограничения привилегий контейнера.
6. Используйте переменные окружения
Повышает гибкость и переносимость в различных средах.
7. Упорядочивайте задачи для кэширования
Упорядочивайте шаги от наименее к наиболее часто изменяемым для оптимизации кэширования.
8. Маркируйте образы
Это улучшает организацию и помогает в управлении образами.
9. Сканируйте образы
Находите уязвимости безопасности, прежде чем они станут серьезными проблемами.
Источник: https://blog.bytebytego.com
9 Рекомендаций по Docker, Которые Стоит Знать
1. Используйте официальные образы
Это обеспечивает безопасность, надежность и регулярные обновления.
2. Используйте конкретную версию образа
Тег по умолчанию (latest) непредсказуем и приводит к непредвиденному поведению.
3. Многоэтапные сборки
Уменьшает размер конечного образа за счет исключения инструментов сборки и зависимостей.
4. Используйте .dockerignore
Исключает ненужные файлы, ускоряет сборку и уменьшает размер образа.
5. Используйте пользователя с минимальными привилегиями
Повышает безопасность за счёт ограничения привилегий контейнера.
6. Используйте переменные окружения
Повышает гибкость и переносимость в различных средах.
7. Упорядочивайте задачи для кэширования
Упорядочивайте шаги от наименее к наиболее часто изменяемым для оптимизации кэширования.
8. Маркируйте образы
Это улучшает организацию и помогает в управлении образами.
9. Сканируйте образы
Находите уязвимости безопасности, прежде чем они станут серьезными проблемами.
Источник: https://blog.bytebytego.com
👍14
День 2420. #BestPractices
Вещи, Которые Я Делаю в Каждом Проекте .NET. Начало
Как и обещал, разбираю советы Скотта Заубера из его доклада на NDC Conference. Их много, так что эта серия затянется.
И получается это очень просто. Вы видите метод из тысячи строк, и вы думаете: «Мне нужно добавить ещё 4 строки». Какая разница, 1000 строк или 1004. Но так же думали те, кто его редактировал, когда он был 800, 600 и 200 строк. В конце концов, нужно, поставить точку и сказать: «Так, нам нужно это отрефакторить». Потому что, если не следить за этим, то всё быстро выйдет из-под контроля, и тогда, возможно, придётся делать великое переписывание, которое всё исправит. Все же знают, что переписать с нуля - всегда работает )))
Эта цитата о том, что необходимо фокусироваться на поддерживаемости во многих подобных вещах, потому что единственное, что постоянно в ПО, — это изменения. Технологии, требования, бизнес - всё меняется, и мы не можем это контролировать. Поэтому старайтесь оптимизировать приложение с учётом изменяемости.
1. Структура папок
Если вы создаёте новый проект, выбираете, например, MVC и работаете с традиционным серверным приложением (без Blazor, Angular, React), то каждый раз, когда вам нужно добавить новую функцию, вам приходится перемещаться по множеству папок. Нужно зайти в папку контроллеров, в папку представлений, в папку моделей, в CSS, в JavaScript, и т.п., которые разбросаны по всему приложению. Таким образом, область действия вашей функции как бы разбросана по всему проекту. И если вам когда-нибудь понадобится удалить функцию, придётся найти все эти файлы и удалить их. А если нужно добавить новую функцию, вам нужно знать, как разместить логику во всех этих разных папках.
Решение в том, чтобы создавать папки для функций, что упрощает поддержку и приводит к так называемой высокой связности, которая просто означает, что связанные элементы должны оставаться вместе. Вы создаёте функцию управления профилем пользователя? Создайте для неё папку и добавьте туда всё, что имеет отношение к этому: контроллер, модель представления, само представление и т.п. В React и Blazor – то же самое. Все компоненты – и даже тесты этих компонентов – всё в этой папке.
Подумайте, где вы храните мыло в вашем доме или квартире. Всё вместе в одном шкафу для мыла? Мыло для рук, шампунь, гель для душа, стиральный порошок и т.п. Нет. Вы храните все разные виды мыла там, где вы ими пользуетесь. Мыло для рук у раковины, шампунь и гель для душа в ванной, порошок – рядом со стиральной машиной и т.п. Почему бы не применить ту же концепцию в проекте?
2. Предупреждения
Бывало ли, что вы открывали проект, собирали его и получали сотни или даже тысячи предупреждений? Не очень приятно, правда? Так вот, предупреждений быть не должно! Либо это ошибка, которая меня волнует, и я её исправляю, либо я её игнорирую по какой-то причине, например, знаю, что она не появится. Поэтому включите флажок «Рассматривать предупреждения как ошибки». Это особенно актуально для новых проектов. Сделайте это с самого начала, потому что в противном случае у вас будут копиться самые разные предупреждения, и вы не будет знать, какие из них важны, а какие можно проигнорировать». Поэтому постарайтесь разбираться с ними с самого начала.
В существующем проекте либо создайте отдельную задачу, чтобы разобраться со всеми предупреждениями, либо делайте это по ходу выполнения других задач, когда работаете с кодом, где возникает предупреждение. Если вы абсолютно уверены, что какой-то вид предупреждений можно безболезненно игнорировать, его можно включить в исключения, чтобы этот вид предупреждений не выдавал ошибку при сборке.
Продолжение следует…
Источник: https://youtu.be/SvcRvolP2NE
Вещи, Которые Я Делаю в Каждом Проекте .NET. Начало
Как и обещал, разбираю советы Скотта Заубера из его доклада на NDC Conference. Их много, так что эта серия затянется.
Каждая система стремится к запутанности, медленности и сложности. Поддержание простоты, скорости и лёгкости использования — это битва, в которой приходится бороться каждый день.
— Гильермо Раух
И получается это очень просто. Вы видите метод из тысячи строк, и вы думаете: «Мне нужно добавить ещё 4 строки». Какая разница, 1000 строк или 1004. Но так же думали те, кто его редактировал, когда он был 800, 600 и 200 строк. В конце концов, нужно, поставить точку и сказать: «Так, нам нужно это отрефакторить». Потому что, если не следить за этим, то всё быстро выйдет из-под контроля, и тогда, возможно, придётся делать великое переписывание, которое всё исправит. Все же знают, что переписать с нуля - всегда работает )))
Эта цитата о том, что необходимо фокусироваться на поддерживаемости во многих подобных вещах, потому что единственное, что постоянно в ПО, — это изменения. Технологии, требования, бизнес - всё меняется, и мы не можем это контролировать. Поэтому старайтесь оптимизировать приложение с учётом изменяемости.
1. Структура папок
Если вы создаёте новый проект, выбираете, например, MVC и работаете с традиционным серверным приложением (без Blazor, Angular, React), то каждый раз, когда вам нужно добавить новую функцию, вам приходится перемещаться по множеству папок. Нужно зайти в папку контроллеров, в папку представлений, в папку моделей, в CSS, в JavaScript, и т.п., которые разбросаны по всему приложению. Таким образом, область действия вашей функции как бы разбросана по всему проекту. И если вам когда-нибудь понадобится удалить функцию, придётся найти все эти файлы и удалить их. А если нужно добавить новую функцию, вам нужно знать, как разместить логику во всех этих разных папках.
Решение в том, чтобы создавать папки для функций, что упрощает поддержку и приводит к так называемой высокой связности, которая просто означает, что связанные элементы должны оставаться вместе. Вы создаёте функцию управления профилем пользователя? Создайте для неё папку и добавьте туда всё, что имеет отношение к этому: контроллер, модель представления, само представление и т.п. В React и Blazor – то же самое. Все компоненты – и даже тесты этих компонентов – всё в этой папке.
Подумайте, где вы храните мыло в вашем доме или квартире. Всё вместе в одном шкафу для мыла? Мыло для рук, шампунь, гель для душа, стиральный порошок и т.п. Нет. Вы храните все разные виды мыла там, где вы ими пользуетесь. Мыло для рук у раковины, шампунь и гель для душа в ванной, порошок – рядом со стиральной машиной и т.п. Почему бы не применить ту же концепцию в проекте?
2. Предупреждения
Бывало ли, что вы открывали проект, собирали его и получали сотни или даже тысячи предупреждений? Не очень приятно, правда? Так вот, предупреждений быть не должно! Либо это ошибка, которая меня волнует, и я её исправляю, либо я её игнорирую по какой-то причине, например, знаю, что она не появится. Поэтому включите флажок «Рассматривать предупреждения как ошибки». Это особенно актуально для новых проектов. Сделайте это с самого начала, потому что в противном случае у вас будут копиться самые разные предупреждения, и вы не будет знать, какие из них важны, а какие можно проигнорировать». Поэтому постарайтесь разбираться с ними с самого начала.
В существующем проекте либо создайте отдельную задачу, чтобы разобраться со всеми предупреждениями, либо делайте это по ходу выполнения других задач, когда работаете с кодом, где возникает предупреждение. Если вы абсолютно уверены, что какой-то вид предупреждений можно безболезненно игнорировать, его можно включить в исключения, чтобы этот вид предупреждений не выдавал ошибку при сборке.
Продолжение следует…
Источник: https://youtu.be/SvcRvolP2NE
👍27
День 2421. #BestPractices
Вещи, Которые Я Делаю в Каждом Проекте .NET. Продолжение
Начало
3. Логирование
Конкретная библиотека не имеет значения: Serilog, NLog или log4net. Но не используйте их напрямую. Используйте везде ILogger, чтобы единственное место, которое бы знало о конкретной его реализации – был файл program.cs. По возможности используйте структурное логирование. Также помните о том, что каждый журнал должен содержать некоторую ключевую информацию, например, ID пользователя или ID корреляции. Так вы сможете отслеживать как один запрос проходит через разные сервисы, и что там происходит. Иногда полезно включать короткий sha Git-коммита, чтобы если появляется ошибка, и вы её исправляете, вы могли сравнить, получаем ли мы больше исключений в последней версии, чем получали раньше?
Также важно разделять, как вы логируете нужную информацию. Например, в системе управления пользователями нужно регистрировать, кто внёс каждое изменение. Иногда мы думаем: «Есть же логгер, запишем в лог». Скорей всего, это не лучшее место. Рассмотрим о логи, метрики и аудиты.
Логи должны быть ориентированы на разработчиков. Вы не должны их передавать бизнесу. Это исключения с трассировками стека, ответы от внешних API, разные этапы процесса обработки и т.п.
Кроме того, многие путают уровни логирования. Например, сваливают всё в Information. Вы вызываете 3 API и хотите логировать их ответы. Это информация уровня отладки (Debug). А Information – это результат запроса: мы обработали столько-то записей за такое-то время, т.е. одна запись на запрос пользователя.
Используйте предупреждения (Warning) вместо ошибок (Error). Логи уровня предупреждения работают так: если у вас одно предупреждение, это не страшно, но если их много, то что-то не так. Классический пример: пользователь вводит неверный пароль и блокирует свою учётную запись на пять минут. Одно событие – не важно, но если их тысячи за короткий промежуток времени, возможно, происходит что-то не то (например, кто-то пытается проникнуть в систему).
Ошибки (Error) — это необработанные исключения. Многие просто игнорируют ошибки в логах. Не стоит так делать. Нужно выяснить первопричину и определить, волнует ли нас это. Может это предупреждение, а может реальная ошибка в коде. Постарайтесь очистить ошибки из лога, потому что худший человек, которому стоит сообщать о проблемах, — это ваши пользователи.
И, наконец, критический уровень (Critical) используется, когда приложение не может загрузиться. Например, нужно сначала обратиться к БД или к Azure Key Vault, чтобы извлечь секреты. Если это не удаётся, приложение не может работать.
Стоит подумать, как долго хранятся логи. Azure Log Analytics по умолчанию хранит только 30 дней. И если вы пытаетесь сохранить историческую информацию, например: «кто что изменил?», то ваш ответ бизнесу «Мы храним только 30 дней логов» вряд ли будет удовлетворительным. Аналогично, многие системы записывают логи в буфер и потом скидывают на диск. Так что, если отключится питание, последние логи потеряются. Это нормально, если логи используются только как описано выше, и не хранят важной для бизнеса информации.
Метрики делятся на 2 типа:
- уровня приложения: процессор, сеть, память, глубина очереди и т.п.
- бизнес-метрики: сколько размещено заказов, сколько раз нажимали эту кнопку, или сколько просмотрели эту страницу.
Как долго нужно хранить эти данные? Это должен быть разговор с бизнесом.
Аудиты - это регистрация того, кто, когда и что делал в приложении. В таких случаях вообще нельзя использовать логи. Самый простой способ — хранить данные аудита в БД вместе с данными. В одной транзакции вносите и изменение, и запись, кто его сделал.
Поэтому, когда кто-то говорит: «Нам нужно логировать это в следующий раз», - подумайте, какое хранилище данных использовать и на какой срок нужны эти данные.
Продолжение следует…
Источник: https://youtu.be/SvcRvolP2NE
Вещи, Которые Я Делаю в Каждом Проекте .NET. Продолжение
Начало
3. Логирование
Конкретная библиотека не имеет значения: Serilog, NLog или log4net. Но не используйте их напрямую. Используйте везде ILogger, чтобы единственное место, которое бы знало о конкретной его реализации – был файл program.cs. По возможности используйте структурное логирование. Также помните о том, что каждый журнал должен содержать некоторую ключевую информацию, например, ID пользователя или ID корреляции. Так вы сможете отслеживать как один запрос проходит через разные сервисы, и что там происходит. Иногда полезно включать короткий sha Git-коммита, чтобы если появляется ошибка, и вы её исправляете, вы могли сравнить, получаем ли мы больше исключений в последней версии, чем получали раньше?
Также важно разделять, как вы логируете нужную информацию. Например, в системе управления пользователями нужно регистрировать, кто внёс каждое изменение. Иногда мы думаем: «Есть же логгер, запишем в лог». Скорей всего, это не лучшее место. Рассмотрим о логи, метрики и аудиты.
Логи должны быть ориентированы на разработчиков. Вы не должны их передавать бизнесу. Это исключения с трассировками стека, ответы от внешних API, разные этапы процесса обработки и т.п.
Кроме того, многие путают уровни логирования. Например, сваливают всё в Information. Вы вызываете 3 API и хотите логировать их ответы. Это информация уровня отладки (Debug). А Information – это результат запроса: мы обработали столько-то записей за такое-то время, т.е. одна запись на запрос пользователя.
Используйте предупреждения (Warning) вместо ошибок (Error). Логи уровня предупреждения работают так: если у вас одно предупреждение, это не страшно, но если их много, то что-то не так. Классический пример: пользователь вводит неверный пароль и блокирует свою учётную запись на пять минут. Одно событие – не важно, но если их тысячи за короткий промежуток времени, возможно, происходит что-то не то (например, кто-то пытается проникнуть в систему).
Ошибки (Error) — это необработанные исключения. Многие просто игнорируют ошибки в логах. Не стоит так делать. Нужно выяснить первопричину и определить, волнует ли нас это. Может это предупреждение, а может реальная ошибка в коде. Постарайтесь очистить ошибки из лога, потому что худший человек, которому стоит сообщать о проблемах, — это ваши пользователи.
И, наконец, критический уровень (Critical) используется, когда приложение не может загрузиться. Например, нужно сначала обратиться к БД или к Azure Key Vault, чтобы извлечь секреты. Если это не удаётся, приложение не может работать.
Стоит подумать, как долго хранятся логи. Azure Log Analytics по умолчанию хранит только 30 дней. И если вы пытаетесь сохранить историческую информацию, например: «кто что изменил?», то ваш ответ бизнесу «Мы храним только 30 дней логов» вряд ли будет удовлетворительным. Аналогично, многие системы записывают логи в буфер и потом скидывают на диск. Так что, если отключится питание, последние логи потеряются. Это нормально, если логи используются только как описано выше, и не хранят важной для бизнеса информации.
Метрики делятся на 2 типа:
- уровня приложения: процессор, сеть, память, глубина очереди и т.п.
- бизнес-метрики: сколько размещено заказов, сколько раз нажимали эту кнопку, или сколько просмотрели эту страницу.
Как долго нужно хранить эти данные? Это должен быть разговор с бизнесом.
Аудиты - это регистрация того, кто, когда и что делал в приложении. В таких случаях вообще нельзя использовать логи. Самый простой способ — хранить данные аудита в БД вместе с данными. В одной транзакции вносите и изменение, и запись, кто его сделал.
Поэтому, когда кто-то говорит: «Нам нужно логировать это в следующий раз», - подумайте, какое хранилище данных использовать и на какой срок нужны эти данные.
Продолжение следует…
Источник: https://youtu.be/SvcRvolP2NE
👍21
День 2422. #BestPractices
Вещи, Которые Я Делаю в Каждом Проекте .NET. Продолжение
1-2
3
4. Задаём авторизацию глобально
Если вы используете, например, контроллеры, вам нужно не забыть добавить атрибут Authorize во всех контроллерах и действиях, которые вы хотите защитить (а это обычно большинство). Либо нужно не забыть наследовать от какого-нибудь базового контроллера, у которого есть этот атрибут. Но проблема в том, что если вы забудете, то этот метод/контроллер полностью открыты для внешнего мира.
Решение этой проблемы — так называемая резервная политика (FallbackPolicy) в ASP.NET Core. Резервная политика работает так: если вы не укажете другую политику, эта будет срабатывать каждый раз. В контейнере DI вы просто добавляете авторизацию и устанавливаете эту резервную политику:
Вы можете создать любую политику, но проще использовать конструктор политик авторизации и запросить аутентифицированного пользователя. Это сработает только в том случае, если вы не укажете ничего другого в контроллере. Если в контроллер или метод контроллера вы добавите атрибут AllowAnonymous, либо атрибут с более строгой политикой, будет использован он. А так вы защищены по умолчанию.
5. Валидация
Наверное, большинство из вас использовали аннотации данных для валидации. Проблема с ними в том, что, если нужно наложить несколько условий на свойство, добавление аннотации для каждого условия быстро становится громоздким и загружает модель. Не говоря уже о случае, когда нам требуется какая-то нестандартная валидация. Кроме того, для них сложно писать автоматизированные тесты.
Fluent Validation позволяет создавать бизнес-правила, которые легко читать даже бизнесу. Их также легко тестировать. Сложные правила создавать тоже просто. Например, в США, вы не можете пользоваться медицинской страховкой родителей после 26 лет. И вот правило для этого:
Вы можете показать это бизнесу, и они поймут эти условия, даже не зная кода.
6. Заголовки сервера
По умолчанию ASP.NET Core в ответ добавляет HTTP-заголовок с именем сервера. Если вы используете Kestrel, это значение будет Kestrel. Зачем он это делает? Скорей всего, в Microsoft просто хотят знать, сколько сайтов используют ASP.NET Core. В .NET Framework было ещё хуже, потому что выдавались и версии MVC и .NET. Но это раскрывает хакерам, что вы используете. Т.е. им не нужно проверять ваш сайт на уязвимости Java или Python, только на уязвимости, специфичные для .NET. Удаление заголовка не избавит вас от атак, но увеличит количество времени, которое атакующий потратит. Если у вас есть публичный веб-сайт, он гарантированно подвергался различным атакам. Удалить заголовок легко, просто добавьте эту строку:
Продолжение следует…
Источник: https://youtu.be/SvcRvolP2NE
Вещи, Которые Я Делаю в Каждом Проекте .NET. Продолжение
1-2
3
4. Задаём авторизацию глобально
Если вы используете, например, контроллеры, вам нужно не забыть добавить атрибут Authorize во всех контроллерах и действиях, которые вы хотите защитить (а это обычно большинство). Либо нужно не забыть наследовать от какого-нибудь базового контроллера, у которого есть этот атрибут. Но проблема в том, что если вы забудете, то этот метод/контроллер полностью открыты для внешнего мира.
Решение этой проблемы — так называемая резервная политика (FallbackPolicy) в ASP.NET Core. Резервная политика работает так: если вы не укажете другую политику, эта будет срабатывать каждый раз. В контейнере DI вы просто добавляете авторизацию и устанавливаете эту резервную политику:
bulder.Services.AddAuthorization(opts =>
{
opts.FallbackPolicy = new
AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
Вы можете создать любую политику, но проще использовать конструктор политик авторизации и запросить аутентифицированного пользователя. Это сработает только в том случае, если вы не укажете ничего другого в контроллере. Если в контроллер или метод контроллера вы добавите атрибут AllowAnonymous, либо атрибут с более строгой политикой, будет использован он. А так вы защищены по умолчанию.
5. Валидация
Наверное, большинство из вас использовали аннотации данных для валидации. Проблема с ними в том, что, если нужно наложить несколько условий на свойство, добавление аннотации для каждого условия быстро становится громоздким и загружает модель. Не говоря уже о случае, когда нам требуется какая-то нестандартная валидация. Кроме того, для них сложно писать автоматизированные тесты.
Fluent Validation позволяет создавать бизнес-правила, которые легко читать даже бизнесу. Их также легко тестировать. Сложные правила создавать тоже просто. Например, в США, вы не можете пользоваться медицинской страховкой родителей после 26 лет. И вот правило для этого:
public class InsuranceValidator
: AbstractValidator<Insurance>
{
public InsuranceValidator()
{
RuleFor(model => model.Age)
.Must(age => age < 26)
.When(model => model.IsDependent)
.WithMessage(“A dependent must be younger than 26”);
}
}
Вы можете показать это бизнесу, и они поймут эти условия, даже не зная кода.
6. Заголовки сервера
По умолчанию ASP.NET Core в ответ добавляет HTTP-заголовок с именем сервера. Если вы используете Kestrel, это значение будет Kestrel. Зачем он это делает? Скорей всего, в Microsoft просто хотят знать, сколько сайтов используют ASP.NET Core. В .NET Framework было ещё хуже, потому что выдавались и версии MVC и .NET. Но это раскрывает хакерам, что вы используете. Т.е. им не нужно проверять ваш сайт на уязвимости Java или Python, только на уязвимости, специфичные для .NET. Удаление заголовка не избавит вас от атак, но увеличит количество времени, которое атакующий потратит. Если у вас есть публичный веб-сайт, он гарантированно подвергался различным атакам. Удалить заголовок легко, просто добавьте эту строку:
builder.WebHost.UseKestrel(opts => opts.AddServerHeader = false);
Продолжение следует…
Источник: https://youtu.be/SvcRvolP2NE
👍25
День 2423. #BestPractices
Вещи, Которые Я Делаю в Каждом Проекте .NET. Продолжение
1-2
3
4-6
7. Не внедряйте IOptions
Проблема с параметрами IOptions в том, что вам нужна зависимость от Microsoft.Extensions. И если вы используете IOptions в других проектах ниже по стеку вызовов, придётся добавлять зависимость во все эти проекты. И тестировать параметр типа IOptions может быть непросто. Кроме того, везде приходится использовать .Value вместо просто имени параметра:
Решение - регистрируйте класс IOptions напрямую, так вы получите нужный класс значений в DI контейнере, который уже можно внедрять:
Если вы хотите, чтобы параметры изменялись без перезагрузки приложения, это тоже будет работать. Регистрируете значения как AddScoped и используйте IOptionsSnapshot<T> вместо IOptions<T>.
8. Запахи кода
Во-первых, возьмите за правило располагать «счастливый путь» в конце метода. Если вы смотрите на незнакомый код, как быстро узнать, что происходит, когда всё идёт хорошо? Проще всего – когда нужно всегда смотреть в конец.
Чтобы этого добиться, используйте технику раннего возврата. Вместо нескольких вложенных if-else, просто возвращайте ошибку (или любой другой результат), если что-то идёт не так. Таким образом, в начале метода следуют необходимые проверки, которые завершаются ранним возвратом, если они не проходят, а в конце (если все проверки прошли) – возврат результата, когда всё хорошо:
Это не только позволяет быстро найти «счастливый путь», но и избавляет от избыточной вложенности конструкций if.
И некоторые не жёсткие правила, а просто предупредительные сигналы о запахах кода:
- метод длиннее 20 строк,
- класс длиннее 200 строк,
- использование областей (#region).
Это всё сигналы о том, что метод или класс можно разбить на части.
9. Новые файлы решений
Это относительно новая функция. Технически она всё ещё в стадии превью версии, но сейчас довольно стабильна. Если коротко, новые файлы .slnx – это старый добрый XML, они гораздо короче и понятнее. Обновить файл решения можно, просто перейдя в папку решения и выполнив:
Затем не забудьте удалить старый файл .sln. Он больше не нужен, но утилита его не удаляет.
Окончание следует…
Источник: https://youtu.be/SvcRvolP2NE
Вещи, Которые Я Делаю в Каждом Проекте .NET. Продолжение
1-2
3
4-6
7. Не внедряйте IOptions
Проблема с параметрами IOptions в том, что вам нужна зависимость от Microsoft.Extensions. И если вы используете IOptions в других проектах ниже по стеку вызовов, придётся добавлять зависимость во все эти проекты. И тестировать параметр типа IOptions может быть непросто. Кроме того, везде приходится использовать .Value вместо просто имени параметра:
public class MyController(
IOptions<AppSettings> appSettings)
{
private readonly AppSettings _appSettings =
appSettings.Value;
…
}
Решение - регистрируйте класс IOptions напрямую, так вы получите нужный класс значений в DI контейнере, который уже можно внедрять:
services.Configure<AppSettings>(
Configuration.GetSection("AppSettings"));
services.AddSingleton(s =>
s.GetRequiredService<IOptions<AppSettings>>().Value);
…
public class MyController(AppSettings appSettings)
{
…
}
Если вы хотите, чтобы параметры изменялись без перезагрузки приложения, это тоже будет работать. Регистрируете значения как AddScoped и используйте IOptionsSnapshot<T> вместо IOptions<T>.
8. Запахи кода
Во-первых, возьмите за правило располагать «счастливый путь» в конце метода. Если вы смотрите на незнакомый код, как быстро узнать, что происходит, когда всё идёт хорошо? Проще всего – когда нужно всегда смотреть в конец.
Чтобы этого добиться, используйте технику раннего возврата. Вместо нескольких вложенных if-else, просто возвращайте ошибку (или любой другой результат), если что-то идёт не так. Таким образом, в начале метода следуют необходимые проверки, которые завершаются ранним возвратом, если они не проходят, а в конце (если все проверки прошли) – возврат результата, когда всё хорошо:
public ActionResult SendMessage(Message msg)
{
if(!ModelState.IsValid())
return View(msg);
if(emailSender.Send(msg) != Result.OK)
{
_logger.Log(…);
return LocalRedirect("/message/error");
}
…
return LocalRedirect("/message/success");
}
Это не только позволяет быстро найти «счастливый путь», но и избавляет от избыточной вложенности конструкций if.
И некоторые не жёсткие правила, а просто предупредительные сигналы о запахах кода:
- метод длиннее 20 строк,
- класс длиннее 200 строк,
- использование областей (#region).
Это всё сигналы о том, что метод или класс можно разбить на части.
9. Новые файлы решений
Это относительно новая функция. Технически она всё ещё в стадии превью версии, но сейчас довольно стабильна. Если коротко, новые файлы .slnx – это старый добрый XML, они гораздо короче и понятнее. Обновить файл решения можно, просто перейдя в папку решения и выполнив:
dotnet sln migrate
Затем не забудьте удалить старый файл .sln. Он больше не нужен, но утилита его не удаляет.
Окончание следует…
Источник: https://youtu.be/SvcRvolP2NE
👍21
День 2424. #BestPractices
Вещи, Которые Я Делаю в Каждом Проекте .NET. Окончание
1-2
3
4-6
7-9
10. HTTP-заголовки безопасности
Они сообщают браузеру о необходимости применения дополнительных правил. Это означает, что вы можете предотвратить определённые типы атак, такие как «человек посередине», кликджекинг, кросс-скриптинг и многие другие. Однако будьте осторожны. Можно, например, запретить загрузку JavaScript отовсюду, кроме вашего домена, но если вы при этом используете CDN, то ваше приложение сломается. Есть стратегии по постепенному внедрению HTTP-заголовков в существующее приложение. Если ваше приложение сканируется на безопасность внешними аналитиками, они всегда проверяют это. Есть публичные сайты, вроде securityheaders.com, которые просканируют ваш сайт и сообщат о состоянии дел. Примерно половина веб-сайтов вообще не имеет заголовков безопасности. И только у 10% рейтинг A или A+. У Эндрю Лока есть NuGet-пакет для реализации некоторых заголовков безопасности.
11. Валидация при сборке
Эта функция проверяет, что ваш DI контейнер настроен правильно. Синглтоны зависят только от синглтонов, а не принимают scoped-объекты. Иначе возникает проблема захвата зависимости. ASP.NET Core обнаруживает это, в режиме локальной разработки, но не в других средах. Но вы можете заставить это работать всегда:
12. Автоматизированные тесты
Надеюсь, не нужно объяснять, почему нужно писать тесты? Здесь рассмотрим один нюанс. Слышали выражение «чеховское ружьё»? Если кратко, Чехов писал, что если в главе 1 у вас на стене висит ружьё, то в последующих главах оно должно выстрелить. Иначе нечего его изначально «вешать». То есть, у всего должно быть предназначение. Вот как это касается тестов.
Что здесь не так? Имя, дата рождения и адрес не имеют значения для этого теста. Фамилия — единственное, что мы проверяем. Мы можем вынести ненужные конструкторы в общий код:
Нижний тест более ясно показывает, что мы тестируем.
13. Централизованное управление пакетами
Проблема, которую решает централизованное управление пакетами, в том, что у вас может быть один пакет в нескольких проектах в решении, и может быть раздражающим поддерживать их синхронизацию. В .NET 6 добавили эту функцию, с помощью которой вы можете создать directory.packages.props в корне и определить там пакеты и версии, которые вам нужны, а затем вы удаляете все версии пакетов в файлах .csproj проектов, и все проекты используют одну версию пакета (хотя, её можно переопределить в любом проекте при необходимости).
Источник: https://youtu.be/SvcRvolP2NE
Вещи, Которые Я Делаю в Каждом Проекте .NET. Окончание
1-2
3
4-6
7-9
10. HTTP-заголовки безопасности
Они сообщают браузеру о необходимости применения дополнительных правил. Это означает, что вы можете предотвратить определённые типы атак, такие как «человек посередине», кликджекинг, кросс-скриптинг и многие другие. Однако будьте осторожны. Можно, например, запретить загрузку JavaScript отовсюду, кроме вашего домена, но если вы при этом используете CDN, то ваше приложение сломается. Есть стратегии по постепенному внедрению HTTP-заголовков в существующее приложение. Если ваше приложение сканируется на безопасность внешними аналитиками, они всегда проверяют это. Есть публичные сайты, вроде securityheaders.com, которые просканируют ваш сайт и сообщат о состоянии дел. Примерно половина веб-сайтов вообще не имеет заголовков безопасности. И только у 10% рейтинг A или A+. У Эндрю Лока есть NuGet-пакет для реализации некоторых заголовков безопасности.
11. Валидация при сборке
Эта функция проверяет, что ваш DI контейнер настроен правильно. Синглтоны зависят только от синглтонов, а не принимают scoped-объекты. Иначе возникает проблема захвата зависимости. ASP.NET Core обнаруживает это, в режиме локальной разработки, но не в других средах. Но вы можете заставить это работать всегда:
builder.Host.UseDefaultHostProvider(config =>
{
config.ValidateOnBuild = true;
});
12. Автоматизированные тесты
Надеюсь, не нужно объяснять, почему нужно писать тесты? Здесь рассмотрим один нюанс. Слышали выражение «чеховское ружьё»? Если кратко, Чехов писал, что если в главе 1 у вас на стене висит ружьё, то в последующих главах оно должно выстрелить. Иначе нечего его изначально «вешать». То есть, у всего должно быть предназначение. Вот как это касается тестов.
[Fact]
public void EmptyLastNameValidationTest()
{
var customer = new Customer
{
FirstName = "John",
LastName = "",
Address = "123 1st Street",
Born = new DateOnly(2000, 1, 1)
}
var result = new CustomerValidator()
.Validate(customer);
result.Errors.Should().Contain(
e => e.ErrorMessage == "Last Name is required");
}
Что здесь не так? Имя, дата рождения и адрес не имеют значения для этого теста. Фамилия — единственное, что мы проверяем. Мы можем вынести ненужные конструкторы в общий код:
[Fact]
public void EmptyLastNameValidationTest()
{
_customer.LastName = "";
var result = _customerValidator
.Validate(_customer);
result.Errors.Should().Contain(
e => e.ErrorMessage == "Last Name is required");
}
Нижний тест более ясно показывает, что мы тестируем.
13. Централизованное управление пакетами
Проблема, которую решает централизованное управление пакетами, в том, что у вас может быть один пакет в нескольких проектах в решении, и может быть раздражающим поддерживать их синхронизацию. В .NET 6 добавили эту функцию, с помощью которой вы можете создать directory.packages.props в корне и определить там пакеты и версии, которые вам нужны, а затем вы удаляете все версии пакетов в файлах .csproj проектов, и все проекты используют одну версию пакета (хотя, её можно переопределить в любом проекте при необходимости).
Источник: https://youtu.be/SvcRvolP2NE
👍17