День 1304. #Карьера
Как Разработчику ПО Развить Навыки Решения Проблем
Общеизвестно, что решение проблем является важным навыком для инженеров-программистов. Хорошие навыки решения проблем включают в себя способность мыслить творчески и аналитически, разбивая проблемы на более мелкие части и используя системный подход для поиска решений. Сильные навыки решения проблем необходимы для успешной карьеры в разработке ПО.
Метод проб и ошибок
Это распространённый метод решения проблем, при котором потенциальные решения опробуются одно за другим, пока не будет найдено рабочее. Его можно использовать как для простых, так и для сложных задач. Это может быть эффективно, но также может отнимать много времени и разочаровывать.
Разделяй и властвуй
Другой подход заключается в использовании более системного метода.
Метод «Разделяй и властвуй» подходит для решения сложных проблем путём их разбиения на более мелкие, управляемые части. Это позволяет более эффективно и действенно решать проблемы. Как только эти подзадачи решены, их можно объединить для решения более крупной и сложной проблемы.
Среди распространённых примеров «разделяй и властвуй»: рекурсия или алгоритм сортировки слиянием, который разбивает массив на более мелкие части, сортирует каждую часть, а затем объединяет их.
Как только решение найдено, важно извлечь уроки из этого опыта и использовать эти знания для улучшения навыков решения проблем в будущем. Это включает в себя понимание того, что пошло не так, что можно было бы сделать лучше и как можно избежать подобных проблем в будущем.
Каждый навык решения проблем важен по-своему. Как разработчик, вы должны пытаться развить все эти навыки, чтобы добиться успеха.
1. Аналитические навыки
Это способность собирать и анализировать данные, выявлять закономерности и тенденции и принимать решения на основе этой информации. Они предполагают как логическое, так и творческое мышление, а также способность обращать внимание на детали. Некоторые примеры:
- Умение разбить проблему и идентифицировать различные компоненты,
- Умение определять закономерности и тенденции,
- Умение видеть связи между различными частями данных,
- Умение принимать решения на основе данных,
- Умение решать сложные задачи.
2. Креативное мышление
В компьютерных науках оно связано с поиском новых и инновационных способов решения проблем. Речь идёт о нестандартном мышлении и поиске креативных решений, о которых раньше никто не думал. В ИТ важно проявлять творческий подход, потому что это постоянно развивающаяся область. Если вы не будете постоянно генерировать новые идеи, вы отстанете. Креативное мышление — это то, что заставляет информатику двигаться вперед.
3. Логическое рассуждение
Это процесс получения выводов на основе имеющейся информации. В информатике он часто используется для решения задач и создания новых алгоритмов. Чтобы рассуждать логически, нужно сначала идентифицировать факты, а затем использовать их, чтобы прийти к правильному заключению.
Итого
Практика — один из лучших способов улучшить свои навыки решения проблем.
Вы можете делать это, работая над задачами по кодированию, участвуя в онлайн-конкурсах или просто пытаясь решить проблемы, с которыми вы сталкиваетесь в своей повседневной работе.
Сотрудничество — ещё один отличный способ улучшить свои навыки решения проблем. Когда вы работаете с другими, вы можете учиться на их опыте и делиться своими мыслями. Это может помочь вам выработать более качественный подход к решению проблем.
И последнее: смиритесь с тем, что вы будете застревать. Застрять при решении какой-то проблемы и попросить помощи – это нормально. Нет ничего постыдного в том, чтобы признать, что вам нужна помощь.
Источник: https://dev.to/nathan20/how-to-develop-strong-problem-solving-skills-as-a-software-developer-25nb
Как Разработчику ПО Развить Навыки Решения Проблем
Общеизвестно, что решение проблем является важным навыком для инженеров-программистов. Хорошие навыки решения проблем включают в себя способность мыслить творчески и аналитически, разбивая проблемы на более мелкие части и используя системный подход для поиска решений. Сильные навыки решения проблем необходимы для успешной карьеры в разработке ПО.
Метод проб и ошибок
Это распространённый метод решения проблем, при котором потенциальные решения опробуются одно за другим, пока не будет найдено рабочее. Его можно использовать как для простых, так и для сложных задач. Это может быть эффективно, но также может отнимать много времени и разочаровывать.
Разделяй и властвуй
Другой подход заключается в использовании более системного метода.
Метод «Разделяй и властвуй» подходит для решения сложных проблем путём их разбиения на более мелкие, управляемые части. Это позволяет более эффективно и действенно решать проблемы. Как только эти подзадачи решены, их можно объединить для решения более крупной и сложной проблемы.
Среди распространённых примеров «разделяй и властвуй»: рекурсия или алгоритм сортировки слиянием, который разбивает массив на более мелкие части, сортирует каждую часть, а затем объединяет их.
Как только решение найдено, важно извлечь уроки из этого опыта и использовать эти знания для улучшения навыков решения проблем в будущем. Это включает в себя понимание того, что пошло не так, что можно было бы сделать лучше и как можно избежать подобных проблем в будущем.
Каждый навык решения проблем важен по-своему. Как разработчик, вы должны пытаться развить все эти навыки, чтобы добиться успеха.
1. Аналитические навыки
Это способность собирать и анализировать данные, выявлять закономерности и тенденции и принимать решения на основе этой информации. Они предполагают как логическое, так и творческое мышление, а также способность обращать внимание на детали. Некоторые примеры:
- Умение разбить проблему и идентифицировать различные компоненты,
- Умение определять закономерности и тенденции,
- Умение видеть связи между различными частями данных,
- Умение принимать решения на основе данных,
- Умение решать сложные задачи.
2. Креативное мышление
В компьютерных науках оно связано с поиском новых и инновационных способов решения проблем. Речь идёт о нестандартном мышлении и поиске креативных решений, о которых раньше никто не думал. В ИТ важно проявлять творческий подход, потому что это постоянно развивающаяся область. Если вы не будете постоянно генерировать новые идеи, вы отстанете. Креативное мышление — это то, что заставляет информатику двигаться вперед.
3. Логическое рассуждение
Это процесс получения выводов на основе имеющейся информации. В информатике он часто используется для решения задач и создания новых алгоритмов. Чтобы рассуждать логически, нужно сначала идентифицировать факты, а затем использовать их, чтобы прийти к правильному заключению.
Итого
Практика — один из лучших способов улучшить свои навыки решения проблем.
Вы можете делать это, работая над задачами по кодированию, участвуя в онлайн-конкурсах или просто пытаясь решить проблемы, с которыми вы сталкиваетесь в своей повседневной работе.
Сотрудничество — ещё один отличный способ улучшить свои навыки решения проблем. Когда вы работаете с другими, вы можете учиться на их опыте и делиться своими мыслями. Это может помочь вам выработать более качественный подход к решению проблем.
И последнее: смиритесь с тем, что вы будете застревать. Застрять при решении какой-то проблемы и попросить помощи – это нормально. Нет ничего постыдного в том, чтобы признать, что вам нужна помощь.
Источник: https://dev.to/nathan20/how-to-develop-strong-problem-solving-skills-as-a-software-developer-25nb
👍10
Что выведет код?
var tasks = Enumerable.Range(0, 2)
.Select(_ => Task.Run( () => Console.Write("*"))); await Task.WhenAll(tasks); Console.Write(tasks.Count()); #Quiz #CSharp
var tasks = Enumerable.Range(0, 2)
.Select(_ => Task.Run( () => Console.Write("*"))); await Task.WhenAll(tasks); Console.Write(tasks.Count()); #Quiz #CSharp
Anonymous Quiz
4%
2
51%
**2
7%
**2**
10%
****2
27%
Что-то другое
День 1305. #Оффтоп #Юмор
Сегодня порекомендую вам крайне познавательный и, в то же время, уморительный доклад Марка Рендла “Programming’s Greatest Mistakes” (Величайшие ошибки в программировании) https://youtu.be/qC_ioJQpv4E с конференции NDC Copenhagen 2022, прошедшей с 30 мая по 2 июня.
В большинстве случаев, когда мы делаем ошибки в нашем коде, всё ограничивается тем, что пользователь получает неправильное сообщение или не отправляется счёт. Но иногда, когда люди делают ошибки в коде, всё в буквальном смысле взрывается, банкротятся компании, или веб-разработка превращается в сущий ад для миллионов программистов на долгие годы.
Марк описывает некоторые из самых серьёзных ошибок в истории программирования. Узнайте, что пошло не так, почему это пошло не так, сколько это стоило и насколько забавны вещи, когда они происходят не с вами.
Кстати, если вы допустили серьёзную ошибку, и не знаете, как теперь быть, прочитайте этот пост.
Сегодня порекомендую вам крайне познавательный и, в то же время, уморительный доклад Марка Рендла “Programming’s Greatest Mistakes” (Величайшие ошибки в программировании) https://youtu.be/qC_ioJQpv4E с конференции NDC Copenhagen 2022, прошедшей с 30 мая по 2 июня.
В большинстве случаев, когда мы делаем ошибки в нашем коде, всё ограничивается тем, что пользователь получает неправильное сообщение или не отправляется счёт. Но иногда, когда люди делают ошибки в коде, всё в буквальном смысле взрывается, банкротятся компании, или веб-разработка превращается в сущий ад для миллионов программистов на долгие годы.
Марк описывает некоторые из самых серьёзных ошибок в истории программирования. Узнайте, что пошло не так, почему это пошло не так, сколько это стоило и насколько забавны вещи, когда они происходят не с вами.
Кстати, если вы допустили серьёзную ошибку, и не знаете, как теперь быть, прочитайте этот пост.
👍4
День 1306. #TypesAndLanguages
7. Инкапсуляция или Публичное Всё
Сейчас немного разожгу:
Всё должно быть публичным. Не используйте модификатор private вообще.
А теперь давайте обсудим это немного подробнее.
Одно из свойств инкапсуляции состоит в сокрытии внутреннего устройства. Это может выражаться в различных формах. Самая простая из них — геттеры и сеттеры. Мы делаем поля приватными, а затем открываем методы доступа для чтения и записи. Однако всё может быть общедоступным, и при этом мы всё равно можем скрывать внутренности. Как это возможно?
Бывают ситуации, когда нам нужно получить доступ к некоторым внутренним элементам или изменить их. Либо напрямую, либо через рефлексию, либо через взлом памяти. Проблема в том, что в большинстве случаев компиляторы нам не помогут в таких ситуациях. Компиляторы не будут проверять вашу рефлексию, верна она у вас или нет. Они не остановят компиляцию вашего небезопасного низкоуровневого кода, если он неверен. Это значительно усложняет работу с внутренними компонентами, поскольку они могут быть изменены практически в любое время, а у нас нет механизма, позволяющего обнаружить, что изменение нарушает наш код. Однако такой проблемы не бывает, когда всё публично. Если вы обращаетесь к внутренним компонентам напрямую, компилятор сообщит вам, когда произойдёт критическое изменение. Это позволяет находить ошибки намного раньше и намного проще.
Но как мы можем скрывать внутренности, когда всё публично? Ответ: представления. С помощью различных представлений, которые в большинстве языков реализованы через интерфейсы, мы можем предоставлять абстракцию, но по-прежнему иметь доступ к внутренним компонентам. Представьте, что у нас есть следующий класс:
Это может быть реализовано несколькими способами в разных языках: интерфейсы, заголовочные файлы, разные пакеты для абстракции и реализации. Есть несколько решений, позволяющих сделать внутреннее содержимое общедоступным.
Примечание: От себя добавлю, что делать совсем всё публичным, наверное, чересчур радикально. На моей практике доступ к внутренностям нужен не так часто, поэтому такой проблемы обычно не возникает. Но в принципе, подход с сокрытием через интерфейс интересный.
Что скажете?
Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/
Автор оригинала: Adam Furmanek
7. Инкапсуляция или Публичное Всё
Сейчас немного разожгу:
Всё должно быть публичным. Не используйте модификатор private вообще.
А теперь давайте обсудим это немного подробнее.
Одно из свойств инкапсуляции состоит в сокрытии внутреннего устройства. Это может выражаться в различных формах. Самая простая из них — геттеры и сеттеры. Мы делаем поля приватными, а затем открываем методы доступа для чтения и записи. Однако всё может быть общедоступным, и при этом мы всё равно можем скрывать внутренности. Как это возможно?
Бывают ситуации, когда нам нужно получить доступ к некоторым внутренним элементам или изменить их. Либо напрямую, либо через рефлексию, либо через взлом памяти. Проблема в том, что в большинстве случаев компиляторы нам не помогут в таких ситуациях. Компиляторы не будут проверять вашу рефлексию, верна она у вас или нет. Они не остановят компиляцию вашего небезопасного низкоуровневого кода, если он неверен. Это значительно усложняет работу с внутренними компонентами, поскольку они могут быть изменены практически в любое время, а у нас нет механизма, позволяющего обнаружить, что изменение нарушает наш код. Однако такой проблемы не бывает, когда всё публично. Если вы обращаетесь к внутренним компонентам напрямую, компилятор сообщит вам, когда произойдёт критическое изменение. Это позволяет находить ошибки намного раньше и намного проще.
Но как мы можем скрывать внутренности, когда всё публично? Ответ: представления. С помощью различных представлений, которые в большинстве языков реализованы через интерфейсы, мы можем предоставлять абстракцию, но по-прежнему иметь доступ к внутренним компонентам. Представьте, что у нас есть следующий класс:
class Foo {Можно сказать, что это хорошо, потому что класс скрывает
public void Bar() { … }
private void BarInternals() { … }
}
BarInternals
, делая его приватным. Таким образом, вызывающая сторона не может получить доступ к внутренним компонентам и не нарушит их. Однако можно использовать интерфейсы:interface IFoo {Теперь любой «порядочный» клиент, вызывающий объект, должен использовать
void Bar();
}
class Foo : IFoo {
public void Bar() { … }
public void BarInternals() { … }
}
Foo
через интерфейс IFoo
, поэтому метод BarInternals
останется недоступным. Дело не в том, что он приватный или доступ заблокирован контроллером политик. Метода просто нет! Однако, если кому-то нужно схитрить, он может привести IFoo
к Foo
и получить поддержку компилятора, чтобы убедиться, что BarInternals
существует.Это может быть реализовано несколькими способами в разных языках: интерфейсы, заголовочные файлы, разные пакеты для абстракции и реализации. Есть несколько решений, позволяющих сделать внутреннее содержимое общедоступным.
Примечание: От себя добавлю, что делать совсем всё публичным, наверное, чересчур радикально. На моей практике доступ к внутренностям нужен не так часто, поэтому такой проблемы обычно не возникает. Но в принципе, подход с сокрытием через интерфейс интересный.
Что скажете?
Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/
Автор оригинала: Adam Furmanek
👍12👎3
День 1307. #Книги
Прочитал книгу «Принципы юнит-тестирования» (Владимир Хориков — СПб.: Питер, 2022).
Книга в целом понравилась. Хорошо расставляет по местам имеющиеся знания о тестировании и добавляет логические связи. Это мне в книгах нравится больше всего – ощущение, что пазл из твоих обрывочных знаний собирается вместе, дополняется недостающими частичками и складывается в единую картину.
В книге довольно подробно описана теория: что такое тесты, какие они бывают, из чего состоят, зачем их делать и какие правила стоит соблюдать, а чего лучше не делать (например, что не стоит гнаться за метриками покрытия кода). Вообще, на канале отрывков из книги приводилось уже довольно много. Их можно найти по тегу #Testing. А вот здесь есть даже шпаргалка по юнит-тестам, по мотивам книги.
Что не совсем понравилось. На мой взгляд примеры в книге слишком упрощены. Я понимаю, что невозможно в печатном издании приводить многостраничные листинги кода. Но, например, в книге «Внедрение зависимостей на платформе .NET», на которую Владимир частенько ссылается, авторам удалось привести примеры реальных приложений и реальных проблем, с которыми можно столкнуться. Здесь же, как мне показалось, примеры приводятся слишком простые, и часто за ними следует фраза вроде «понятно, что в реальных системах всё будет намного сложнее».
В чём я лично вижу проблему с переупрощёнными примерами. Требуется опыт, чтобы придумать, где это будет применено в реальности. А это нужно, чтобы кусочек пазла встал на своё место. У меня с этим проблем не возникло, потому что я в последнее время всерьёз занялся внедрением тестов на своей основной работе (собственно, поэтому и книгу приобрёл). Я уже столкнулся с большинством описанных препятствий, поэтому у меня они «легли в контекст», и я довольно часто ловил себя на мысли «а, так вот как это надо было делать». Или же я легко представлял, где я смогу это использовать.
Однако у человека, не имеющего хотя бы небольшого опыта в тестировании серьёзного приложения, как мне кажется, может возникнуть проблема с обоснованием нужности того или иного утверждения из книги. А когда факт зависает вне контекста, не отвечая на вопрос «зачем?», он быстро забывается. Хотя, в этом случае можно посоветовать прочитать книгу, узнать основы, а затем перелистать её после получения некоторой реальной практики (и пары шишек).
Прочитал книгу «Принципы юнит-тестирования» (Владимир Хориков — СПб.: Питер, 2022).
Книга в целом понравилась. Хорошо расставляет по местам имеющиеся знания о тестировании и добавляет логические связи. Это мне в книгах нравится больше всего – ощущение, что пазл из твоих обрывочных знаний собирается вместе, дополняется недостающими частичками и складывается в единую картину.
В книге довольно подробно описана теория: что такое тесты, какие они бывают, из чего состоят, зачем их делать и какие правила стоит соблюдать, а чего лучше не делать (например, что не стоит гнаться за метриками покрытия кода). Вообще, на канале отрывков из книги приводилось уже довольно много. Их можно найти по тегу #Testing. А вот здесь есть даже шпаргалка по юнит-тестам, по мотивам книги.
Что не совсем понравилось. На мой взгляд примеры в книге слишком упрощены. Я понимаю, что невозможно в печатном издании приводить многостраничные листинги кода. Но, например, в книге «Внедрение зависимостей на платформе .NET», на которую Владимир частенько ссылается, авторам удалось привести примеры реальных приложений и реальных проблем, с которыми можно столкнуться. Здесь же, как мне показалось, примеры приводятся слишком простые, и часто за ними следует фраза вроде «понятно, что в реальных системах всё будет намного сложнее».
В чём я лично вижу проблему с переупрощёнными примерами. Требуется опыт, чтобы придумать, где это будет применено в реальности. А это нужно, чтобы кусочек пазла встал на своё место. У меня с этим проблем не возникло, потому что я в последнее время всерьёз занялся внедрением тестов на своей основной работе (собственно, поэтому и книгу приобрёл). Я уже столкнулся с большинством описанных препятствий, поэтому у меня они «легли в контекст», и я довольно часто ловил себя на мысли «а, так вот как это надо было делать». Или же я легко представлял, где я смогу это использовать.
Однако у человека, не имеющего хотя бы небольшого опыта в тестировании серьёзного приложения, как мне кажется, может возникнуть проблема с обоснованием нужности того или иного утверждения из книги. А когда факт зависает вне контекста, не отвечая на вопрос «зачем?», он быстро забывается. Хотя, в этом случае можно посоветовать прочитать книгу, узнать основы, а затем перелистать её после получения некоторой реальной практики (и пары шишек).
👍13
День 1308. #ЗаметкиНаПолях
Принудительный HTTPS в Приложениях ASP.NET Core. Начало
Как заставить ваше приложение ASP.NET Core использовать только HTTPS? Изучаем лучшие практики для различных сценариев.
1. Использовать перенаправление HTTPS
Если клиент вызывает приложение, используя HTTP, приложение перенаправляет его на тот же URL-адрес, начинающийся с HTTPS. Перенаправление URL — хорошо известный подход. Веб-приложение создает ответ HTTP с кодом состояния, начинающимся с 3, и заголовком Location, как в следующем примере:
2. Атрибут RequireHttps
Его можно использовать в приложениях, чтобы заставить страницу требовать HTTPS. В Razor Pages
Можно применить
3. Промежуточное ПО перенаправления на HTTPS
При создании веб-приложения с использованием одного из стандартных шаблонов проектов ASP.NET файл Program.cs (Startup.cs) содержит вызов метода
4. Промежуточное ПО HSTS
К сожалению, принудительного переключения клиента с HTTP на HTTPS при каждом запросе может быть недостаточно для предотвращения атак с понижением протокола. Злоумышленник может перехватить HTTP-запрос клиента до того, как он переключится на соответствующий HTTPS-запрос.
Нужен способ указать браузеру обязательно использовать HTTPS для запроса любого ресурса веб-приложения. Это заголовок HTTP Strict-Transport-Security (HSTS). Имея заголовок HSTS, браузер будет вызывать ваше приложение с использованием HTTP только в самый первый раз. Последующие запросы к тому же домену будут выполняться через HTTPS, даже если в адресе будет HTTP. Включить HSTS можно с помощью метода
Окончание следует…
Источник: https://auth0.com/blog/force-https-in-aspnet-core-apps/
Принудительный HTTPS в Приложениях ASP.NET Core. Начало
Как заставить ваше приложение ASP.NET Core использовать только HTTPS? Изучаем лучшие практики для различных сценариев.
1. Использовать перенаправление HTTPS
Если клиент вызывает приложение, используя HTTP, приложение перенаправляет его на тот же URL-адрес, начинающийся с HTTPS. Перенаправление URL — хорошо известный подход. Веб-приложение создает ответ HTTP с кодом состояния, начинающимся с 3, и заголовком Location, как в следующем примере:
HTTP/1.1 301 Moved PermanentlyЭтот подход не устраняет все риски безопасности, но является хорошей отправной точкой. К счастью, в ASP.NET Core есть несколько других вариантов.
Location: https://...
2. Атрибут RequireHttps
Его можно использовать в приложениях, чтобы заставить страницу требовать HTTPS. В Razor Pages
RequireHttps
можно применять только к классам, страниц, либо к методам класса:[RequireHttps]В ASP.NET Core MVC можно применить атрибут
public class PrivacyModel : PageModel
{ … }
RequireHttps
к классам, контроллеров или к их методам действия:[RequireHttps]Есть соблазн применять атрибут выборочно к определённым страницам или представлениям, таким образом ограничить HTTPS только страницами с конфиденциальным содержимым. Но смешивание страниц HTTP и HTTPS — очень плохая идея! Ваше приложение так подвергается атакам с понижением протокола. Это разновидность атак man-in-the-middle, когда HTTP запрос перехватывается атакующим, и таким образом компрометируется вся безопасность последующей коммуникации между клиентом и сервером.
public class HomeController : Controller
{ … }
Можно применить
RequireHttps
ко всем страницам, но есть и более простые способы.3. Промежуточное ПО перенаправления на HTTPS
При создании веб-приложения с использованием одного из стандартных шаблонов проектов ASP.NET файл Program.cs (Startup.cs) содержит вызов метода
UseHttpsRedirection()
в конвейере промежуточного ПО:…Вызов метода
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
…
UseHttpsRedirection()
означает, что каждый запрос к вашему приложению будет проверен и, возможно, перенаправлен промежуточным ПО. Все страницы вашего приложения будут требовать HTTPS. 4. Промежуточное ПО HSTS
К сожалению, принудительного переключения клиента с HTTP на HTTPS при каждом запросе может быть недостаточно для предотвращения атак с понижением протокола. Злоумышленник может перехватить HTTP-запрос клиента до того, как он переключится на соответствующий HTTPS-запрос.
Нужен способ указать браузеру обязательно использовать HTTPS для запроса любого ресурса веб-приложения. Это заголовок HTTP Strict-Transport-Security (HSTS). Имея заголовок HSTS, браузер будет вызывать ваше приложение с использованием HTTP только в самый первый раз. Последующие запросы к тому же домену будут выполняться через HTTPS, даже если в адресе будет HTTP. Включить HSTS можно с помощью метода
UseHsts()
. Этот вызов также уже включён в шаблоны веб-приложений ASP.NET Core:if (!app.Environment.IsDevelopment())По умолчанию поддержка HSTS отключена в вашей среде разработки. Скорее всего, вы используете localhost в качестве домена. Если вы используете HSTS, любой запрос, сделанный вашим браузером к локальному хосту, будет использовать HTTPS. Это является хорошей практикой. Но при этом браузер будет делать HTTPS-запросы к любому приложению, размещённому на локальном хосте. Это может вызвать проблемы, например с Angular приложениями.
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Окончание следует…
Источник: https://auth0.com/blog/force-https-in-aspnet-core-apps/
👍10
День 1309. #ЗаметкиНаПолях
Принудительный HTTPS в Приложениях ASP.NET Core. Окончание
Начало
Перенаправление HTTPS и API
Подход с перенаправлением HTTPS основан на отправке обратно клиенту кода состояния 301 или другого 30* HTTP, независимо от того, используете ли вы атрибут
Оба подхода хорошо понимаются стандартными браузерами. Таким образом, на эти подходы могут полагаться типы приложений, клиентами которых являются браузеры, например приложения ASP.NET Core MVC, Razor Pages и Blazor Server.
Однако эти подходы обычно игнорируются небраузерными клиентами, такими как клиенты API. Мобильное приложение или SPA крайне редко заботятся о кодах состояния 301 или заголовках HSTS. В этом случае есть два альтернативных способа работы с клиентами, которые делают HTTP-запросы:
1. Игнорировать HTTP-запросы
Один из самых простых способов — использовать флаг
В производственной среде можно задать переменную окружения
PowerShell:
Для этого потребуется собственное промежуточное ПО вместо
Перенаправление HTTPS и обратные прокси
Все вышеизложенное имеет смысл, если ваше приложение ASP.NET Core напрямую подключено к Интернету. Если ваше приложение развернуто в среде с обратным прокси-сервером, который обеспечивает безопасность подключения, нет необходимости использовать перенаправление HTTPS или промежуточное ПО HSTS. В этом случае вы можете просто удалить вызовы методов
Источник: https://auth0.com/blog/force-https-in-aspnet-core-apps/
Принудительный HTTPS в Приложениях ASP.NET Core. Окончание
Начало
Перенаправление HTTPS и API
Подход с перенаправлением HTTPS основан на отправке обратно клиенту кода состояния 301 или другого 30* HTTP, независимо от того, используете ли вы атрибут
RequireHttps
или ПО промежуточного слоя для перенаправления HTTPS. Подход HSTS основан на отправке заголовка Strict-Transport-Security.Оба подхода хорошо понимаются стандартными браузерами. Таким образом, на эти подходы могут полагаться типы приложений, клиентами которых являются браузеры, например приложения ASP.NET Core MVC, Razor Pages и Blazor Server.
Однако эти подходы обычно игнорируются небраузерными клиентами, такими как клиенты API. Мобильное приложение или SPA крайне редко заботятся о кодах состояния 301 или заголовках HSTS. В этом случае есть два альтернативных способа работы с клиентами, которые делают HTTP-запросы:
1. Игнорировать HTTP-запросы
Один из самых простых способов — использовать флаг
--urls
команды запуска dotnet
, как показано ниже:dotnet run --urls "https://localhost:7123"Это переопределит настройки URL в файле Properties/launchSettings.json проекта ASP.NET Core.
В производственной среде можно задать переменную окружения
ASPNETCORE_URLS
.PowerShell:
$Env: ASPNETCORE_URLS = "https://localhost:7123"Bash:
export ASPNETCORE_URLS=https://localhost:71232. Выдавать на HTTP-запросы код ответа Bad Request
Для этого потребуется собственное промежуточное ПО вместо
UseHttpsRedirection()
и UseHsts()
://app.UseHttpsRedirection();Код выше просто проверяет, использует ли текущий запрос HTTPS. Если это не так, он отвечает кодом состояния 400 Bad Request и сообщением, предупреждающим, что требуется HTTPS.
app.Use(async (context, next) => {
if (!context.Request.IsHttps) {
context.Response.StatusCode =
StatusCodes.Status400BadRequest;
await context
.Response
.WriteAsync("HTTPS required!");
}
else {
await next(context);
}
});
Перенаправление HTTPS и обратные прокси
Все вышеизложенное имеет смысл, если ваше приложение ASP.NET Core напрямую подключено к Интернету. Если ваше приложение развернуто в среде с обратным прокси-сервером, который обеспечивает безопасность подключения, нет необходимости использовать перенаправление HTTPS или промежуточное ПО HSTS. В этом случае вы можете просто удалить вызовы методов
UseHttpsRedirection()
и UseHsts()
из веб-приложений или собственное промежуточное ПО из примера выше для веб-API. Вы делегируете переключение с HTTP на HTTPS и управление ответами обратному прокси-серверу.Источник: https://auth0.com/blog/force-https-in-aspnet-core-apps/
👍10
День 1310. #Карьера
С началом нового учебного года всех!
Лично для меня 1 сентября до сих пор остаётся днём старта чего-то нового. Стартует учебный год (теперь уже у детей), старт нового телесезона, старт многих осенне-весенних спортивных сезонов. В общем, повод выползать из отпускного настроения и приниматься за работу.
Поэтому сегодня поговорим о нашем злейшем враге – прокрастинации.
«По результатам многочисленных опросов, около 95% людей признают, что часто откладывают дела на потом.» (Остальные 5% просто врут).
- Пирс Стил «Уравнение прокрастинации»
Прокрастинация — увлекательная тема, и столь же увлекательной является наука, стоящая за ней. Исследования показывают, что у задачи есть шесть атрибутов, которые заставляют нас с большей вероятностью отложить её.
Мы гораздо более склонны откладывать на потом, когда задача:
1. Скучная (например, написание документации).
2. Разочаровывающая или рутинная (например, изучение нового навыка).
3. Сложная (например, дебаг плавающей ошибки).
4. Неоднозначная или неструктурированная (например, подготовка к марафону или реализация большого проекта).
5. Не содержащая в себе вознаграждения (например, всё то же написание документации, зная, что её никто не будет читать).
6. Не имеющая ценности для вас лично (например, уборка домашнего офиса).
Чем больше этих атрибутов имеет задача, тем больше вероятность, что мы её отложим.
Постараемся побороть каждый из этих атрибутов.
1. Делайте скучные задачи более увлекательными. Если нужно писать документацию, пойдите в любимое кафе и сделайте это за чашкой какого-нибудь экзотического кофе. Если выполнение задачи не требует умственных усилий, скачайте интересную аудиокнигу или подкаст.
2. Установите ограничение по времени для разочаровывающих задач. Занимайтесь задачей в течение 20-30 минут, а дальше – как пойдёт. Сделайте из этого игру. К примеру, Microsoft Learn имеет для этого очки опыта и бейджи за каждый изученный навык.
3. Разбейте сложную задачу на более мелкие и составьте план работы. Работайте над самыми сложными задачами во время вашего биологического прайм-тайма (подробнее о нём тут). Кроме того, не стесняйтесь просить помощи.
4. Составьте план неоднозначных и неструктурированных задач. Например, потратьте 20 минут на то, чтобы наметить следующие шаги по проекту. Вычёркивайте выполненные пункты. Поищите примеры того, как другие справлялись с такими задачами.
5. Побалуйте себя, выполняя задачи, которые не содержат в себе вознаграждения. Например, откладывайте доллар (или любой эквивалент) на какой-нибудь ваш каприз за каждые 10 минут работы (работы, а не прокрастинации) над задачей.
6. Ищите позитивные стороны в задачах, не имеющих ценности для вас лично. Например, убранное рабочее место позволяет чувствовать себя более спокойно, организованно и работать более продуктивно.
А вот ещё 3 совета:
1. Составьте список задач на случай, когда поймаете себя на прокрастинации. Главное, чтобы эти задачи имели хоть какую-нибудь пользу и ценность для вас. Это позволит вернуть чувство продуктивности, если основная задача никак не решается. Можно заняться хоть чем-то полезным, пусть это будет даже наведение порядка в папках на компьютере, обновление IDE или написания маленького скрипта для автоматизации ежедневных рутинных действий. Но не слишком увлекайтесь.
2. Составьте список негативных последствий. Простое перечисление и осознание негативных последствий от несделанного дела – отличный мотиватор взяться за работу.
3. Просто начните. Поставьте таймер на 15 минут, после чего позволите себе остановиться и заняться чем-то другим. Иногда задача не настолько неприятная, как вам изначально казалось. Если через 15 минут вы чувствуете в себе силы продолжать – продолжайте.
Прокрастинация — это человеческий феномен: все на планете откладывают дела. В следующий раз, когда вы заметите, что откладываете что-то, обратите внимание на то, что заставляет вас отложить задачу и составьте простой план противодействия этому. В результате вы сделаете намного больше.
Источник: https://alifeofproductivity.com/what-triggers-procrastination/
С началом нового учебного года всех!
Лично для меня 1 сентября до сих пор остаётся днём старта чего-то нового. Стартует учебный год (теперь уже у детей), старт нового телесезона, старт многих осенне-весенних спортивных сезонов. В общем, повод выползать из отпускного настроения и приниматься за работу.
Поэтому сегодня поговорим о нашем злейшем враге – прокрастинации.
«По результатам многочисленных опросов, около 95% людей признают, что часто откладывают дела на потом.» (Остальные 5% просто врут).
- Пирс Стил «Уравнение прокрастинации»
Прокрастинация — увлекательная тема, и столь же увлекательной является наука, стоящая за ней. Исследования показывают, что у задачи есть шесть атрибутов, которые заставляют нас с большей вероятностью отложить её.
Мы гораздо более склонны откладывать на потом, когда задача:
1. Скучная (например, написание документации).
2. Разочаровывающая или рутинная (например, изучение нового навыка).
3. Сложная (например, дебаг плавающей ошибки).
4. Неоднозначная или неструктурированная (например, подготовка к марафону или реализация большого проекта).
5. Не содержащая в себе вознаграждения (например, всё то же написание документации, зная, что её никто не будет читать).
6. Не имеющая ценности для вас лично (например, уборка домашнего офиса).
Чем больше этих атрибутов имеет задача, тем больше вероятность, что мы её отложим.
Постараемся побороть каждый из этих атрибутов.
1. Делайте скучные задачи более увлекательными. Если нужно писать документацию, пойдите в любимое кафе и сделайте это за чашкой какого-нибудь экзотического кофе. Если выполнение задачи не требует умственных усилий, скачайте интересную аудиокнигу или подкаст.
2. Установите ограничение по времени для разочаровывающих задач. Занимайтесь задачей в течение 20-30 минут, а дальше – как пойдёт. Сделайте из этого игру. К примеру, Microsoft Learn имеет для этого очки опыта и бейджи за каждый изученный навык.
3. Разбейте сложную задачу на более мелкие и составьте план работы. Работайте над самыми сложными задачами во время вашего биологического прайм-тайма (подробнее о нём тут). Кроме того, не стесняйтесь просить помощи.
4. Составьте план неоднозначных и неструктурированных задач. Например, потратьте 20 минут на то, чтобы наметить следующие шаги по проекту. Вычёркивайте выполненные пункты. Поищите примеры того, как другие справлялись с такими задачами.
5. Побалуйте себя, выполняя задачи, которые не содержат в себе вознаграждения. Например, откладывайте доллар (или любой эквивалент) на какой-нибудь ваш каприз за каждые 10 минут работы (работы, а не прокрастинации) над задачей.
6. Ищите позитивные стороны в задачах, не имеющих ценности для вас лично. Например, убранное рабочее место позволяет чувствовать себя более спокойно, организованно и работать более продуктивно.
А вот ещё 3 совета:
1. Составьте список задач на случай, когда поймаете себя на прокрастинации. Главное, чтобы эти задачи имели хоть какую-нибудь пользу и ценность для вас. Это позволит вернуть чувство продуктивности, если основная задача никак не решается. Можно заняться хоть чем-то полезным, пусть это будет даже наведение порядка в папках на компьютере, обновление IDE или написания маленького скрипта для автоматизации ежедневных рутинных действий. Но не слишком увлекайтесь.
2. Составьте список негативных последствий. Простое перечисление и осознание негативных последствий от несделанного дела – отличный мотиватор взяться за работу.
3. Просто начните. Поставьте таймер на 15 минут, после чего позволите себе остановиться и заняться чем-то другим. Иногда задача не настолько неприятная, как вам изначально казалось. Если через 15 минут вы чувствуете в себе силы продолжать – продолжайте.
Прокрастинация — это человеческий феномен: все на планете откладывают дела. В следующий раз, когда вы заметите, что откладываете что-то, обратите внимание на то, что заставляет вас отложить задачу и составьте простой план противодействия этому. В результате вы сделаете намного больше.
Источник: https://alifeofproductivity.com/what-triggers-procrastination/
👍6
Что мы говорим богу прокрастинации?
Anonymous Poll
30%
Не сегодня!
30%
Ещё 5 минуточек…
14%
Почему бы и нет?
26%
@#%*@#!, дедлайн!
👍12
День 1311. #ЗаметкиНаПолях #AsyncTips
Взаимодействие с другими системами отмены
Задача
Имеется внешний или унаследованный код с собственными концепциями отмены. Требуется управлять им с использованием стандартного объекта
Решение
У типа
Допустим, вы пишете обертку для
Метод
Помните о сроке существования регистрации обратных вызовов. Метод
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
Взаимодействие с другими системами отмены
Задача
Имеется внешний или унаследованный код с собственными концепциями отмены. Требуется управлять им с использованием стандартного объекта
CancellationToken
.Решение
У типа
CancellationToken
существует два основных способа реакции на запрос на отмену: периодический опрос и обратные вызовы. Периодический опрос обычно используется для кода, интенсивно использующего процессор, — например, циклов обработки данных; обратные вызовы обычно используются во всех остальных ситуациях. Регистрация обратного вызова для маркера осуществляется методом CancellationToken.Register
.Допустим, вы пишете обертку для
System.Net.NetworkInformation.Pingtype
и хотите предусмотреть возможность отмены тестового опроса. Класс Ping
уже имеет API на базе Task
, но не поддерживает CancellationToken
. Вместо этого тип Ping
содержит собственный метод SendAsyncCancel
, который может использоваться для отмены. Для этого зарегистрируйте обратный вызов, который активизирует этот метод:async Task<PingReply> PingAsync(
string host,
CancellationToken ct)
{
using var ping = new Ping();
var task = ping.SendPingAsync(host);
using CancellationTokenRegistration _ =
ct.Register(() => ping.SendAsyncCancel());
return await task;
}
Теперь при запросе на отмену CancellationToken
вызовет метод SendAsyncCancel
за вас, отменяя метод SendPingAsync
.Метод
CancellationToken.Register
может использоваться для взаимодействия с любой альтернативной системой отмены. Но следует помнить, что, если метод получает CancellationToken
, запрос отмены должен отменять только эту одну операцию. Некоторые альтернативные системы отмены реализуют отмену закрытием некоторого ресурса, что может привести к отмене нескольких операций; эта разновидность системы отмены плохо соответствует CancellationToken
. Если вы решите инкапсулировать такую разновидность отмены в CancellationToken
, следует документировать её необычную семантику отмены.Помните о сроке существования регистрации обратных вызовов. Метод
Register
возвращает отменяемый объект, который должен быть освобожден, когда обратный вызов перестанет быть нужным. Предыдущий пример использует команду using для выполнения очистки при завершении асинхронной операции. Если в коде отсутствует команда using, то при каждом вызове кода с тем же (долгосрочным) маркером CancellationToken
он будет добавлять новый обратный вызов (который, в свою очередь, будет поддерживать существование объекта Ping
). Чтобы избежать утечки памяти и ресурсов, очищайте регистрацию обратного вызова, когда он перестаёт быть нужным.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
👍8
День 1312. #CodeReview
Насколько Хорош Ваш Процесс Код-Ревью?
Если ваша команда считает код-ревью пустой тратой времени, то они правы. Те, кто не ценит проверки кода, откладывают их выполнение, часто мало чего находят, либо их комментарии носят чисто стилистический характер. В такой команде внедрение код-ревью может только ухудшить процесс разработки, замедлив его без улучшения качества кода.
Можно построить процесс проверки кода, который будет повышать эффективность, но нужно действовать целенаправленно. Во-первых, организация должна договориться о целях. Во-вторых, нужно регулярно отслеживать показатели проверки, чтобы убедиться, что цели достигнуты и процесс работает исправно.
Согласованность
Эффективный процесс код-ревью начинается с согласования цели - под какие результаты оптимизируется процесс? Выявление ошибок, улучшение сопровождаемости, повышение стилистической согласованности или обмен знаниями в команде? Определение приоритетов поможет команде сосредоточиться на том, какие отзывы оставлять и что искать.
Ключевые показатели
Метрики могут быть разными в зависимости от целей, но есть несколько общих, которые позволят быстро диагностировать и устранять проблемы, связанные с процессом проверки.
1. Скорость
«Время до первого отзыва» — среднее время ожидания отзыва отправителем. Когда этот показатель высок, отправители либо тратят время на ожидание, либо вынуждены делать что-то другое. Если это происходит, важно согласовать ожидания от проверки кода и то, как проверки могут быть лучше интегрированы в повседневные процессы. Определите, что для вас означает «низкое» время до первого отзыва. Относительно этого можно углубляться в индивидуальные и командные показатели: размер пул-реквестов, баланс рабочей нагрузки и скорость проверки. Важно снизить время до первого отзыва настолько, насколько это возможно, без ущерба для внимания и производительности рецензентов.
2. Покрытие
Если ваша цель — улучшить качество кода и выявить ошибки, важно сравнить количество файлов с комментариями в обзоре с количеством изменённых файлов в пул-реквесте. Это будет показателем тщательности проверки. Не существует оптимального числа, но вы должны убедиться, что результат соответствует ожиданиям. Чтобы рецензенты не просто проштамповывали любые изменения, но, и чтобы не сильно придирались и не замедляли процесс.
3. Влияние
Одно только покрытие отзывами не говорит о качестве кода. Важно посмотреть, все ли эти отзывы приводят к действиям? Для этого отслеживайте процент комментариев, которые приводят к ответным комментариям или изменениям в коде. Большое количество комментариев с низким «влиянием» указывает на то, что отзывы рецензентов не воспринимаются как ценные для отправителя. Это может потребовать перестройки того, как должны проводиться проверки кода.
4. Циклы
Пулл-реквесты, перескакивающие туда-сюда между автором и рецензентом, могут замедлять процесс. Если это происходит часто, процесс рецензирования может стать узким местом и источником демотивации для инженеров, пытающихся завершить свою работу.
Средний показатель может меняться по многим причинам. Привлечение новых разработчиков может вызвать всплеск. Однако такой всплеск в опытной команде часто является признаком рассогласованности представлений:
- о том, что значит «готово»,
- какие изменения ожидаются после комментария,
- как должно быть реализовано решение.
Если количество циклов проверки для определённого отправителя велико, это может означать, что он не понимает кодовую базу или имеет дело с нечёткими требованиями.
Проверка кода — один из самых сложных процессов в команде разработчиков ПО. В каждой команде существует свой идеальный баланс тщательности и скорости, и этот баланс может даже измениться для данной команды из-за изменения приоритетов. Менеджеры должны постоянно следить за процессом код-ревью, беседовать с командой, чтобы собрать информацию, необходимую для придания контекста метрикам проверки кода и придания им значимости.
Источник: https://thenewstack.io/how-good-is-your-code-review-process/
Насколько Хорош Ваш Процесс Код-Ревью?
Если ваша команда считает код-ревью пустой тратой времени, то они правы. Те, кто не ценит проверки кода, откладывают их выполнение, часто мало чего находят, либо их комментарии носят чисто стилистический характер. В такой команде внедрение код-ревью может только ухудшить процесс разработки, замедлив его без улучшения качества кода.
Можно построить процесс проверки кода, который будет повышать эффективность, но нужно действовать целенаправленно. Во-первых, организация должна договориться о целях. Во-вторых, нужно регулярно отслеживать показатели проверки, чтобы убедиться, что цели достигнуты и процесс работает исправно.
Согласованность
Эффективный процесс код-ревью начинается с согласования цели - под какие результаты оптимизируется процесс? Выявление ошибок, улучшение сопровождаемости, повышение стилистической согласованности или обмен знаниями в команде? Определение приоритетов поможет команде сосредоточиться на том, какие отзывы оставлять и что искать.
Ключевые показатели
Метрики могут быть разными в зависимости от целей, но есть несколько общих, которые позволят быстро диагностировать и устранять проблемы, связанные с процессом проверки.
1. Скорость
«Время до первого отзыва» — среднее время ожидания отзыва отправителем. Когда этот показатель высок, отправители либо тратят время на ожидание, либо вынуждены делать что-то другое. Если это происходит, важно согласовать ожидания от проверки кода и то, как проверки могут быть лучше интегрированы в повседневные процессы. Определите, что для вас означает «низкое» время до первого отзыва. Относительно этого можно углубляться в индивидуальные и командные показатели: размер пул-реквестов, баланс рабочей нагрузки и скорость проверки. Важно снизить время до первого отзыва настолько, насколько это возможно, без ущерба для внимания и производительности рецензентов.
2. Покрытие
Если ваша цель — улучшить качество кода и выявить ошибки, важно сравнить количество файлов с комментариями в обзоре с количеством изменённых файлов в пул-реквесте. Это будет показателем тщательности проверки. Не существует оптимального числа, но вы должны убедиться, что результат соответствует ожиданиям. Чтобы рецензенты не просто проштамповывали любые изменения, но, и чтобы не сильно придирались и не замедляли процесс.
3. Влияние
Одно только покрытие отзывами не говорит о качестве кода. Важно посмотреть, все ли эти отзывы приводят к действиям? Для этого отслеживайте процент комментариев, которые приводят к ответным комментариям или изменениям в коде. Большое количество комментариев с низким «влиянием» указывает на то, что отзывы рецензентов не воспринимаются как ценные для отправителя. Это может потребовать перестройки того, как должны проводиться проверки кода.
4. Циклы
Пулл-реквесты, перескакивающие туда-сюда между автором и рецензентом, могут замедлять процесс. Если это происходит часто, процесс рецензирования может стать узким местом и источником демотивации для инженеров, пытающихся завершить свою работу.
Средний показатель может меняться по многим причинам. Привлечение новых разработчиков может вызвать всплеск. Однако такой всплеск в опытной команде часто является признаком рассогласованности представлений:
- о том, что значит «готово»,
- какие изменения ожидаются после комментария,
- как должно быть реализовано решение.
Если количество циклов проверки для определённого отправителя велико, это может означать, что он не понимает кодовую базу или имеет дело с нечёткими требованиями.
Проверка кода — один из самых сложных процессов в команде разработчиков ПО. В каждой команде существует свой идеальный баланс тщательности и скорости, и этот баланс может даже измениться для данной команды из-за изменения приоритетов. Менеджеры должны постоянно следить за процессом код-ревью, беседовать с командой, чтобы собрать информацию, необходимую для придания контекста метрикам проверки кода и придания им значимости.
Источник: https://thenewstack.io/how-good-is-your-code-review-process/
👍7
День 1313. #TypesAndLanguages
Ваш Язык Влияет на то, Как Вы Думаете. Начало
Кажется очевидным, не так ли? Ваш язык диктует правила, и вам нужно играть по правилам. Однако последствия гораздо серьёзнее, чем вы думаете. Дело не только в том, что мы выбираем решения, которые просты в использовании на данном языке. Также мы считаем некоторые решения «плохими в целом», потому что они могут создавать некоторые проблемы на данном языке. Однако мы должны помнить, что концепции никогда не бывают хорошими или плохими. Именно то, как мы их используем, делает их таковыми.
Контейнеры внедрения зависимостей
Java-программисты часто заявляют, что DI-контейнеры — это плохо, и мы не должны их использовать. Вы можете найти сообщения в блогах, доклады на конференциях или дискуссии о том, почему мы не должны использовать DI и почему следует отказаться от Spring. В то же время Microsoft поддерживает DI-контейнер непосредственно в платформе .NET Core. Как так?
Дело не в том, что DI-контейнеры хороши или плохи. Дело в том, как мы их используем. Все методы экземпляра в Java являются виртуальными. Это делает переопределение очень простым и возможным почти всегда. Это привело к массовому использованию cglib для создания динамических прокси во время выполнения. Контейнеры DI в Java позволяют внедрять transient объекты в синглтоны — что является плохой практикой и отслеживается в .NET. То же самое касается серверов приложений — они гораздо популярнее и мощнее в мире Java, чем в .NET.
Поскольку проще использовать генерацию кода, проще делать более мощные и более опасные решения. А это приводит к проблемам: чтобы использовать мощные решения, нужно их понимать и уметь не навредить себе. А поскольку у нас не так много времени на изучение наших инструментов, мы часто вносим неправильные изменения в нашу кодовую базу. Это приводит к тонким проблемам с транзакциями, потерей данных и т.п. Java-программисты заметили это и решили не использовать эти возможности. Однако дело не в том, что «контейнеры DI плохи». Это «то, как мы используем DI-контейнеры в мире Java, слишком опасно и приводит к множеству проблем». Просто изучите свои инструменты, и вы будете в большей безопасности.
Частичные моки и виртуальные методы
То же самое происходит и в тестах. Java позволяет переопределить почти любой метод экземпляра, поэтому создание частичного мока разрешено и поддерживается по умолчанию. С другой стороны, вам нужно явно пометить свой метод виртуальным в C#, поэтому обычно вы этого не делаете. Если вы это сделаете, люди могут начать задавать вопросы в код-ревью вроде «почему он виртуальный? вы переопределяете его?». Таким образом, вы не делаете его виртуальным и не можете использовать частичные моки. Совершенно иначе, чем в Java.
Поскольку это разрешено в Java, оно используется чаще. Причина в том, что «если это разрешено по умолчанию, то это должно быть хорошо». Опять же, не стоит обобщать.
Множественное наследование
C++ допускал множественное наследование, и люди испугались проблемы алмаза. Java и C# решили полностью избежать этой проблемы, поэтому они множественное наследование запретили. Однако в то же время они заблокировали множественное наследование состояний и множественное наследование реализации. Единственной разрешённой формой было множественное наследование интерфейсов. К сожалению, проблема алмаза реально существует в языках C# и Java с самого начала.
Поэтому люди испугались наследования. В то же время такие языки, как Scala, допускают почти полное множественное наследование, и это не проблема. Даже Java и C# представили реализацию интерфейса по умолчанию, которую можно использовать для реализации миксинов и множественного наследования состояний. А что, теперь стало можно? Опять же, нельзя сказать, что множественное наследование хорошо или плохо само по себе. Проблема в том, как мы его используем.
Окончание следует…
Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/
Автор оригинала: Adam Furmanek
Ваш Язык Влияет на то, Как Вы Думаете. Начало
Кажется очевидным, не так ли? Ваш язык диктует правила, и вам нужно играть по правилам. Однако последствия гораздо серьёзнее, чем вы думаете. Дело не только в том, что мы выбираем решения, которые просты в использовании на данном языке. Также мы считаем некоторые решения «плохими в целом», потому что они могут создавать некоторые проблемы на данном языке. Однако мы должны помнить, что концепции никогда не бывают хорошими или плохими. Именно то, как мы их используем, делает их таковыми.
Контейнеры внедрения зависимостей
Java-программисты часто заявляют, что DI-контейнеры — это плохо, и мы не должны их использовать. Вы можете найти сообщения в блогах, доклады на конференциях или дискуссии о том, почему мы не должны использовать DI и почему следует отказаться от Spring. В то же время Microsoft поддерживает DI-контейнер непосредственно в платформе .NET Core. Как так?
Дело не в том, что DI-контейнеры хороши или плохи. Дело в том, как мы их используем. Все методы экземпляра в Java являются виртуальными. Это делает переопределение очень простым и возможным почти всегда. Это привело к массовому использованию cglib для создания динамических прокси во время выполнения. Контейнеры DI в Java позволяют внедрять transient объекты в синглтоны — что является плохой практикой и отслеживается в .NET. То же самое касается серверов приложений — они гораздо популярнее и мощнее в мире Java, чем в .NET.
Поскольку проще использовать генерацию кода, проще делать более мощные и более опасные решения. А это приводит к проблемам: чтобы использовать мощные решения, нужно их понимать и уметь не навредить себе. А поскольку у нас не так много времени на изучение наших инструментов, мы часто вносим неправильные изменения в нашу кодовую базу. Это приводит к тонким проблемам с транзакциями, потерей данных и т.п. Java-программисты заметили это и решили не использовать эти возможности. Однако дело не в том, что «контейнеры DI плохи». Это «то, как мы используем DI-контейнеры в мире Java, слишком опасно и приводит к множеству проблем». Просто изучите свои инструменты, и вы будете в большей безопасности.
Частичные моки и виртуальные методы
То же самое происходит и в тестах. Java позволяет переопределить почти любой метод экземпляра, поэтому создание частичного мока разрешено и поддерживается по умолчанию. С другой стороны, вам нужно явно пометить свой метод виртуальным в C#, поэтому обычно вы этого не делаете. Если вы это сделаете, люди могут начать задавать вопросы в код-ревью вроде «почему он виртуальный? вы переопределяете его?». Таким образом, вы не делаете его виртуальным и не можете использовать частичные моки. Совершенно иначе, чем в Java.
Поскольку это разрешено в Java, оно используется чаще. Причина в том, что «если это разрешено по умолчанию, то это должно быть хорошо». Опять же, не стоит обобщать.
Множественное наследование
C++ допускал множественное наследование, и люди испугались проблемы алмаза. Java и C# решили полностью избежать этой проблемы, поэтому они множественное наследование запретили. Однако в то же время они заблокировали множественное наследование состояний и множественное наследование реализации. Единственной разрешённой формой было множественное наследование интерфейсов. К сожалению, проблема алмаза реально существует в языках C# и Java с самого начала.
Поэтому люди испугались наследования. В то же время такие языки, как Scala, допускают почти полное множественное наследование, и это не проблема. Даже Java и C# представили реализацию интерфейса по умолчанию, которую можно использовать для реализации миксинов и множественного наследования состояний. А что, теперь стало можно? Опять же, нельзя сказать, что множественное наследование хорошо или плохо само по себе. Проблема в том, как мы его используем.
Окончание следует…
Источник: https://blog.adamfurmanek.pl/2022/07/23/types-and-programming-languages-part-16/
Автор оригинала: Adam Furmanek
👍7
День 1314. #TypesAndLanguages
Ваш Язык Влияет на то, Как Вы Думаете. Окончание
Начало
Наследование против композиции
Что из этого мы должны использовать? «Очевидно — композицию. Наследование — это плохо». Опять же, легко обобщать, но это не обязательно правильно.
Возможности ООП активно использовались на заре Java. Наследование было прорывом, глубокая классовая иерархия не удивляла. Как ни странно, божественные объекты также были популярны. Прошло время, и люди поняли, что помещать всё в класс длиной 8000 строк — не лучшая идея. Так что нам делать? «Запретить наследование, использовать композицию».
На самом деле дискуссия уходит гораздо глубже. Должны ли мы использовать сценарий транзакции и анемичную модель предметной области? Это хорошо? Или нам следует использовать классы с сохранением состояния и предметно-ориентированное проектирование?
Наследование не является ошибкой. Вам нужно понять концепцию и подумать, где она работает хорошо. Не запрещайте его только потому, что вы боитесь божественных классов.
Goto
Конечно, вы не можете использовать goto. Его надо запретить и убрать из языка. Теперь зайдите на GitHub и посмотрите варианты использования. Вы удивитесь.
Преждевременная оптимизация
Этим сильно злоупотребляют. Полная цитата гласит: «Мы должны забыть о неэффективности примерно в 97% случаев: преждевременная оптимизация — корень всех зол». Однако это относится к микрооптимизациям, таким как
В то же время не следует пренебрегать фактором оптимизации. Думайте об алгоритме, а не о циклах под капотом. Удалите ненужные коллекции и структуры данных, но не забивайте голову работой по выравниванию битов.
Однако очень легко снизить производительность, используя возможности языка. Отличным примером является LINQ в .NET — первое, что вы делаете для ускорения работы, — это избавляетесь от LINQ. Хотя по умолчанию он доступен.
Зелёные потоки
Зелёные потоки (если коротко, это потоки, управляемые средой выполнения, а не операционной системой) были популярны, но в какой-то момент подверглись жёсткой критике. В Microsoft написали об этом хорошую статью. C# представил асинхронность, которая позже была скопирована в другие языки (Python, JS, C++, Kotlin).
Однако Java реализовала асинхронность по-другому в своем проекте Loom. Они использовали виртуальные потоки под капотом. И тут в Microsoft внезапно решили поэкспериментировать с зелёными потоками в .NET.
Забавно, правда? Опять же, дело не в том, что концепция плоха. Дело в том, как мы это используем. Зелёные потоки также создают проблемы, особенно в отношении блокирующих операций, примитивов блокировки или interop-вызовов. Но это опять же о реализации, а не об идее.
Источник: https://blog.adamfurmanek.pl/2022/08/13/types-and-programming-languages-part-18/
Ваш Язык Влияет на то, Как Вы Думаете. Окончание
Начало
Наследование против композиции
Что из этого мы должны использовать? «Очевидно — композицию. Наследование — это плохо». Опять же, легко обобщать, но это не обязательно правильно.
Возможности ООП активно использовались на заре Java. Наследование было прорывом, глубокая классовая иерархия не удивляла. Как ни странно, божественные объекты также были популярны. Прошло время, и люди поняли, что помещать всё в класс длиной 8000 строк — не лучшая идея. Так что нам делать? «Запретить наследование, использовать композицию».
На самом деле дискуссия уходит гораздо глубже. Должны ли мы использовать сценарий транзакции и анемичную модель предметной области? Это хорошо? Или нам следует использовать классы с сохранением состояния и предметно-ориентированное проектирование?
Наследование не является ошибкой. Вам нужно понять концепцию и подумать, где она работает хорошо. Не запрещайте его только потому, что вы боитесь божественных классов.
Goto
Конечно, вы не можете использовать goto. Его надо запретить и убрать из языка. Теперь зайдите на GitHub и посмотрите варианты использования. Вы удивитесь.
Преждевременная оптимизация
Этим сильно злоупотребляют. Полная цитата гласит: «Мы должны забыть о неэффективности примерно в 97% случаев: преждевременная оптимизация — корень всех зол». Однако это относится к микрооптимизациям, таким как
i++
против ++i
. И да, такая оптимизация, вероятно, не нужна, так как наш код работает медленно из-за других вещей.В то же время не следует пренебрегать фактором оптимизации. Думайте об алгоритме, а не о циклах под капотом. Удалите ненужные коллекции и структуры данных, но не забивайте голову работой по выравниванию битов.
Однако очень легко снизить производительность, используя возможности языка. Отличным примером является LINQ в .NET — первое, что вы делаете для ускорения работы, — это избавляетесь от LINQ. Хотя по умолчанию он доступен.
Зелёные потоки
Зелёные потоки (если коротко, это потоки, управляемые средой выполнения, а не операционной системой) были популярны, но в какой-то момент подверглись жёсткой критике. В Microsoft написали об этом хорошую статью. C# представил асинхронность, которая позже была скопирована в другие языки (Python, JS, C++, Kotlin).
Однако Java реализовала асинхронность по-другому в своем проекте Loom. Они использовали виртуальные потоки под капотом. И тут в Microsoft внезапно решили поэкспериментировать с зелёными потоками в .NET.
Забавно, правда? Опять же, дело не в том, что концепция плоха. Дело в том, как мы это используем. Зелёные потоки также создают проблемы, особенно в отношении блокирующих операций, примитивов блокировки или interop-вызовов. Но это опять же о реализации, а не об идее.
Источник: https://blog.adamfurmanek.pl/2022/08/13/types-and-programming-languages-part-18/
👍6
День 1315. #ЧтоНовенького
Bulk-Операции в Entity Framework 7
В EF наконец завезут Bulk-Update и Bulk-Delete. Добавленные методы улучшают производительность. Теперь мы можем делать обновления и удаления с помощью всего одной операции, результатом которой будет одна команда SQL.
Рассмотрим использование этих операций. Допустим, у нас есть класс людей:
Чтобы массово удалить набор сущностей, отфильтруем их с помощью
ExecuteUpdate
Для обновления сущностей нам нужно использовать новый метод SetProperty. Первый аргумент SetProperty выбирает свойство, которое необходимо обновить с помощью лямбда-выражения, а второй аргумент — это новое значение этого свойства также с помощью лямбда-выражения, в котором мы также можем получать доступ к свойству. Например, здесь мы добавим префикс "New" к имени первой тысячи людей:
Bulk-Операции в Entity Framework 7
В EF наконец завезут Bulk-Update и Bulk-Delete. Добавленные методы улучшают производительность. Теперь мы можем делать обновления и удаления с помощью всего одной операции, результатом которой будет одна команда SQL.
Рассмотрим использование этих операций. Допустим, у нас есть класс людей:
public class PersonExecuteDelete
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Чтобы массово удалить набор сущностей, отфильтруем их с помощью
Where
(как раньше), а затем вызовем ExecuteDelete
. Помимо прочего, метод возвращает количество удалённых записей:var personsDeleted = context.PersonsВот какой код SQL он сгенерирует:
.Where(p => p.Name.Contains("L"))
.ExecuteDelete();
DELETE FROM [p]Как видите, он просто генерирует одну инструкцию SQL для удаления сущностей, соответствующих условию.
FROM [Persons] AS [p]
WHERE [p].[Name] LIKE N'%L%'
ExecuteUpdate
Для обновления сущностей нам нужно использовать новый метод SetProperty. Первый аргумент SetProperty выбирает свойство, которое необходимо обновить с помощью лямбда-выражения, а второй аргумент — это новое значение этого свойства также с помощью лямбда-выражения, в котором мы также можем получать доступ к свойству. Например, здесь мы добавим префикс "New" к имени первой тысячи людей:
var personsUpdated =В результате возвращается количество обновлённых записей, а SQL код получается таким:
context.Persons
.Where(p => p.PersonId <= 1_000)
.ExecuteUpdate(
p => p.SetProperty(
x => x.Name,
x => "New" + x.Name)
);
}
UPDATE [p]Чтобы обновить несколько свойств за раз, просто вызовите методы
SET [p].[Name] = N'New' + [p].[Name]
FROM [Persons] AS [p]
WHERE [p].[Id] <= CAST(1000 AS bigint)
SetProperty
в цепочке:….ExecuteUpdate(p =>Источник: https://timdeschryver.dev/blog/new-in-entity-framework-7-bulk-operations-with-executedelete-and-executeupdate
p.SetProperty(x => x.Name, x => "…")
.SetProperty(x => x.Age, x => 42)
);
}
👍21
День 1316. #ЗаметкиНаПолях
Неочевидные Различия в Regex
1. \d или [0-9]
В документации .NET про Regex,
- по умолчанию, без опции RegexOptions.ECMAScript,
- с опцией RegexOptions.ECMAScript
Категория цифр в Unicode содержит цифры 0, 1, 2, … но также цифры из других языков, вроде ٣, ٧, ൩ или ໓. Полный список состоит из 610 символов!
Поэтому
Добавление опции решает проблему:
2. [a-zA-Z] или [a-z] с IgnoreCase
Рассмотрим два регулярных выражения:
- «A» является ToLower() представлением «B»,
- оба символа являются представлением в нижнем регистре для одного и того же символа.
В этом случае
Источник: https://www.meziantou.net/regex-with-ignorecase-option-may-match-more-characters-than-expected.htm
Неочевидные Различия в Regex
1. \d или [0-9]
В документации .NET про Regex,
\d
означает любую цифру. Что означает термин «цифра», зависит от опций выражения:- по умолчанию, без опции RegexOptions.ECMAScript,
\d
означает \p{Nd}
, т.е. любой символ из категории «цифр» в Unicode;- с опцией RegexOptions.ECMAScript
\d
означает [0-9]
.Категория цифр в Unicode содержит цифры 0, 1, 2, … но также цифры из других языков, вроде ٣, ٧, ൩ или ໓. Полный список состоит из 610 символов!
Поэтому
Regex.IsMatch("०१२३४५६७८९", "[0-9]{10}");вернёт
False
, тогда какRegex.IsMatch("०१२३४५६७८९", "\\d{10}");вернёт
True
.Добавление опции решает проблему:
Regex.IsMatch("०१२३४५६७८९", "\\d{10}", RegexOptions.ECMAScript);вернёт
False
.2. [a-zA-Z] или [a-z] с IgnoreCase
Рассмотрим два регулярных выражения:
var regex1 = new Regex("^[a-zA-Z]+$");В большинстве случаев они работают одинаково, так, как мы и предполагаем:
var regex2 = new Regex("^[a-z]+$",
RegexOptions.IgnoreCase |
RegexOptions.CultureInvariant);
regex1.IsMatch("Test"); // TrueОднако, есть специальный символ K (U+212A), обозначающий температуру по Кельвину, и здесь всё интереснее:
regex2.IsMatch("Test"); // True
regex1.IsMatch("K"); // FalseКогда в регулярном выражении указан параметр
regex2.IsMatch("K"); // True
RegexOptions.IgnoreCase
, сравнение между входными данными и шаблоном будет выполняться без учёта регистра. Чтобы поддерживать это, Regex необходимо определить, какие отображения регистра будут использоваться для сравнений. Отображение регистра существует всякий раз, когда у вас есть два символа «A» и «B», где либо:- «A» является ToLower() представлением «B»,
- оба символа являются представлением в нижнем регистре для одного и того же символа.
В этом случае
char.ToLowerInvariant('K')
- это k (строчная латинская буква K). Поэтому второе выражение возвращает True
для знака Кельвина, однако он не входит в множество [a-zA-Z]
, поэтому первое выражение возвращает False
.Источник: https://www.meziantou.net/regex-with-ignorecase-option-may-match-more-characters-than-expected.htm
👍21
День 1317. #ЗаметкиНаПолях #ЧтоНовенького
Исправляем Предупреждение CS891
Если вы были одним из первых пользователей .NET 7, возможно, вы столкнулись со следующей ошибкой при компиляции существующего проекта .NET 6:
Warning CS8981: The type name only contains lower-cased ascii characters. Such names may become reserved for the language. (Имя типа содержит символы только в нижнем регистре. Такие имена могут быть зарезервированы под ключевые слова языка.)
Хотя предупреждение в принципе довольно подробное, в нём отсутствует пояснение, почему оно отображается. Особенно когда в .NET 6 код компилировался успешно. Рассмотрим на очень простой пример того, почему это предупреждение было добавлено.
Представим, что мы вернулись на много лет назад и пишем код C# в .NET 2.0. У нас есть код, который выглядит так:
Тут мы решаем обновиться до C# 5, а вместе с ним к нам пришли ключевые слова async/await. Теперь у нас проблемы, потому наш класс имеет конфликт имён.
Microsoft активно выпускает ежегодные выпуски .NET/C#, и само собой разумеется, что они могут добавить дополнительные зарезервированные ключевые слова в язык. Но до этого времени Microsoft, очевидно, не может зарезервировать все возможные комбинации ключевых слов, которые могут понадобиться в будущем.
Поэтому в Microsoft явно указали на тот факт, что все зарезервированные ключевые слова пишутся полностью строчными буквами. И, если вы следуете соглашениям об именовании, которые советуют не называть всё исключительно строчными буквами, то вы можете быть уверены, что в будущем у вас не будет конфликтов.
С другой стороны, это только предупреждение, вы можете его игнорировать, но на свой страх и риск.
Источник: https://dotnetcoretutorials.com/2022/08/10/fixing-cs891-the-type-name-only-contains-lower-cased-ascii-characters/
Исправляем Предупреждение CS891
Если вы были одним из первых пользователей .NET 7, возможно, вы столкнулись со следующей ошибкой при компиляции существующего проекта .NET 6:
Warning CS8981: The type name only contains lower-cased ascii characters. Such names may become reserved for the language. (Имя типа содержит символы только в нижнем регистре. Такие имена могут быть зарезервированы под ключевые слова языка.)
Хотя предупреждение в принципе довольно подробное, в нём отсутствует пояснение, почему оно отображается. Особенно когда в .NET 6 код компилировался успешно. Рассмотрим на очень простой пример того, почему это предупреждение было добавлено.
Представим, что мы вернулись на много лет назад и пишем код C# в .NET 2.0. У нас есть код, который выглядит так:
class async {В то время async/await не существовало в .NET, и вы могли бы создать класс, названный с использованием любого из этих ключевых слов, даже если они не соответствовали традиционным стандартам именования PascalCase.
}
Тут мы решаем обновиться до C# 5, а вместе с ним к нам пришли ключевые слова async/await. Теперь у нас проблемы, потому наш класс имеет конфликт имён.
Microsoft активно выпускает ежегодные выпуски .NET/C#, и само собой разумеется, что они могут добавить дополнительные зарезервированные ключевые слова в язык. Но до этого времени Microsoft, очевидно, не может зарезервировать все возможные комбинации ключевых слов, которые могут понадобиться в будущем.
Поэтому в Microsoft явно указали на тот факт, что все зарезервированные ключевые слова пишутся полностью строчными буквами. И, если вы следуете соглашениям об именовании, которые советуют не называть всё исключительно строчными буквами, то вы можете быть уверены, что в будущем у вас не будет конфликтов.
С другой стороны, это только предупреждение, вы можете его игнорировать, но на свой страх и риск.
Источник: https://dotnetcoretutorials.com/2022/08/10/fixing-cs891-the-type-name-only-contains-lower-cased-ascii-characters/
👍14
День 1318. #DevOps
6 Принципов Разработки Архитектуры ПО
В последнее время термин «непрерывный» (continuous) очень часто используется в речи поставщиков ПО и экспертов как программная архитектура, которую мы все должны и хотим иметь. Проблема в том, что многие считают, что «непрерывный» означает быструю доставку. Однако проектирование непрерывной программной архитектуры требует постоянной обратной связи от всех участников процесса: архитекторов, дизайнеров, разработчиков, операторов — и постоянного улучшения. Разработка архитектуры ПО больше не может быть разовым процессом.
Об этом на недавней конференции GOTO 2022 поговорили Пьер Пюрер, соавтор книги «Continuous Architecture in Practice», и Курт Биттнер, глава отдела корпоративных решений в Scrum.org.
«Проектирование и поддержка хорошо функционирующей непрерывной программной архитектуры требует, прежде всего, терпения,» - считает Пюрер. - «Cпешить с технологическим решением, прежде чем задать правильные вопросы, означает упускать возможности или функции, которые могут быть жизненно важными для бизнеса. Я видел команды, которые начинают с конца, и они знают, что хотят внедрить какую-то технологию. Кто-то сказал им: «Нам нужно быть в облаке Amazon». Ответом будет облако Amazon, а вы даже не задаёте этот вопрос.»
В течение многих лет проектирование архитектуры ПО означало проектирование чего-либо на начальном этапе, а затем переход к этапу развёртывания. Согласно традиционному представлению об архитектуре, «мы не пишем ни строчки кода, пока вся архитектура не будет собрана», — сказал Пюрер.
«Проблема с таким подходом, конечно, в том, что очень сложно знать всё сразу. Проектирование архитектуры, когда более половины ваших требований неверны, не даст вам хороших результатов. Трудно предсказать, как система будет эволюционировать."
Появились более гибкие подходы, что сделало процесс более итеративным. Тем не менее, это предполагает, что «вы пишете код, и архитектура каким-то образом появляется, как кит из воды». Но это приводит к необходимости «большого рефакторинга и перенастройки».
Гибкая разработка — это шаг в правильном направлении, но для непрерывной архитектуры проектировщики и разработчики ПО должны сделать ещё один шаг.
Им нужно задавать трудные вопросы: что нужно бизнесу? Что лучше сработает для пользователей или клиентов? Какие части бизнеса должны быть вовлечены в процесс проектирования?
По словам Пюрера, в основе успешной непрерывной архитектуры лежат шесть принципов. «Ни один из принципов не является новым или революционным, но вместе они имеют большой смысл».
Вот эти принципы:
1. Создавайте архитектуру продукта, а не проекта. Звучит очевидно, но многие об этом забывают.
2. Сосредоточьтесь на атрибутах качества, а не на обширности функционала. Да, функциональные требования важны, но, если качество не соответствует, у вас не получится эффективного продукта.
3. Откладывайте решения до тех пор, пока не будете уверены, что должны принять решение. У каждого решения есть цена. А если оно окажется неверным, будет и цена отката этого решения. Не принимайте решения слишком рано, пытаясь угадать, старайтесь основывать решение на фактах.
4. Планируйте изменения, потому что всё изменится — так что подумайте о «минималистичном дизайне». Хотя это не обязательно означает микросервисы.
5. Помните, тестирование сборки системы важно, но тестирование развёртывания системы едва ли не важнее.
6. Организуйте команду из людей, которые занимаются всеми аспектами системы. Да, может быть разделение на фронт и бэк, но все специалисты должны чётко представлять, какой продукт должен получиться.
«Люди думают об архитектуре как о чертежах, красивых диаграммах и т. д.», — говорит Пюрер. - «Да, у вас должны быть эти вещи, с помощью которых вы будете общаться, как часть архитектуры. Поскольку вы постоянно принимаете решения, вы будете учиться на своих ошибках, постоянно возвращаться и пересматривать свои решения».
Источник: https://www.zdnet.com/article/agile-alertness-6-principles-to-help-your-software-design-process-succeed/
6 Принципов Разработки Архитектуры ПО
В последнее время термин «непрерывный» (continuous) очень часто используется в речи поставщиков ПО и экспертов как программная архитектура, которую мы все должны и хотим иметь. Проблема в том, что многие считают, что «непрерывный» означает быструю доставку. Однако проектирование непрерывной программной архитектуры требует постоянной обратной связи от всех участников процесса: архитекторов, дизайнеров, разработчиков, операторов — и постоянного улучшения. Разработка архитектуры ПО больше не может быть разовым процессом.
Об этом на недавней конференции GOTO 2022 поговорили Пьер Пюрер, соавтор книги «Continuous Architecture in Practice», и Курт Биттнер, глава отдела корпоративных решений в Scrum.org.
«Проектирование и поддержка хорошо функционирующей непрерывной программной архитектуры требует, прежде всего, терпения,» - считает Пюрер. - «Cпешить с технологическим решением, прежде чем задать правильные вопросы, означает упускать возможности или функции, которые могут быть жизненно важными для бизнеса. Я видел команды, которые начинают с конца, и они знают, что хотят внедрить какую-то технологию. Кто-то сказал им: «Нам нужно быть в облаке Amazon». Ответом будет облако Amazon, а вы даже не задаёте этот вопрос.»
В течение многих лет проектирование архитектуры ПО означало проектирование чего-либо на начальном этапе, а затем переход к этапу развёртывания. Согласно традиционному представлению об архитектуре, «мы не пишем ни строчки кода, пока вся архитектура не будет собрана», — сказал Пюрер.
«Проблема с таким подходом, конечно, в том, что очень сложно знать всё сразу. Проектирование архитектуры, когда более половины ваших требований неверны, не даст вам хороших результатов. Трудно предсказать, как система будет эволюционировать."
Появились более гибкие подходы, что сделало процесс более итеративным. Тем не менее, это предполагает, что «вы пишете код, и архитектура каким-то образом появляется, как кит из воды». Но это приводит к необходимости «большого рефакторинга и перенастройки».
Гибкая разработка — это шаг в правильном направлении, но для непрерывной архитектуры проектировщики и разработчики ПО должны сделать ещё один шаг.
Им нужно задавать трудные вопросы: что нужно бизнесу? Что лучше сработает для пользователей или клиентов? Какие части бизнеса должны быть вовлечены в процесс проектирования?
По словам Пюрера, в основе успешной непрерывной архитектуры лежат шесть принципов. «Ни один из принципов не является новым или революционным, но вместе они имеют большой смысл».
Вот эти принципы:
1. Создавайте архитектуру продукта, а не проекта. Звучит очевидно, но многие об этом забывают.
2. Сосредоточьтесь на атрибутах качества, а не на обширности функционала. Да, функциональные требования важны, но, если качество не соответствует, у вас не получится эффективного продукта.
3. Откладывайте решения до тех пор, пока не будете уверены, что должны принять решение. У каждого решения есть цена. А если оно окажется неверным, будет и цена отката этого решения. Не принимайте решения слишком рано, пытаясь угадать, старайтесь основывать решение на фактах.
4. Планируйте изменения, потому что всё изменится — так что подумайте о «минималистичном дизайне». Хотя это не обязательно означает микросервисы.
5. Помните, тестирование сборки системы важно, но тестирование развёртывания системы едва ли не важнее.
6. Организуйте команду из людей, которые занимаются всеми аспектами системы. Да, может быть разделение на фронт и бэк, но все специалисты должны чётко представлять, какой продукт должен получиться.
«Люди думают об архитектуре как о чертежах, красивых диаграммах и т. д.», — говорит Пюрер. - «Да, у вас должны быть эти вещи, с помощью которых вы будете общаться, как часть архитектуры. Поскольку вы постоянно принимаете решения, вы будете учиться на своих ошибках, постоянно возвращаться и пересматривать свои решения».
Источник: https://www.zdnet.com/article/agile-alertness-6-principles-to-help-your-software-design-process-succeed/
👍10
День 1320. #ЗаметкиНаПолях #AsyncTips
Асинхронные интерфейсы и наследование
Задача: В интерфейсе или базовом классе имеется метод, который требуется сделать асинхронным.
Решение
Ключом к пониманию этой задачи и её решения станет понимание того, что async относится к подробностям реализации. Ключевое слово async может применяться только к методам с реализациями. Невозможно применить его к абстрактным методам или методам интерфейсов (если они не имеют реализации по умолчанию). Тем не менее вы можете определить метод с такой же сигнатурой, как у async-метода, но без ключевого слова async.
Ожидание допускают типы, а не методы. Вы можете использовать await с объектом Task, возвращённым методом, независимо от того, был метод реализован с ключевым словом async или нет. Таким образом, интерфейс или абстрактный метод может просто вернуть Task (или Task<T>), и это значение может ожидаться.
Следующий пример определяет интерфейс с асинхронным методом (без ключевого слова async), реализацию этого интерфейса (с async), и независимый метод, который потребляет метод этого интерфейса (посредством await):
Асинхронная сигнатура метода (возврат Task или Task<T>) означает лишь то, что реализация может быть асинхронной. Фактическая реализация может быть синхронной, если нет реальной асинхронной работы, которую нужно было бы выполнять. Например, тестовая заглушка может реализовать тот же интерфейс (без async), используя, например,
См. также: Возвращение завершённых задач
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.
Асинхронные интерфейсы и наследование
Задача: В интерфейсе или базовом классе имеется метод, который требуется сделать асинхронным.
Решение
Ключом к пониманию этой задачи и её решения станет понимание того, что async относится к подробностям реализации. Ключевое слово async может применяться только к методам с реализациями. Невозможно применить его к абстрактным методам или методам интерфейсов (если они не имеют реализации по умолчанию). Тем не менее вы можете определить метод с такой же сигнатурой, как у async-метода, но без ключевого слова async.
Ожидание допускают типы, а не методы. Вы можете использовать await с объектом Task, возвращённым методом, независимо от того, был метод реализован с ключевым словом async или нет. Таким образом, интерфейс или абстрактный метод может просто вернуть Task (или Task<T>), и это значение может ожидаться.
Следующий пример определяет интерфейс с асинхронным методом (без ключевого слова async), реализацию этого интерфейса (с async), и независимый метод, который потребляет метод этого интерфейса (посредством await):
interface ICountBytes…
{
Task<int> CountBytesAsync(
HttpClient hc, string url);
}
class Counter : ICountBytes
{
public async Task<int>
CountBytesAsync(HttpClient hc, string url)
{
var b = await hc.GetByteArrayAsync(url);
return b.Length;
}
}
async Task UseCounter(Этот паттерн работает и с абстрактными методами базовых классов.
HttpClient hc,
ICountBytes svc)
{
var res = await svc.CountBytesAsync(
hc,
"https://www.google.com");
Console.WriteLine(res);
}
Асинхронная сигнатура метода (возврат Task или Task<T>) означает лишь то, что реализация может быть асинхронной. Фактическая реализация может быть синхронной, если нет реальной асинхронной работы, которую нужно было бы выполнять. Например, тестовая заглушка может реализовать тот же интерфейс (без async), используя, например,
FromResult
:class CounterStub : ICountBytesАсинхронные методы интерфейсов и базовых классов встречаются всё чаще. Работать с ними не так уж сложно, если помнить, что ожидание должно применяться к возвращаемому типу (а не к методу), а определение асинхронного метода может быть реализовано как асинхронно, так и синхронно.
{
public Task<int> CountBytesAsync(
HttpClient hc, string url)
{
return Task.FromResult(13);
}
}
См. также: Возвращение завершённых задач
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 11.
👍7