День триста восемьдесят шестой. #MoreEffectiveCSharp
2. По возможности делайте значимые типы неизменяемыми
Неизменяемые типы просты: после того, как они созданы, они являются постоянными. Если вы проверяете параметры в конструкторе, вы знаете, что объект находится в согласованном состоянии с момента создания. Вы не можете изменить внутреннее состояние объекта и нарушить согласованность. Тем самым вы избавляете себя от множества необходимых проверок. Кроме того, неизменяемые типы потокобезопасны, могут быть безопасно экспортированы и лучше работают в коллекциях на основе хешей.
На практике очень трудно сделать каждый тип неизменяемым. Вот почему эта рекомендация предназначена для атомарных неизменяемых значимых типов. Выделите среди ваших типов структуры, которые естественным образом образуют единую сущность. Например, Адрес - это единая сущность, состоящая из нескольких связанных полей. Изменение одного поля скорее всего означает изменения в других полях. А Клиент не является атомарным типом. Он, скорее всего, будет содержать много независимой друг от друга информации: адрес, имя и один или несколько телефонных номеров. Любая из этих частей информации может измениться независимо от других.
В атомарных типах скорее всего изменится всё содержимое, а изменение одного из полей - исключение.
Внутренние изменения состояния означают, что возможно нарушить инварианты объекта, по крайней мере, временно. Например, при изменении города скорее всего изменится индекс или область. Изменение их двумя последовательными присваиваниями выглядит безопасно, но предположим, что этот фрагмент является частью многопоточной программы. Любое переключение контекста после изменения города и до изменения индекса может привести к тому, что другой поток увидит несогласованное представление данных.
У вас однопоточная программа? Тогда представьте, что после изменения города возникло исключение. Внесена лишь часть изменений, и объект остался в недопустимом состоянии. В итоге как для потоковой безопасности, так и для защиты от ошибок, пришлось бы добавлять массивный код проверки целостности объекта, который бы только увеличивался по мере эволюции приложения.
Чтобы создать неизменяемый тип, помимо запрета на изменение состояния в интерфейсе типа, необходимо убедиться, что в нем нет дыр, которые позволили бы клиентам изменять его внутреннее состояние. Структуры не поддерживают наследования, поэтому можно не защищаться от изменяемых полей в производных типах. Но нужно следить за любыми полями ссылочного типам в неизменяемом типе. Например, массив – ссылочный тип. Если массив разместить в поле
Чтобы исключить эту возможность, нужно делать защищённую копию массива, либо можно использовать класс
1. Определить разумный ограниченный набор конструкторов. Это часто является самым простым подходом.
2. Создать фабричные методы для инициализации. Фабрики облегчают создание часто используемых значений. Например, тип Color следует этой стратегии для инициализации системных цветов. Статические методы
3. Создать изменяемый вспомогательный класс для случаев, когда необходимы многоэтапные операции для полного создания неизменяемого типа. Примером такого вспомогательного класса является
Неизменяемые типы проще как при написании кода, так и при его обслуживании. Не спешите слепо лепить аксессоры get и set для каждого свойства вашего типа. Первоначальным выбором для типов, хранящих данные, должны быть неизменяемые, атомарные значимые типы. Затем вы легко сможете построить более сложные структуры из этих объектов.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 3.
2. По возможности делайте значимые типы неизменяемыми
Неизменяемые типы просты: после того, как они созданы, они являются постоянными. Если вы проверяете параметры в конструкторе, вы знаете, что объект находится в согласованном состоянии с момента создания. Вы не можете изменить внутреннее состояние объекта и нарушить согласованность. Тем самым вы избавляете себя от множества необходимых проверок. Кроме того, неизменяемые типы потокобезопасны, могут быть безопасно экспортированы и лучше работают в коллекциях на основе хешей.
На практике очень трудно сделать каждый тип неизменяемым. Вот почему эта рекомендация предназначена для атомарных неизменяемых значимых типов. Выделите среди ваших типов структуры, которые естественным образом образуют единую сущность. Например, Адрес - это единая сущность, состоящая из нескольких связанных полей. Изменение одного поля скорее всего означает изменения в других полях. А Клиент не является атомарным типом. Он, скорее всего, будет содержать много независимой друг от друга информации: адрес, имя и один или несколько телефонных номеров. Любая из этих частей информации может измениться независимо от других.
В атомарных типах скорее всего изменится всё содержимое, а изменение одного из полей - исключение.
Внутренние изменения состояния означают, что возможно нарушить инварианты объекта, по крайней мере, временно. Например, при изменении города скорее всего изменится индекс или область. Изменение их двумя последовательными присваиваниями выглядит безопасно, но предположим, что этот фрагмент является частью многопоточной программы. Любое переключение контекста после изменения города и до изменения индекса может привести к тому, что другой поток увидит несогласованное представление данных.
У вас однопоточная программа? Тогда представьте, что после изменения города возникло исключение. Внесена лишь часть изменений, и объект остался в недопустимом состоянии. В итоге как для потоковой безопасности, так и для защиты от ошибок, пришлось бы добавлять массивный код проверки целостности объекта, который бы только увеличивался по мере эволюции приложения.
Чтобы создать неизменяемый тип, помимо запрета на изменение состояния в интерфейсе типа, необходимо убедиться, что в нем нет дыр, которые позволили бы клиентам изменять его внутреннее состояние. Структуры не поддерживают наследования, поэтому можно не защищаться от изменяемых полей в производных типах. Но нужно следить за любыми полями ссылочного типам в неизменяемом типе. Например, массив – ссылочный тип. Если массив разместить в поле
readonly
, то само поле (ссылка на массив) будет неизменяемо, но отдельные элементы массива всё равно можно изменить.Чтобы исключить эту возможность, нужно делать защищённую копию массива, либо можно использовать класс
ImmutableArray
из пространства имен System.Collections.Immutable.
Сложность типа определяет, какую из трех стратегий использовать для инициализации неизменяемого типа:1. Определить разумный ограниченный набор конструкторов. Это часто является самым простым подходом.
2. Создать фабричные методы для инициализации. Фабрики облегчают создание часто используемых значений. Например, тип Color следует этой стратегии для инициализации системных цветов. Статические методы
Color.FromKnownColor()
и Color.FromName()
создают объект типа из значения предопределённого системного цвета.3. Создать изменяемый вспомогательный класс для случаев, когда необходимы многоэтапные операции для полного создания неизменяемого типа. Примером такого вспомогательного класса является
System.Text.StringBuilder
для создания строк.Неизменяемые типы проще как при написании кода, так и при его обслуживании. Не спешите слепо лепить аксессоры get и set для каждого свойства вашего типа. Первоначальным выбором для типов, хранящих данные, должны быть неизменяемые, атомарные значимые типы. Затем вы легко сможете построить более сложные структуры из этих объектов.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 3.
День триста восемьдесят седьмой. #ЧтоНовенького
Visual Studio Online
Всё постепенно уходит в онлайн. Вот и наша любимая студия "улетела" в облако. Visual Studio Online позволяет вам заниматься разработкой из любой точки мира и с любого компьютера через браузер. На самом деле (надеюсь, что пока) это Visual Studio Code. Вы можете подключиться к git репозиторию, отредактировать код и даже запускать и отлаживать его с точками останова и вот этим всем. В этом видео серии Visual Studio Toolbox рассказывается более подробно https://youtu.be/lV3P2fYxNzc
Теперь о минусах. Предоставляется сервис только внутри аккаунта Azure, который небесплатный (бесплатная годовой триал на данный момент недоступен для России).
Visual Studio Online
Всё постепенно уходит в онлайн. Вот и наша любимая студия "улетела" в облако. Visual Studio Online позволяет вам заниматься разработкой из любой точки мира и с любого компьютера через браузер. На самом деле (надеюсь, что пока) это Visual Studio Code. Вы можете подключиться к git репозиторию, отредактировать код и даже запускать и отлаживать его с точками останова и вот этим всем. В этом видео серии Visual Studio Toolbox рассказывается более подробно https://youtu.be/lV3P2fYxNzc
Теперь о минусах. Предоставляется сервис только внутри аккаунта Azure, который небесплатный (бесплатная годовой триал на данный момент недоступен для России).
YouTube
Visual Studio Online
In this episode, Robert is joined by Burke Holland, who introduces us to Visual Studio Online, which provides a cloud-based development environment you can access from anywhere. Burke shows how easy it is to spin up a new environment, point it at a repo and…
День триста восемьдесят восьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
27. Не просто учите язык, поймите его культуру
В вузе мне нужно было выучить иностранный язык. В то время я думал, что достаточно будет хорошо владеть английским, поэтому я решил поспать три года на уроках французского. Через несколько лет я отправился в Тунис на каникулы. Арабский язык там является официальным языком, но как в бывшей французской колонии, французский также широко используется. На английском говорят только в туристических районах. Из-за незнания языка я проводил много времени у бассейна, читая «Поминки по Финнегану» Джеймса Джойса – шедевр игры слов и форм. Его жонглирование фразами из более чем сорока языков оказалось удивительным, хотя и изнуряющим чтением. Понимание того, как переплетённые между собой иностранные слова и фразы дали автору новые способы выражения мыслей, — вот что я извлёк для своей карьеры программиста.
В своей оригинальной книге «Программист-прагматик» Энди Хант и Дейв Томас побуждают нас каждый год изучать новый язык программирования. Я пытался следовать их советам, и на протяжении многих лет у меня был опыт программирования на многих языках. Самый важный вывод, который я сделал из моих приключений полиглота, заключается в том, что для изучения языка нужно больше, чем просто изучение синтаксиса: нужно понять его культуру.
Вы можете писать на Фортране, используя любой язык, но, чтобы по-настоящему выучить язык, вы должны вникнуть в его суть. Не оправдывайтесь, если ваш код на C# является длинным методом Main с несколькими вспомогательными методами. Узнайте, почему имеет смысл использовать классы. Не стесняйтесь, если вам трудно понять лямбда-выражения, заставьте себя использовать их. Когда вы освоите новые языки, вы удивитесь тому, как начнёте по-новому использовать языки, которые вы уже знаете.
Я научился эффективно использовать делегаты в C# из программирования на Ruby. Раскрытие полного потенциала дженериков .NET дало мне идею о том, как я могу сделать дженерики в Java более полезными, а LINQ помог мне легко изучить Scala.
Вы также получите лучшее понимание шаблонов проектирования, переключаясь между различными языками. Программисты на C обнаруживают, что C# и Java модифицировали шаблон итератора. В Ruby и других динамических языках вы всё ещё можете использовать посетителя, но ваша реализация не будет похожа на пример из книги «Банды четырех».
Некоторые могут сказать, что «Поминки по Финнегану» невозможно читать, а другие аплодируют его стилистической красоте. Чтобы сделать книгу менее страшной, доступны её переводы на один язык. По иронии судьбы первый перевод был на французский.
Код во многом похож. Если вы пишете код Wakes (так называют язык, на котором написана «Поминки по Финнегану»), используя немного из Python, немного Java и капельку Erlang, ваши проекты превратятся в хаос. Если вы вместо этого исследуете новые языки, чтобы расширить свой кругозор и получить свежие идеи о том, как вы можете решать проблемы различными способами, вы обнаружите, что код, который вы пишете на своём старом добром языке, становится более красивым с каждым новым изученным вами языком.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Anders Noras
97 Вещей, Которые Должен Знать Каждый Программист
27. Не просто учите язык, поймите его культуру
В вузе мне нужно было выучить иностранный язык. В то время я думал, что достаточно будет хорошо владеть английским, поэтому я решил поспать три года на уроках французского. Через несколько лет я отправился в Тунис на каникулы. Арабский язык там является официальным языком, но как в бывшей французской колонии, французский также широко используется. На английском говорят только в туристических районах. Из-за незнания языка я проводил много времени у бассейна, читая «Поминки по Финнегану» Джеймса Джойса – шедевр игры слов и форм. Его жонглирование фразами из более чем сорока языков оказалось удивительным, хотя и изнуряющим чтением. Понимание того, как переплетённые между собой иностранные слова и фразы дали автору новые способы выражения мыслей, — вот что я извлёк для своей карьеры программиста.
В своей оригинальной книге «Программист-прагматик» Энди Хант и Дейв Томас побуждают нас каждый год изучать новый язык программирования. Я пытался следовать их советам, и на протяжении многих лет у меня был опыт программирования на многих языках. Самый важный вывод, который я сделал из моих приключений полиглота, заключается в том, что для изучения языка нужно больше, чем просто изучение синтаксиса: нужно понять его культуру.
Вы можете писать на Фортране, используя любой язык, но, чтобы по-настоящему выучить язык, вы должны вникнуть в его суть. Не оправдывайтесь, если ваш код на C# является длинным методом Main с несколькими вспомогательными методами. Узнайте, почему имеет смысл использовать классы. Не стесняйтесь, если вам трудно понять лямбда-выражения, заставьте себя использовать их. Когда вы освоите новые языки, вы удивитесь тому, как начнёте по-новому использовать языки, которые вы уже знаете.
Я научился эффективно использовать делегаты в C# из программирования на Ruby. Раскрытие полного потенциала дженериков .NET дало мне идею о том, как я могу сделать дженерики в Java более полезными, а LINQ помог мне легко изучить Scala.
Вы также получите лучшее понимание шаблонов проектирования, переключаясь между различными языками. Программисты на C обнаруживают, что C# и Java модифицировали шаблон итератора. В Ruby и других динамических языках вы всё ещё можете использовать посетителя, но ваша реализация не будет похожа на пример из книги «Банды четырех».
Некоторые могут сказать, что «Поминки по Финнегану» невозможно читать, а другие аплодируют его стилистической красоте. Чтобы сделать книгу менее страшной, доступны её переводы на один язык. По иронии судьбы первый перевод был на французский.
Код во многом похож. Если вы пишете код Wakes (так называют язык, на котором написана «Поминки по Финнегану»), используя немного из Python, немного Java и капельку Erlang, ваши проекты превратятся в хаос. Если вы вместо этого исследуете новые языки, чтобы расширить свой кругозор и получить свежие идеи о том, как вы можете решать проблемы различными способами, вы обнаружите, что код, который вы пишете на своём старом добром языке, становится более красивым с каждым новым изученным вами языком.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Anders Noras
День триста восемьдесят девятый. #DesignPatterns
Паттерны проектирования
13. Паттерн «Строитель» (Builder)
Иногда процесс создания является довольно сложным, состоит из нескольких этапов. Создаваемому объекту нужно передать множество аргументов, часть из которых нужны одним клиентам, но не нужны другим. Фабричный метод с десятью аргументами, девять из которых будут регулярно повторяться, нельзя назвать удачным решением. В этом случае поможет другой порождающий паттерн — «Строитель».
Назначение: строитель отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.
Причины использования:
Паттерн «Строитель» идеально подходит для ситуаций, когда процесс создания является сложным и состоит из нескольких этапов, при этом одним клиентам нужно устанавливать одни параметры создаваемого объекта, а другим — другие. Строитель может устанавливать разумные значения по умолчанию, позволяя клиентам сосредоточиться лишь на важных для них параметрах.
Использование паттерна «Строитель» позволяет более четко разграничить ответственность между создателем и потребителем объектов, а также делает процесс создания более удобным. Это особенно полезно, если продукт физически или логически является неизменяемым (immutable).
Классическая диаграмма паттерна «Строитель» приведена в верхней части рисунка ниже:
-
-
-
Обратите внимание на два момента: наличие наследования и то, что о классе
- Кто потребляет созданный продукт?
- Как конкретный строитель узнает об этом потребителе?
- Всегда ли процесс формирования и потребления продуктов должен быть настолько разделён, что продукт конструируется классом
На практике обычно используется более простая разновидность паттерна «Строитель», без наследования и с более явной моделью взаимодействия между участниками (см. в нижней части рисунка). Участники в этом случае те же самые, но ответственность немного меняется:
-
-
Особенности реализации в .NET
1. Использование текучего интерфейса.
Текучий интерфейс предназначен для повышения читабельности кода. Каждый метод возвращает объект, над которым выполняется текущая операция, что позволяет связывать методы в цепочку:
2. Методы расширения
Методы расширения позволяют создать видимость того, что мы добавляем операции в существующие типы. В некоторых случаях можно создать набор методов расширения, которые будут играть роль строителя для существующих типов.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 11.
Паттерны проектирования
13. Паттерн «Строитель» (Builder)
Иногда процесс создания является довольно сложным, состоит из нескольких этапов. Создаваемому объекту нужно передать множество аргументов, часть из которых нужны одним клиентам, но не нужны другим. Фабричный метод с десятью аргументами, девять из которых будут регулярно повторяться, нельзя назвать удачным решением. В этом случае поможет другой порождающий паттерн — «Строитель».
Назначение: строитель отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.
Причины использования:
Паттерн «Строитель» идеально подходит для ситуаций, когда процесс создания является сложным и состоит из нескольких этапов, при этом одним клиентам нужно устанавливать одни параметры создаваемого объекта, а другим — другие. Строитель может устанавливать разумные значения по умолчанию, позволяя клиентам сосредоточиться лишь на важных для них параметрах.
Использование паттерна «Строитель» позволяет более четко разграничить ответственность между создателем и потребителем объектов, а также делает процесс создания более удобным. Это особенно полезно, если продукт физически или логически является неизменяемым (immutable).
Классическая диаграмма паттерна «Строитель» приведена в верхней части рисунка ниже:
-
Builder
определяет интерфейс конструирования продукта по частям;-
Director
управляет процессом создания, не зная, какой продукт будет создан в результате;-
ConcreteBuilder
— конкретный строитель, который создает известный только ему объект класса Product
.Обратите внимание на два момента: наличие наследования и то, что о классе
Product
знает только конкретный строитель (ConcreteBuilder
). Ни базовый класс строителя, ни его клиент (Director
) не знают о типе создаваемого продукта. Это позволяет конкретным строителям формировать совершенно разнородные объекты, но оставляет открытыми многие вопросы:- Кто потребляет созданный продукт?
- Как конкретный строитель узнает об этом потребителе?
- Всегда ли процесс формирования и потребления продуктов должен быть настолько разделён, что продукт конструируется классом
Director
, а потребляется непонятно кем?На практике обычно используется более простая разновидность паттерна «Строитель», без наследования и с более явной моделью взаимодействия между участниками (см. в нижней части рисунка). Участники в этом случае те же самые, но ответственность немного меняется:
-
Client
(Director
) управляет созданием сложного объекта и получает созданный объект путем вызова метода Build
. -
Builder
отвечает за создание конкретного продукта.Особенности реализации в .NET
1. Использование текучего интерфейса.
Текучий интерфейс предназначен для повышения читабельности кода. Каждый метод возвращает объект, над которым выполняется текущая операция, что позволяет связывать методы в цепочку:
var result = Enumerable.Range(1, 10).Select(n => n + 1).Count();При реализации строителей данная идиома используется постоянно, поскольку позволяет создавать требуемый объект одним оператором. Последним вызывается метод
Build
, возвращающий требуемый продукт.2. Методы расширения
Методы расширения позволяют создать видимость того, что мы добавляем операции в существующие типы. В некоторых случаях можно создать набор методов расширения, которые будут играть роль строителя для существующих типов.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 11.
День триста девяностый. #АтакиНаСайты
ASP.NET MVC 5. Безопасность Веб-Приложений
Когда ваше веб-приложение открыто для публичных пользователей, оно уязвимо для различных атак. Поскольку веб-приложения работают по стандартным текстовым протоколам, таким как HTTP и HTML, они также особенно уязвимы для автоматических атак ботами. В этой серии постов мы рассмотрим некоторые атаки на веб-приложения, с которыми вы можете столкнуться.
1. Cross-Site Scripting (XSS)
Это одна из наиболее популярных атак на веб-приложения. Она может быть выполнена двумя способами:
- Пассивным. XSS выполняется путем введения кода скрипта на сайт, который принимает пользовательский ввод. Многие формы позволяют пользователю указать адрес персональной веб-страницы. А разработчики часто ленятся проверять валидность введённого URL, поскольку это нетривиальная задача, и выводят отправленное пользователем значение, как есть, в код вроде этого:
- Активное внедрение XSS вовлекает жертву в атаку непосредственно. Оно подразумевает отправку пользователем вредоносной информации, которая отображается на странице и не сохраняется в базе данных сайта. Как это происходит? Многие сайты имеют возможность поиска по сайту и отображают в заголовке поиска строку, вроде:
Главное правило. Никогда, никогда не доверяйте никаким данным, которых пользователь хоть как-то может касаться: значения форм, URL-адреса, cookie или личные данные, полученные из сторонних источников, таких как OpenID. Базы данных или службы, к которым обращается ваш сайт, также могут быть скомпрометированы. Все входные данные для вашего приложения, являются подозрительными.
Предотвращение XSS
1. Кодирование HTML. В большинстве случаев вы можете избежать XSS, используя простую кодировку HTML - процесс, с помощью которого сервер заменяет зарезервированные символы HTML (например,
2. Url.Encode. Чтобы должным образом обезопасить ссылки (как из примера с пассивным XSS), можно использовать
3. Кодирование JavaScript. Если вы используете данные, полученные от пользователя внутри кода JavaScript, HTML кодирование не спасёт. Есть два решения этой проблемы: использование вспомогательной функции Ajax.JavaScriptStringEncode, либо библиотеки AntiXSS.
Библиотека AntiXSS может добавить дополнительный уровень безопасности:
- AntiXSS использует белый список разрешённых символов (ASP.NET по умолчанию использует ограниченный чёрный список запрещённых символов).
- AntiXSS сосредоточена на предотвращении уязвимостей в ваших приложениях кодировка, а кодирование в ASP.NET в первую очередь направлено на предотвращение проблем с отображением из-за «сломанного» HTML.
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 7.
ASP.NET MVC 5. Безопасность Веб-Приложений
Когда ваше веб-приложение открыто для публичных пользователей, оно уязвимо для различных атак. Поскольку веб-приложения работают по стандартным текстовым протоколам, таким как HTTP и HTML, они также особенно уязвимы для автоматических атак ботами. В этой серии постов мы рассмотрим некоторые атаки на веб-приложения, с которыми вы можете столкнуться.
1. Cross-Site Scripting (XSS)
Это одна из наиболее популярных атак на веб-приложения. Она может быть выполнена двумя способами:
- Пассивным. XSS выполняется путем введения кода скрипта на сайт, который принимает пользовательский ввод. Многие формы позволяют пользователю указать адрес персональной веб-страницы. А разработчики часто ленятся проверять валидность введённого URL, поскольку это нетривиальная задача, и выводят отправленное пользователем значение, как есть, в код вроде этого:
<a href="…URL…">…</a>
Очевидно, что отправка атакующим строки вроде "></a><script src="https://hack.com/trojan.js"></script> <a href="приведёт к тому, что в страницу будет включён скрипт с вредоносным кодом, который будет выполнен для каждого посетителя страницы. Внешний вид страницы при этом не меняется.
- Активное внедрение XSS вовлекает жертву в атаку непосредственно. Оно подразумевает отправку пользователем вредоносной информации, которая отображается на странице и не сохраняется в базе данных сайта. Как это происходит? Многие сайты имеют возможность поиска по сайту и отображают в заголовке поиска строку, вроде:
По запросу 'текст запроса' найдено X результатов.Уязвимость заключается в том, что
'текст запроса'
, введённый пользователем, не кодируется и позволяет вывести HTML код. Кроме того, этот текст сохраняется в URL запроса. Тогда атакующий с помощью нескольких манипуляций может вставить в URL форму входа в систему, требующую от жертвы логина и пароля для продолжения. А дальше в ход идёт социальная инженерия. Жертве отправляется эта длинная ссылка (на вполне безобидный сайт) с текстом вроде: «Тут твои фотки с вечеринки. Только введи свой пароль, я их закрыл от чужих глаз.» Удивительно, сколько людей до сих пор ведутся на такое. И хотя это нельзя назвать атакой непосредственно на ваш сайт, она может подорвать доверие пользователей к вашему сайту.Главное правило. Никогда, никогда не доверяйте никаким данным, которых пользователь хоть как-то может касаться: значения форм, URL-адреса, cookie или личные данные, полученные из сторонних источников, таких как OpenID. Базы данных или службы, к которым обращается ваш сайт, также могут быть скомпрометированы. Все входные данные для вашего приложения, являются подозрительными.
Предотвращение XSS
1. Кодирование HTML. В большинстве случаев вы можете избежать XSS, используя простую кодировку HTML - процесс, с помощью которого сервер заменяет зарезервированные символы HTML (например,
<
и >
) их кодами. В представлении MVC можно использовать Html.Encode
или Html.AttributeEncode
для значений атрибутов. Использование помощников Html также кодирует содержимое и значения атрибутов для каждого тега.2. Url.Encode. Чтобы должным образом обезопасить ссылки (как из примера с пассивным XSS), можно использовать
Url.Encode
.3. Кодирование JavaScript. Если вы используете данные, полученные от пользователя внутри кода JavaScript, HTML кодирование не спасёт. Есть два решения этой проблемы: использование вспомогательной функции Ajax.JavaScriptStringEncode, либо библиотеки AntiXSS.
Библиотека AntiXSS может добавить дополнительный уровень безопасности:
- AntiXSS использует белый список разрешённых символов (ASP.NET по умолчанию использует ограниченный чёрный список запрещённых символов).
- AntiXSS сосредоточена на предотвращении уязвимостей в ваших приложениях кодировка, а кодирование в ASP.NET в первую очередь направлено на предотвращение проблем с отображением из-за «сломанного» HTML.
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 7.
👍1
День триста девяносто первый. #MoreEffectiveCSharp
3. Использование значимых и ссылочных типов
Вы должны решить, как будут вести себя все экземпляры вашего типа. Это важное решение, которое нужно принять при создании, потому что изменение структуры на класс может поломать довольно много кода самым непредсказуемым образом.
Правильный выбор зависит от того, как вы собираетесь использовать новый тип. Структуры не полиморфны, они должны быть небольшими и лучше подходят для хранения данных, которыми манипулирует приложение. Классы могут быть полиморфными, формируют иерархию типов приложения и должны использоваться для определения поведения приложения. Подумайте об ожидаемых обязанностях вашего нового типа и, исходя из этого, решите, какой тип создать.
Например, тип используется как возвращаемое значение из метода:
Теперь немного подробнее рассмотрим, как эти типы хранятся в памяти, а также вопросы производительности, связанные с моделями хранения:
Решение использовать структуру или класс является очень важным. Изменение структуры на класс в готовом коде влечёт за собой неприятные последствия. Допустим вы создали структуру работника, хранящую размер заработной платы. Затем вы решаете, что могут быть разные классы сотрудников: продавцы получают комиссионные, а менеджеры получают бонусы. Вы решаете изменить структуру на класс. Это нарушит большую часть клиентского кода, использующего структуру. Возврат по значению становится возвратом по ссылке. Параметры, которые передавались по значению, теперь передаются по ссылке. Помимо хранения элементов данных, которые определяют сотрудника, вы добавили обязанности: расчёт зарплаты. Обязанности — это ответственность классов. Классы могут легко определять полиморфные реализации общих обязанностей; структуры должны ограничиваться хранением значений.
Документация по .NET рекомендует рассматривать размер типа как определяющий фактор между типами значений и ссылочными типами. На самом деле, гораздо лучшим фактором является способ использования типа. Если вы ответите «да» на все эти вопросы, создавайте структуру:
1. Основная обязанность типа - хранение данных?
2. Можно ли сделать этот тип неизменяемым?
3. Ожидается, что тип будет маленьким?
4. Открытый интерфейс типа содержит только свойства для доступа к данным?
5. У типа никогда не будет подклассов?
6. Тип никогда не будет использоваться полиморфно?
Если вы сомневаетесь относительно ожидаемого использования типа, используйте ссылочный тип.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 4.
3. Использование значимых и ссылочных типов
Вы должны решить, как будут вести себя все экземпляры вашего типа. Это важное решение, которое нужно принять при создании, потому что изменение структуры на класс может поломать довольно много кода самым непредсказуемым образом.
Правильный выбор зависит от того, как вы собираетесь использовать новый тип. Структуры не полиморфны, они должны быть небольшими и лучше подходят для хранения данных, которыми манипулирует приложение. Классы могут быть полиморфными, формируют иерархию типов приложения и должны использоваться для определения поведения приложения. Подумайте об ожидаемых обязанностях вашего нового типа и, исходя из этого, решите, какой тип создать.
Например, тип используется как возвращаемое значение из метода:
private MyData myData;Если
public MyData Foo() => myData;
MyData v = Foo();
TotalSum += v.Value;
MyData
— значимый тип, содержимое возврата копируется в переменную v
. А если MyData
— ссылочный тип, то экспортируется ссылка на внутреннюю переменную. Вы нарушаете принцип инкапсуляции, что может позволить клиентам изменять объект по ссылке, обходя ваш API. Другой вариант:public MyData Foo2 () => myData.CreateCopy();Теперь
v
— это копия исходных данных myData
. В куче создаются два объекта. Исчезла проблема раскрытия внутренних данных, но мы создали дополнительный объект в куче. В общем, это неэффективно. Типы, которые используются для экспорта данных с помощью открытых методов и свойств, должны быть значимыми типами.Теперь немного подробнее рассмотрим, как эти типы хранятся в памяти, а также вопросы производительности, связанные с моделями хранения:
public class C {Сколько объектов создано? Насколько они большие? Это зависит. Если
private MyType a = new MyType();
private MyType b = new MyType();
…
}
C c = new C();
MyType
— структура, выделен один объект, размер которого в два раза больше размера MyType
. А если MyType
— класс, выделено 3 объекта: для типа C (8 байт в 32-разрядной системе) и 2 для типа MyType
. Разница возникает из-за того, что структуры хранятся внутри объекта, а каждая переменная ссылочного типа содержит ссылку, и требует выделения дополнительного места в хранилище. Это особенно важно, если вы собираетесь выделить место под массив. Массив структур выделится за 1 раз, массив ссылочных типов изначально будет заполнен null
, но потребует дополнительного выделения места под каждый элемент при его инициализации.Решение использовать структуру или класс является очень важным. Изменение структуры на класс в готовом коде влечёт за собой неприятные последствия. Допустим вы создали структуру работника, хранящую размер заработной платы. Затем вы решаете, что могут быть разные классы сотрудников: продавцы получают комиссионные, а менеджеры получают бонусы. Вы решаете изменить структуру на класс. Это нарушит большую часть клиентского кода, использующего структуру. Возврат по значению становится возвратом по ссылке. Параметры, которые передавались по значению, теперь передаются по ссылке. Помимо хранения элементов данных, которые определяют сотрудника, вы добавили обязанности: расчёт зарплаты. Обязанности — это ответственность классов. Классы могут легко определять полиморфные реализации общих обязанностей; структуры должны ограничиваться хранением значений.
Документация по .NET рекомендует рассматривать размер типа как определяющий фактор между типами значений и ссылочными типами. На самом деле, гораздо лучшим фактором является способ использования типа. Если вы ответите «да» на все эти вопросы, создавайте структуру:
1. Основная обязанность типа - хранение данных?
2. Можно ли сделать этот тип неизменяемым?
3. Ожидается, что тип будет маленьким?
4. Открытый интерфейс типа содержит только свойства для доступа к данным?
5. У типа никогда не будет подклассов?
6. Тип никогда не будет использоваться полиморфно?
Если вы сомневаетесь относительно ожидаемого использования типа, используйте ссылочный тип.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 4.
День триста девяносто второй. #DebuggingTools
10 основных инструментов отладки в .NET. Начало (1-4)
Когда дело доходит до отладки, чрезвычайно важны правильные инструменты. Правильный инструмент => правильная информация => лёгкий поиск причины проблемы => быстрое исправление ошибки.
Помимо обычных проблем в коде, следующие инструменты помогают найти другие типы проблем:
- С производительностью
- С памятью (перегрузка GC и утечки памяти)
- Со сторонними библиотеками
- В продакшн среде
- С сетью
1. Visual Studio
Основным инструментом отладки является Visual Studio. Она имеет массу функций, включая различные окна инструментов, параметры исключений, всплывающие подсказки и многое другое. Microsoft удалось включить как базовые, так и расширенные функции в интуитивно понятную программу, что сделало Visual Studio второй по популярности IDE для всех разработчиков согласно опросу StackOverflow 2019 года.
Помимо интерактивной (традиционной) отладки, VS включает в себя множество других инструментов анализа:
- Профилирование производительности
- Профилирование памяти
- Историческая отладка с IntelliTrace
- Облачная отладка (как часть Cloud Explorer)
Хотя некоторые из следующих инструментов могут быть предпочтительнее.
2. dnSpy
dnSpy - один из самых полезных инструментов для отладки в .NET. Это хороший декомпилятор, но его основное применение - отладчик. dnSpy позволяет отлаживать любую сборку .NET независимо от наличия символов или исходного кода.
Этот инструмент выглядит и ведёт себя как Visual Studio. Когда вы начинаете отладку процесса .NET без символов или исходного кода, dnSpy показывает вам декомпилированный код. А дальше начинается волшебство: вы можете поместить точки останова в сам декомпилированный код. При достижении этих точек останова вы увидите локальные переменные, потоки, стек вызовов и получите полноценный опыт отладки. Это делает dnSpy одним из лучших инструментов для отладки стороннего кода и производственной среды. Он легкий и не требует установки. Просто скопируйте папку на любой продакшн сервер и начните отладку.
Тут есть небольшая хитрость. Если вы запустите процесс с помощью dnSpy, всё будет работать хорошо. Но если вы подключитесь к запущенному процессу, модули, которые уже были загружены, останутся оптимизированными (как если бы они были собраны в режиме «Release»). Когда код оптимизирован, некоторые точки останова не будут достигаться, а некоторые локальные переменные не будут показываться. Это сильно ухудшит отладку. Просто перезапустите процесс с помощью dnSpy, а не присоединяйтесь к нему.
3. dotPeek
dotPeek - это бесплатный .NET-декомпилятор от JetBrains. Он выделяется среди других по двум причинам:
- Лучший пользовательский опыт: он выглядит и ощущается как ReSharper.
- Он может создать сервер символов из любой сборки, даже не имея символов или исходного кода. В этом он похож на dnSpy: он декомпилирует код и создает из него символы. С помощью dotPeek Visual Studio может отлаживать любой сторонний код, как dnSpy.
4. dotTrace
dotTrace - ещё один инструмент от JetBrains - профилировщик производительности. dotTrace позволяет «записать» выполнение приложения, а затем проанализировать производительность записи. Вы сможете увидеть, сколько времени было потрачено на каждый из вызванных методов, на запросы к базе данных, запросы HTTP, на сборку мусора и так далее.
На картинке ниже показан краткий анализ записи работы Visual Studio. Вы можете видеть, что
Сначала нужно потратить немного времени на обучение, но, как только вы к нему привыкнете, профайлинг станет очень простым.
Источник: Michael Shpilt - https://michaelscodingspot.com/
10 основных инструментов отладки в .NET. Начало (1-4)
Когда дело доходит до отладки, чрезвычайно важны правильные инструменты. Правильный инструмент => правильная информация => лёгкий поиск причины проблемы => быстрое исправление ошибки.
Помимо обычных проблем в коде, следующие инструменты помогают найти другие типы проблем:
- С производительностью
- С памятью (перегрузка GC и утечки памяти)
- Со сторонними библиотеками
- В продакшн среде
- С сетью
1. Visual Studio
Основным инструментом отладки является Visual Studio. Она имеет массу функций, включая различные окна инструментов, параметры исключений, всплывающие подсказки и многое другое. Microsoft удалось включить как базовые, так и расширенные функции в интуитивно понятную программу, что сделало Visual Studio второй по популярности IDE для всех разработчиков согласно опросу StackOverflow 2019 года.
Помимо интерактивной (традиционной) отладки, VS включает в себя множество других инструментов анализа:
- Профилирование производительности
- Профилирование памяти
- Историческая отладка с IntelliTrace
- Облачная отладка (как часть Cloud Explorer)
Хотя некоторые из следующих инструментов могут быть предпочтительнее.
2. dnSpy
dnSpy - один из самых полезных инструментов для отладки в .NET. Это хороший декомпилятор, но его основное применение - отладчик. dnSpy позволяет отлаживать любую сборку .NET независимо от наличия символов или исходного кода.
Этот инструмент выглядит и ведёт себя как Visual Studio. Когда вы начинаете отладку процесса .NET без символов или исходного кода, dnSpy показывает вам декомпилированный код. А дальше начинается волшебство: вы можете поместить точки останова в сам декомпилированный код. При достижении этих точек останова вы увидите локальные переменные, потоки, стек вызовов и получите полноценный опыт отладки. Это делает dnSpy одним из лучших инструментов для отладки стороннего кода и производственной среды. Он легкий и не требует установки. Просто скопируйте папку на любой продакшн сервер и начните отладку.
Тут есть небольшая хитрость. Если вы запустите процесс с помощью dnSpy, всё будет работать хорошо. Но если вы подключитесь к запущенному процессу, модули, которые уже были загружены, останутся оптимизированными (как если бы они были собраны в режиме «Release»). Когда код оптимизирован, некоторые точки останова не будут достигаться, а некоторые локальные переменные не будут показываться. Это сильно ухудшит отладку. Просто перезапустите процесс с помощью dnSpy, а не присоединяйтесь к нему.
3. dotPeek
dotPeek - это бесплатный .NET-декомпилятор от JetBrains. Он выделяется среди других по двум причинам:
- Лучший пользовательский опыт: он выглядит и ощущается как ReSharper.
- Он может создать сервер символов из любой сборки, даже не имея символов или исходного кода. В этом он похож на dnSpy: он декомпилирует код и создает из него символы. С помощью dotPeek Visual Studio может отлаживать любой сторонний код, как dnSpy.
4. dotTrace
dotTrace - ещё один инструмент от JetBrains - профилировщик производительности. dotTrace позволяет «записать» выполнение приложения, а затем проанализировать производительность записи. Вы сможете увидеть, сколько времени было потрачено на каждый из вызванных методов, на запросы к базе данных, запросы HTTP, на сборку мусора и так далее.
На картинке ниже показан краткий анализ записи работы Visual Studio. Вы можете видеть, что
ShowWindow
занял 155 мс, включая методы HwndSourceHook
(42 мс), Convert
(16 мс) и так далее. Выполнение этого метода на 42% состоит из вызовов WPF, 20% кода пользователя, 11,5% ожиданий GC, 10% кода коллекций, 10% кода рефлексии и 5% системного кода. Неплохо, правда?Сначала нужно потратить немного времени на обучение, но, как только вы к нему привыкнете, профайлинг станет очень простым.
Источник: Michael Shpilt - https://michaelscodingspot.com/
День триста девяносто третий. #DebuggingTools
10 основных инструментов отладки в .NET. Продолжение (5-7)
5. SciTech's .NET Memory Profiler
Профилировщик памяти - это ещё одна категория инструментов, которые необходимы для решения проблем с памятью: утечек памяти или снижения производительности от нагрузки на GC. Если у вас достаточно большое приложение, рано или поздно у вас возникнут проблемы с памятью.
Профилировщик памяти может сделать «снимок памяти» и позволить вам исследовать его. Вы увидите, какие объекты занимают больше всего памяти, кто ссылается на них и почему они не были собраны сборщиком мусора. Сравнивая два снимка, вы можете обнаружить утечки памяти.
Доступно несколько профилировщиков памяти, но SciTech .NET Memory Profiler, по-моему, самый мощный и имеет меньше всего проблем.
6. OzCode
OzCode - это уникальное расширение Visual Studio. Его единственная цель - помочь вашей интерактивной отладке. OzCode имеет большой набор функций, которые можно разделить на 4 части:
- Heads-up display - добавляет некоторые полезные функции визуализации во время отладки, например, выделение красным/зелёным и отображение выбранных свойств объекта или разбиение выражения на части.
- Отладка LINQ - LINQ отлично подходит для написания кода, но его очень сложно отлаживать. OzCode позволяет исследовать выражения LINQ во время отладки практически без проблем.
- DataTip - это всплывающее окно, которое появляется при наведении на переменные в Visual Studio. OzCode заменяет это окно собственным, усовершенствованным, которое имеет опции «любимых» свойств, поиска, экспорта в JSON и т.п.
- Time Travel - в 4 версии добавлена новая революционная функция отладки. OzCode может предсказать будущее без перемещения точки останова. То есть вы сможете увидеть, что происходит в строке кода, которая находится после вашей текущей позиции отладки. Эта функция работает не во всех случаях. Например, OzCode не может предсказать такие вещи, как результаты HTTP-запроса или SQL-запросы, потому что для этого он должен их выполнить.
7. SysInternals
Sysinternals - это набор утилит для устранения неполадок и мониторинга программного обеспечения Windows. Он включает в себя некоторые из наиболее важных инструментов, которые нам нужны для отладки. Лучше всего скачать весь пакет и сохранить его где-нибудь, для лёгкого доступа из командной строки, например C:\Sysinternals. Вот несколько наиболее важных для .NET инструментов:
Process Explorer
Похож на диспетчер задач Windows на стероидах. Он имеет множество функций, полезных для отладки:
- Просмотр загруженных модулей
- Просмотр хэндлеров
- Создание дампов
- Просмотр дерева процессов
- Просмотр счётчиков производительности
Process Monitor, также известный как ProcMon.
Позволяет отслеживать события активности процессов. В частности, вы можете видеть события доступа к реестру, файлам, сети, активность потоков и события профилирования. Если вы хотите узнать, какие файлы или значения реестра были затронуты вашим процессом, то ProcMon вам поможет.
ProcDump
Это инструмент командной строки для сохранения дампов. Он может генерировать дампы по требованию или по триггерам. Вот некоторые из вариантов создания дампов:
- немедленно
- несколько дампов с определенными интервалами (например, 3х дампов с интервалом 5 секунд)
- при превышении порога нагрузки на CPU
- при зависании процесса
- при сбое
Подробнее о способах отладки по дампам в докладе Саши Гольдштейна на DotNext 2015 Moscow.
Источник: Michael Shpilt - https://michaelscodingspot.com/
10 основных инструментов отладки в .NET. Продолжение (5-7)
5. SciTech's .NET Memory Profiler
Профилировщик памяти - это ещё одна категория инструментов, которые необходимы для решения проблем с памятью: утечек памяти или снижения производительности от нагрузки на GC. Если у вас достаточно большое приложение, рано или поздно у вас возникнут проблемы с памятью.
Профилировщик памяти может сделать «снимок памяти» и позволить вам исследовать его. Вы увидите, какие объекты занимают больше всего памяти, кто ссылается на них и почему они не были собраны сборщиком мусора. Сравнивая два снимка, вы можете обнаружить утечки памяти.
Доступно несколько профилировщиков памяти, но SciTech .NET Memory Profiler, по-моему, самый мощный и имеет меньше всего проблем.
6. OzCode
OzCode - это уникальное расширение Visual Studio. Его единственная цель - помочь вашей интерактивной отладке. OzCode имеет большой набор функций, которые можно разделить на 4 части:
- Heads-up display - добавляет некоторые полезные функции визуализации во время отладки, например, выделение красным/зелёным и отображение выбранных свойств объекта или разбиение выражения на части.
- Отладка LINQ - LINQ отлично подходит для написания кода, но его очень сложно отлаживать. OzCode позволяет исследовать выражения LINQ во время отладки практически без проблем.
- DataTip - это всплывающее окно, которое появляется при наведении на переменные в Visual Studio. OzCode заменяет это окно собственным, усовершенствованным, которое имеет опции «любимых» свойств, поиска, экспорта в JSON и т.п.
- Time Travel - в 4 версии добавлена новая революционная функция отладки. OzCode может предсказать будущее без перемещения точки останова. То есть вы сможете увидеть, что происходит в строке кода, которая находится после вашей текущей позиции отладки. Эта функция работает не во всех случаях. Например, OzCode не может предсказать такие вещи, как результаты HTTP-запроса или SQL-запросы, потому что для этого он должен их выполнить.
7. SysInternals
Sysinternals - это набор утилит для устранения неполадок и мониторинга программного обеспечения Windows. Он включает в себя некоторые из наиболее важных инструментов, которые нам нужны для отладки. Лучше всего скачать весь пакет и сохранить его где-нибудь, для лёгкого доступа из командной строки, например C:\Sysinternals. Вот несколько наиболее важных для .NET инструментов:
Process Explorer
Похож на диспетчер задач Windows на стероидах. Он имеет множество функций, полезных для отладки:
- Просмотр загруженных модулей
- Просмотр хэндлеров
- Создание дампов
- Просмотр дерева процессов
- Просмотр счётчиков производительности
Process Monitor, также известный как ProcMon.
Позволяет отслеживать события активности процессов. В частности, вы можете видеть события доступа к реестру, файлам, сети, активность потоков и события профилирования. Если вы хотите узнать, какие файлы или значения реестра были затронуты вашим процессом, то ProcMon вам поможет.
ProcDump
Это инструмент командной строки для сохранения дампов. Он может генерировать дампы по требованию или по триггерам. Вот некоторые из вариантов создания дампов:
- немедленно
- несколько дампов с определенными интервалами (например, 3х дампов с интервалом 5 секунд)
- при превышении порога нагрузки на CPU
- при зависании процесса
- при сбое
Подробнее о способах отладки по дампам в докладе Саши Гольдштейна на DotNext 2015 Moscow.
Источник: Michael Shpilt - https://michaelscodingspot.com/
День триста девяносто четвёртый. #DebuggingTools
10 основных инструментов отладки в .NET. Окончание (8-10)
8. Performance Monitor (PerfMon)
В Windows есть встроенные механизмы, которые называются счетчиками производительности. Они позволяют вам следить за множеством полезных показателей того, что происходит на компьютере. Это могут быть метрики для всей системы или для конкретного процесса. Вот несколько примеров того, что вы можете измерить с их помощью:
- Использование процессора
- Использование памяти
- Количество исключений выброшенных в процессе
- Скорость чтения/записи ввода-вывода
- Количество запросов к вашему приложению ASP.NET
- Время ответа на запрос вашего приложения ASP.NET
Есть тысячи различных счетчиков, которые вы можете отслеживать. Например, если вы хотите узнать об использовании памяти процессом, есть счетчики собственной памяти, виртуальной памяти, занятой памяти, количества сборок мусора в поколении X, процента времени GC, размера кучи больших объектов и многое другое.
Performance Monitor - это инструмент, который позволяет визуализировать эти счетчики (хотя есть и другие инструменты). Он предустановлен в Windows. Чтобы запустить его, просто наберите «Performance Monitor» в меню «Пуск» или perfmon в командной строке.
9. PerfView
PerfView - это инструмент анализа общего назначения с открытым исходным кодом. Он имеет множество функций, например:
- Профилирование производительности
- Профилирование памяти
- Анализ событий ETW
- Импорт снимков производительности из Linux
- Различные отчёты о поведении приложений, включая время компиляции JIT, время сборки мусора и другие
Его анализ основан на событиях Трассировки Событий для Windows (ETW). Это встроенная система ведения журналов, которая чрезвычайно быстра и используется всеми частями Windows. Все процессы регистрируют события в ETW, включая ядро, ОС Windows, среду выполнения CLR, IIS, инфраструктуру ASP.NET, WPF и т.д.
PerfView - самый сложный инструмент в этом списке, но очень мощный. На Channel 9 есть видеокурс по использованию PerfView.
10. Fiddler
Fiddler - бесплатный инструмент от Progress Telerik для отладки сетевых вызовов. Он захватывает все HTTP-запросы, регистрирует данные и отправляет запрос дальше по назначению. Для каждого запроса вы можете увидеть его прогресс, заголовки, полезную нагрузку, ответ, статус.
Для отладки Fiddler имеет несколько полезных функций:
- Повторение запроса - вы можете щёлкнуть правой кнопкой мыши на любом запросе и нажать «Replay», что снова отправит точно такой же запрос. Это полезно при устранении неполадок на стороне сервера. Если вы хотите воспроизвести проблемный запрос, Fiddler избавит вас от необходимости повторного запуска сценария на клиенте для повторной отправки того же запроса. Это также помогает с запросами, которые трудно воспроизвести.
- Редактирование и воспроизведение запросов - Fiddler позволяет не только воспроизводить запросы, но и изменять их. Вы можете изменить заголовки, тело и даже URL. Вы можете использовать его, чтобы увидеть, как ваша серверная сторона справляется с пограничными случаями. Или для воспроизведения проблемы, которая происходит при конкретном запросе.
Не вошедший в топ. WinDbg
WinDbg раньше был основным средством отладки для Windows, как сейчас Visual Studio для .NET. Сейчас он не так актуален, по крайней мере для разработки в .NET. В Visual Studio вы можете делать практически всё, и это будет проще и быстрее. Однако кое в чём WinDbg всё ещё лучше, например, его возможности сценариев, простой удалённый доступ и удобная отладка в продакшн среде. Вы можете скопировать WinDbg на продакшн и довольно быстро исследовать файлы дампов. Он не требует долгой установки, как Visual Studio. Однако лично я всегда копирую файлы дампа на мою машину и открываю их с помощью профилировщика памяти или Visual Studio. Это просто более эффективно. Таким образом, мой вердикт заключается в том, что WinDbg больше не является важным инструментом отладки для разработки в .NET.
Источник: Michael Shpilt - https://michaelscodingspot.com/
10 основных инструментов отладки в .NET. Окончание (8-10)
8. Performance Monitor (PerfMon)
В Windows есть встроенные механизмы, которые называются счетчиками производительности. Они позволяют вам следить за множеством полезных показателей того, что происходит на компьютере. Это могут быть метрики для всей системы или для конкретного процесса. Вот несколько примеров того, что вы можете измерить с их помощью:
- Использование процессора
- Использование памяти
- Количество исключений выброшенных в процессе
- Скорость чтения/записи ввода-вывода
- Количество запросов к вашему приложению ASP.NET
- Время ответа на запрос вашего приложения ASP.NET
Есть тысячи различных счетчиков, которые вы можете отслеживать. Например, если вы хотите узнать об использовании памяти процессом, есть счетчики собственной памяти, виртуальной памяти, занятой памяти, количества сборок мусора в поколении X, процента времени GC, размера кучи больших объектов и многое другое.
Performance Monitor - это инструмент, который позволяет визуализировать эти счетчики (хотя есть и другие инструменты). Он предустановлен в Windows. Чтобы запустить его, просто наберите «Performance Monitor» в меню «Пуск» или perfmon в командной строке.
9. PerfView
PerfView - это инструмент анализа общего назначения с открытым исходным кодом. Он имеет множество функций, например:
- Профилирование производительности
- Профилирование памяти
- Анализ событий ETW
- Импорт снимков производительности из Linux
- Различные отчёты о поведении приложений, включая время компиляции JIT, время сборки мусора и другие
Его анализ основан на событиях Трассировки Событий для Windows (ETW). Это встроенная система ведения журналов, которая чрезвычайно быстра и используется всеми частями Windows. Все процессы регистрируют события в ETW, включая ядро, ОС Windows, среду выполнения CLR, IIS, инфраструктуру ASP.NET, WPF и т.д.
PerfView - самый сложный инструмент в этом списке, но очень мощный. На Channel 9 есть видеокурс по использованию PerfView.
10. Fiddler
Fiddler - бесплатный инструмент от Progress Telerik для отладки сетевых вызовов. Он захватывает все HTTP-запросы, регистрирует данные и отправляет запрос дальше по назначению. Для каждого запроса вы можете увидеть его прогресс, заголовки, полезную нагрузку, ответ, статус.
Для отладки Fiddler имеет несколько полезных функций:
- Повторение запроса - вы можете щёлкнуть правой кнопкой мыши на любом запросе и нажать «Replay», что снова отправит точно такой же запрос. Это полезно при устранении неполадок на стороне сервера. Если вы хотите воспроизвести проблемный запрос, Fiddler избавит вас от необходимости повторного запуска сценария на клиенте для повторной отправки того же запроса. Это также помогает с запросами, которые трудно воспроизвести.
- Редактирование и воспроизведение запросов - Fiddler позволяет не только воспроизводить запросы, но и изменять их. Вы можете изменить заголовки, тело и даже URL. Вы можете использовать его, чтобы увидеть, как ваша серверная сторона справляется с пограничными случаями. Или для воспроизведения проблемы, которая происходит при конкретном запросе.
Не вошедший в топ. WinDbg
WinDbg раньше был основным средством отладки для Windows, как сейчас Visual Studio для .NET. Сейчас он не так актуален, по крайней мере для разработки в .NET. В Visual Studio вы можете делать практически всё, и это будет проще и быстрее. Однако кое в чём WinDbg всё ещё лучше, например, его возможности сценариев, простой удалённый доступ и удобная отладка в продакшн среде. Вы можете скопировать WinDbg на продакшн и довольно быстро исследовать файлы дампов. Он не требует долгой установки, как Visual Studio. Однако лично я всегда копирую файлы дампа на мою машину и открываю их с помощью профилировщика памяти или Visual Studio. Это просто более эффективно. Таким образом, мой вердикт заключается в том, что WinDbg больше не является важным инструментом отладки для разработки в .NET.
Источник: Michael Shpilt - https://michaelscodingspot.com/
День триста девяносто пятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
28. Позвольте трупу упасть
Однажды я предложил коллегам шутливую викторину: напишите программу, которая при помощи множества конструкций try…catch по всему коду ни за что не даёт программе завершиться аварийно. Результат мы назвали «труп, не падающий потому, что он прибит гвоздями к стене». Несмотря на легкомысленность примера, он основан на горьком опыте.
У нас был базовый класс в нашей собственной библиотеке C++. На протяжении многих лет он страдал от рук многих программистов (и мало у кого руки росли из нужного места). Класс содержал код для обработки всех возможных исключений из всех возможных мест. Мы решили (нет, скорее, убедили себя, потому что «решение» предполагает обдумывание, чем мы не занимались, когда создавали этого монстра), что экземпляр нашего класса, как Йоссариан из «Уловки-22», должен жить вечно или умереть в попытках это сделать.
Для этого мы сплели сеть из множества обработчиков исключений. Мы смешали в кучу как «родные» обработчики, так и обработчики Windows. Когда что-то неожиданно падало, мы пытались вызвать обработчики снова, сильнее ограничивая параметры. Оглядываясь назад, мне нравится сравнивать написание конструкций try…catch, вложенных в другие блоки catch, с решением свернуть с широкой дороги проверенных практик на манящую, но опасную для здоровья узкую тропинку безумия. Однако, это уже «умная мысля опосля».
Излишне говорить, что, когда что-то ломалось в приложениях, основанных на этом классе, ошибки пропадали, как жертвы мафии в суде, не оставляя улик, указывающих на то, что же, чёрт возьми, произошло, несмотря на процедуры логирования и дампы, которые должны были вызываться для записи поломки. В конце концов – много времени спустя - мы посмотрели на то, что мы натворили, и нам стало стыдно. Мы заменили весь этот хаос на краткий и надёжный механизм сообщения об ошибках. Но произошло это после многих и многих сбоев, оставшихся необнаруженными.
Я не стал бы об этом писать – вряд ли кто-то может быть таким же глупым, как мы, - если бы не недавний онлайн-спор с парнем, академическая должность которого намекала на то, что он кое-что должен понимать. Мы обсуждали код Java в удалённой транзакции. «Если код терпит неудачу», - утверждал он, - «он должен перехватить исключение на месте и не пробрасывать его наружу». «И что с ним сделать?» - спросил я. - «Приготовить его на ужин?»
Он процитировал правило дизайнеров пользовательского интерфейса: «НИКОГДА НЕ ПОЗВОЛЯЙТЕ ПОЛЬЗОВАТЕЛЮ ВИДЕТЬ СООБЩЕНИЕ ОБ ОШИБКАХ», - видимо, не задумываясь о том, что капс и «никогда» – это не самые лучшие аргументы. Я спросил, не он ли писал софт для банкоматов, «синий экран» которых так любят фоткать и выкладывать в сеть, за что был забанен.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Verity Stob
97 Вещей, Которые Должен Знать Каждый Программист
28. Позвольте трупу упасть
Однажды я предложил коллегам шутливую викторину: напишите программу, которая при помощи множества конструкций try…catch по всему коду ни за что не даёт программе завершиться аварийно. Результат мы назвали «труп, не падающий потому, что он прибит гвоздями к стене». Несмотря на легкомысленность примера, он основан на горьком опыте.
У нас был базовый класс в нашей собственной библиотеке C++. На протяжении многих лет он страдал от рук многих программистов (и мало у кого руки росли из нужного места). Класс содержал код для обработки всех возможных исключений из всех возможных мест. Мы решили (нет, скорее, убедили себя, потому что «решение» предполагает обдумывание, чем мы не занимались, когда создавали этого монстра), что экземпляр нашего класса, как Йоссариан из «Уловки-22», должен жить вечно или умереть в попытках это сделать.
Для этого мы сплели сеть из множества обработчиков исключений. Мы смешали в кучу как «родные» обработчики, так и обработчики Windows. Когда что-то неожиданно падало, мы пытались вызвать обработчики снова, сильнее ограничивая параметры. Оглядываясь назад, мне нравится сравнивать написание конструкций try…catch, вложенных в другие блоки catch, с решением свернуть с широкой дороги проверенных практик на манящую, но опасную для здоровья узкую тропинку безумия. Однако, это уже «умная мысля опосля».
Излишне говорить, что, когда что-то ломалось в приложениях, основанных на этом классе, ошибки пропадали, как жертвы мафии в суде, не оставляя улик, указывающих на то, что же, чёрт возьми, произошло, несмотря на процедуры логирования и дампы, которые должны были вызываться для записи поломки. В конце концов – много времени спустя - мы посмотрели на то, что мы натворили, и нам стало стыдно. Мы заменили весь этот хаос на краткий и надёжный механизм сообщения об ошибках. Но произошло это после многих и многих сбоев, оставшихся необнаруженными.
Я не стал бы об этом писать – вряд ли кто-то может быть таким же глупым, как мы, - если бы не недавний онлайн-спор с парнем, академическая должность которого намекала на то, что он кое-что должен понимать. Мы обсуждали код Java в удалённой транзакции. «Если код терпит неудачу», - утверждал он, - «он должен перехватить исключение на месте и не пробрасывать его наружу». «И что с ним сделать?» - спросил я. - «Приготовить его на ужин?»
Он процитировал правило дизайнеров пользовательского интерфейса: «НИКОГДА НЕ ПОЗВОЛЯЙТЕ ПОЛЬЗОВАТЕЛЮ ВИДЕТЬ СООБЩЕНИЕ ОБ ОШИБКАХ», - видимо, не задумываясь о том, что капс и «никогда» – это не самые лучшие аргументы. Я спросил, не он ли писал софт для банкоматов, «синий экран» которых так любят фоткать и выкладывать в сеть, за что был забанен.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Verity Stob
День триста девяносто шестой. #Оффтоп
Вопросы и ответы с Робертом Грином: Разработка с помощью Visual Studio и Azure DevOps
Разработчики, плохо знакомые с методологией DevOps, могут не знать о её преимуществах, таких как более частые релизы, снижение частоты сбоев и более быстрые исправления ошибок. Команды разработчиков, и даже отдельные программисты, могут использовать концепции гибкой разработки, непрерывной интеграции и непрерывной доставки (CI/CD) при создании ПО. Независимый консультант Роберт Грин в интервью Visual Studio Magazine рассказал о его видении DevOps.
- Что бы вы хотели, чтобы каждый разработчик в первую очередь понимал о методах DevOps?
- Практики DevOps в основном направлены на то, чтобы непрерывно приносить пользу вашим конечным пользователям. Представьте две команды разработчиков ПО. Клиенты находят ошибку в новой версии продукта. Команда А говорит, что придётся ждать ежеквартального пакета обновлений с исправлением. Команда B говорит им, что её исправят сегодня, а обновление выйдет в ближайшее время. Клиенты хотят иметь возможность сортировать список по дате, а потом по сумме. Команда А говорит, что нужно ждать следующего полугодового обновления. Команда B говорит, что включат опцию в следующее еженедельное обновление функционала. Практики DevOps помогают вам больше походить на команду B, создавать лучший продукт и быстрее доставлять его клиентам.
- Какие 1-3 лучшие методики DevOps вы считаете наиболее важными для разработчиков?
- Управление версиями. Конвейер непрерывной интеграции (сборки). Конвейер постоянной доставки. Они автоматизируют большую часть работы, которую вам приходится выполнять вручную. Рассмотрим следующий процесс:
1. Вы загружаете код в систему контроля версий.
2. Выполняется полный набор юнит-тестов.
3. Если они проходят, приложение развёртывается на двух тестовых серверах, один из которых запускает автоматические тесты UI, а другой специфические тесты.
Если вы настроите конвейер CI/CD, все процессы после загрузки кода происходят автоматически и каждый раз одинаково. Это экономит ваше время, снижает количество ошибок, и, следовательно, вы сможете быстрее доставлять обновления.
- Насколько DevOps помогает командам разработчиков переосмыслить свои процессы?
- Первое, что нужно переосмыслить, это частоту выпусков обновлений (спринтов). Ежедневно для ошибок и еженедельно для функционала? Еженедельно для ошибок и ежемесячно для функционала? Какая частота удовлетворит ваших клиентов и оставит довольными разработчиков? Как только вы определитесь с темпом выпуска, нужно научиться управлять количеством работы в каждом выпуске. Со временем вы будете всё лучше и лучше его оценивать, и тогда вы сможете прогнозировать, какие функции и когда будут добавлены в продукт.
- Был ли DevOps раньше и почему он получил такое внимание сейчас?
- Я уверен, что у него было много имен. Разработчикам в Visual Studio может быть знакомо понятие ALM (Application Lifecycle Management). Сейчас клиенты ожидают более частых исправлений ошибок и добавлений новых функций. Приложения на наших телефонах обновляются часто и регулярно, Windows и Visual Studio тоже. Если вы не можете предоставлять достаточно частые обновления, вы рискуете потерять уважение и доверие ваших клиентов.
- Как службы Azure помогают осуществлять DevOps на практике?
- Службы Azure DevOps предоставляют интерфейс для планирования (создания резервных копий, отслеживания ошибок, управления спринтами, отслеживания прогресса), разработки (записи, тестирования, проверки и сборки) кода, доставки (выпуска для тестирования, подготовки, продакшена) и эксплуатации (мониторинга и устранения неполадок).
- Являются ли методы DevOps действительно важными для разработчиков?
- Я думаю, да. И несложно начать их использовать.
Источник: https://visualstudiomagazine.com/articles/2020/02/24/devops-qa.aspx
Вопросы и ответы с Робертом Грином: Разработка с помощью Visual Studio и Azure DevOps
Разработчики, плохо знакомые с методологией DevOps, могут не знать о её преимуществах, таких как более частые релизы, снижение частоты сбоев и более быстрые исправления ошибок. Команды разработчиков, и даже отдельные программисты, могут использовать концепции гибкой разработки, непрерывной интеграции и непрерывной доставки (CI/CD) при создании ПО. Независимый консультант Роберт Грин в интервью Visual Studio Magazine рассказал о его видении DevOps.
- Что бы вы хотели, чтобы каждый разработчик в первую очередь понимал о методах DevOps?
- Практики DevOps в основном направлены на то, чтобы непрерывно приносить пользу вашим конечным пользователям. Представьте две команды разработчиков ПО. Клиенты находят ошибку в новой версии продукта. Команда А говорит, что придётся ждать ежеквартального пакета обновлений с исправлением. Команда B говорит им, что её исправят сегодня, а обновление выйдет в ближайшее время. Клиенты хотят иметь возможность сортировать список по дате, а потом по сумме. Команда А говорит, что нужно ждать следующего полугодового обновления. Команда B говорит, что включат опцию в следующее еженедельное обновление функционала. Практики DevOps помогают вам больше походить на команду B, создавать лучший продукт и быстрее доставлять его клиентам.
- Какие 1-3 лучшие методики DevOps вы считаете наиболее важными для разработчиков?
- Управление версиями. Конвейер непрерывной интеграции (сборки). Конвейер постоянной доставки. Они автоматизируют большую часть работы, которую вам приходится выполнять вручную. Рассмотрим следующий процесс:
1. Вы загружаете код в систему контроля версий.
2. Выполняется полный набор юнит-тестов.
3. Если они проходят, приложение развёртывается на двух тестовых серверах, один из которых запускает автоматические тесты UI, а другой специфические тесты.
Если вы настроите конвейер CI/CD, все процессы после загрузки кода происходят автоматически и каждый раз одинаково. Это экономит ваше время, снижает количество ошибок, и, следовательно, вы сможете быстрее доставлять обновления.
- Насколько DevOps помогает командам разработчиков переосмыслить свои процессы?
- Первое, что нужно переосмыслить, это частоту выпусков обновлений (спринтов). Ежедневно для ошибок и еженедельно для функционала? Еженедельно для ошибок и ежемесячно для функционала? Какая частота удовлетворит ваших клиентов и оставит довольными разработчиков? Как только вы определитесь с темпом выпуска, нужно научиться управлять количеством работы в каждом выпуске. Со временем вы будете всё лучше и лучше его оценивать, и тогда вы сможете прогнозировать, какие функции и когда будут добавлены в продукт.
- Был ли DevOps раньше и почему он получил такое внимание сейчас?
- Я уверен, что у него было много имен. Разработчикам в Visual Studio может быть знакомо понятие ALM (Application Lifecycle Management). Сейчас клиенты ожидают более частых исправлений ошибок и добавлений новых функций. Приложения на наших телефонах обновляются часто и регулярно, Windows и Visual Studio тоже. Если вы не можете предоставлять достаточно частые обновления, вы рискуете потерять уважение и доверие ваших клиентов.
- Как службы Azure помогают осуществлять DevOps на практике?
- Службы Azure DevOps предоставляют интерфейс для планирования (создания резервных копий, отслеживания ошибок, управления спринтами, отслеживания прогресса), разработки (записи, тестирования, проверки и сборки) кода, доставки (выпуска для тестирования, подготовки, продакшена) и эксплуатации (мониторинга и устранения неполадок).
- Являются ли методы DevOps действительно важными для разработчиков?
- Я думаю, да. И несложно начать их использовать.
Источник: https://visualstudiomagazine.com/articles/2020/02/24/devops-qa.aspx
День триста девяносто седьмой. #DesignPatterns
Паттерны проектирования
14. Паттерн «Адаптер» (Adapter)
Адаптер является одним из тех паттернов проектирования, которые мы используем, почти не задумываясь. Диаграмма классов этого паттерна настолько общая, что практически любую композицию объектов можно считать примером использования адаптеров.
Назначение: преобразует интерфейс одного класса в интерфейс другого, который ожидают клиенты. Адаптер делает возможной совместную работу классов с несовместимыми интерфейсами.
Причины использования:
Далеко не все системы обладают прекрасным дизайном. Даже если модуль или приложение были хорошо продуманы изначально, внесение изменений разными разработчиками в течение длительного времени может привести к неприятным последствиям. Одно из таких последствий — рассогласованность реализации однотипных задач. Адаптер — это клей, который связывает воедино два мира путем подгонки текущих классов к требуемому интерфейсу.
Классическая диаграмма приведена на рисунке ниже:
-
-
-
-
Варианты применения:
- Повторное использование чужого кода. В некоторых случаях у нас уже есть код, который решает нужную задачу, но его интерфейс не подходит для текущего приложения. Вместо изменения кода библиотеки можно создать слой адаптеров.
- Адаптивный рефакторинг. Адаптеры позволяют плавно изменять существующую функциональность путем выделения нового «правильного» интерфейса, но с использованием старой проверенной функциональности.
Адаптивный рефакторинг
В некоторых случаях адаптеры могут упростить эволюцию дизайна и рефакторинг. Предположим, что у нас есть иерархия классов, которую мы хотим модифицировать. Можно переписать все классы иерархии, но можно пойти более итеративным путём:
1. Проектируем новый интерфейс с набором нужных методов.
2. Создаём первую реализацию (адаптер), которая реализует интерфейс, но делегирует все операции старой реализации.
3. Переводим клиентов иерархии на использование нового интерфейса и проверяем, что клиенты работают нормально.
4. Создаем полноценную новую реализацию.
5. Удаляем адаптер и старую иерархию за ненадобностью.
Преимущество такого подхода в том, что изменения происходят постепенно, а не одним большим скачком.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 12.
Паттерны проектирования
14. Паттерн «Адаптер» (Adapter)
Адаптер является одним из тех паттернов проектирования, которые мы используем, почти не задумываясь. Диаграмма классов этого паттерна настолько общая, что практически любую композицию объектов можно считать примером использования адаптеров.
Назначение: преобразует интерфейс одного класса в интерфейс другого, который ожидают клиенты. Адаптер делает возможной совместную работу классов с несовместимыми интерфейсами.
Причины использования:
Далеко не все системы обладают прекрасным дизайном. Даже если модуль или приложение были хорошо продуманы изначально, внесение изменений разными разработчиками в течение длительного времени может привести к неприятным последствиям. Одно из таких последствий — рассогласованность реализации однотипных задач. Адаптер — это клей, который связывает воедино два мира путем подгонки текущих классов к требуемому интерфейсу.
Классическая диаграмма приведена на рисунке ниже:
-
Target
— целевой интерфейс, к которому нужно преобразовать интерфейс существующих классов;-
Adaptee
— существующий класс, чей интерфейс нужно преобразовать;-
Adapter
— класс-адаптер, который преобразует интерфейс адаптируемого класса к целевому;-
Client
— клиенты нового интерфейса, которые работают с адаптированными классами полиморфным образом.Варианты применения:
- Повторное использование чужого кода. В некоторых случаях у нас уже есть код, который решает нужную задачу, но его интерфейс не подходит для текущего приложения. Вместо изменения кода библиотеки можно создать слой адаптеров.
- Адаптивный рефакторинг. Адаптеры позволяют плавно изменять существующую функциональность путем выделения нового «правильного» интерфейса, но с использованием старой проверенной функциональности.
Адаптивный рефакторинг
В некоторых случаях адаптеры могут упростить эволюцию дизайна и рефакторинг. Предположим, что у нас есть иерархия классов, которую мы хотим модифицировать. Можно переписать все классы иерархии, но можно пойти более итеративным путём:
1. Проектируем новый интерфейс с набором нужных методов.
2. Создаём первую реализацию (адаптер), которая реализует интерфейс, но делегирует все операции старой реализации.
3. Переводим клиентов иерархии на использование нового интерфейса и проверяем, что клиенты работают нормально.
4. Создаем полноценную новую реализацию.
5. Удаляем адаптер и старую иерархию за ненадобностью.
Преимущество такого подхода в том, что изменения происходят постепенно, а не одним большим скачком.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 12.
День триста девяносто восьмой. #Оффтоп
Сегодня хочу вам порекомендовать отличное видео выступления Билла Вагнера на NDC Conference в Лондоне в конце января. Тема выступления «Изменяйте ваши привычки: Современные техники в современном C#». Билл рассказывает о фишках последних версий языка C# и о том, как их можно использовать на практике, серьёзно сокращая код и упрощая его для понимания. Основные моменты выступления:
1. Использование кортежей для хранения связанных данных. Как кортежи могут упростить код небольшого класса.
2. Использование readonly членов и структур. Как яснее выразить свои намерения в коде и одновременно помочь компилятору создать более эффективный код.
3. Обнуляемые ссылочные типы. Как аннотации #nullable всё больше распространяются по коду в том числе стандартных библиотек, и как они помогают сокращать код и ловить самый распространённый вид ошибок –
4. Использование дискардов и продвинутого сопоставления с шаблоном. Также в некоторых случаях позволяет серьёзно сократить код.
Основные выводы из доклада:
- Используйте лучшие практики в своих приложениях.
- Когда код кажется слишком громоздким, поищите новые функции и рекомендации. Например, посмотрите более свежие ответы на stackoverflow, a не самые залайканные, которые могут быть 10-летней давности.
Бонус: рассмотрите советы Visual Studio, обозначенные лампочкой или отвёрткой.
ЗЫ: про английский не стоит напоминать, правда?)))
Источник: https://www.youtube.com/watch?v=aUbXGs7YTGo
Сегодня хочу вам порекомендовать отличное видео выступления Билла Вагнера на NDC Conference в Лондоне в конце января. Тема выступления «Изменяйте ваши привычки: Современные техники в современном C#». Билл рассказывает о фишках последних версий языка C# и о том, как их можно использовать на практике, серьёзно сокращая код и упрощая его для понимания. Основные моменты выступления:
1. Использование кортежей для хранения связанных данных. Как кортежи могут упростить код небольшого класса.
2. Использование readonly членов и структур. Как яснее выразить свои намерения в коде и одновременно помочь компилятору создать более эффективный код.
3. Обнуляемые ссылочные типы. Как аннотации #nullable всё больше распространяются по коду в том числе стандартных библиотек, и как они помогают сокращать код и ловить самый распространённый вид ошибок –
NullReferenceException
.4. Использование дискардов и продвинутого сопоставления с шаблоном. Также в некоторых случаях позволяет серьёзно сократить код.
Основные выводы из доклада:
- Используйте лучшие практики в своих приложениях.
- Когда код кажется слишком громоздким, поищите новые функции и рекомендации. Например, посмотрите более свежие ответы на stackoverflow, a не самые залайканные, которые могут быть 10-летней давности.
Бонус: рассмотрите советы Visual Studio, обозначенные лампочкой или отвёрткой.
ЗЫ: про английский не стоит напоминать, правда?)))
Источник: https://www.youtube.com/watch?v=aUbXGs7YTGo
День триста девяносто девятый. #АтакиНаСайты
ASP.NET MVC 5. Безопасность Веб-Приложений
2. Cross-Site Request Forgery (CSRF)
Подделка межсайтовых запросов (CSRF или XSRF) немного более сложная, чем XSS. Рассмотрим случай XSS + Confused Deputy. Проблема Confused Deputy заключается в подозрительном доверии приложений к принимаемым данным. Атаке подвергается ваш браузер, которого обманом заставляют представлять вас на удалённом веб-сайте.
Например, вы обнаружили уязвимость для XSS на «Популярном Сайте». Кроме того, допустим, что один «Крупный Банк» предлагает простой способ перевода денег онлайн с указанием параметров в URL:
Дальше немного социальной инженерии. Вы заходите на «Популярный Сайт» и оставляете пост:
Эй, а знаете ли вы, что у клиентов «Крупного Банка» сумма цифр номера счета равняется 30? Смотрите сами:
Фигасе, ты прав! Как странно!
Штука в том, чтобы заставить клиентов «Крупного Банка» войти в аккаунт и попытаться сложить цифры счёта. Когда они увидят, что это не работает, они возвращаются на «Популярный Сайт», чтобы снова прочитать пост или оставить гневный комментарий. К сожалению для «идеальной жертвы», её браузер все ещё хранит сеанс входа в онлайн-банк. Когда она попадает на страницу с атакой CSRF, запрос отправляется на веб-сайт банка (где личность жертвы установлена), и вуаля! - жертва лишилась денег.
Изображение в комментарии (со ссылкой CSRF) не будет отображено, и большинство людей будут думать, что это просто плохой аватар или смайлик. Но на самом деле, это удалённый вызов страницы.
Другой вариант: попытаться завлечь пользователя на страницу, внутри которой будет скрытый iframe, выполняющий аналогичный удалённый вызов (в том числе POST).
Предотвращение атак CSRF
1. Проверка токенов
Заключается в проверке того, что пользователь, отправивший данные на ваш сайт, сделал это добровольно. Самый простой способ сделать это – добавить скрытое поле с уникальным значением. Вы можете сделать это с помощью HTML помощника:
Вы можете предотвратить целый класс CSRF-атак, ограничив изменения на вашем сайте только запросами POST. Это включает регистрацию, вход/выход из системы и т.п. Подробнее о методах GET и POST.
3. Проверка HttpReferrer
Проверку HttpReferrer также можно реализовать с помощью создания фильтра метода действия:
ASP.NET MVC 5. Безопасность Веб-Приложений
2. Cross-Site Request Forgery (CSRF)
Подделка межсайтовых запросов (CSRF или XSRF) немного более сложная, чем XSS. Рассмотрим случай XSS + Confused Deputy. Проблема Confused Deputy заключается в подозрительном доверии приложений к принимаемым данным. Атаке подвергается ваш браузер, которого обманом заставляют представлять вас на удалённом веб-сайте.
Например, вы обнаружили уязвимость для XSS на «Популярном Сайте». Кроме того, допустим, что один «Крупный Банк» предлагает простой способ перевода денег онлайн с указанием параметров в URL:
https://bank.example.com?function=transfer&amount=1000&toaccount=23234554333&from=checkingЭто может показаться чрезвычайно глупым. Какой банк в здравом уме так сделает? К сожалению, ответ на этот вопрос: «тысячи их» (с). Причина довольно проста: веб-разработчики слишком сильно доверяют браузеру, а публичность URL-адреса основана на том, что запрос может выполняться «скрыто» через AJAX, а сервер будет проверять личность пользователя, используя информацию из cookie-файла сеанса.
Дальше немного социальной инженерии. Вы заходите на «Популярный Сайт» и оставляете пост:
Эй, а знаете ли вы, что у клиентов «Крупного Банка» сумма цифр номера счета равняется 30? Смотрите сами:
https://bank.example.com
Затем вы входите под другим аккаунтом, оставляя комментарий вроде:Фигасе, ты прав! Как странно!
<img src="https://bank.example.com?function=transfer&amount=1000&toaccount=23234554333&from=checking" />
.Штука в том, чтобы заставить клиентов «Крупного Банка» войти в аккаунт и попытаться сложить цифры счёта. Когда они увидят, что это не работает, они возвращаются на «Популярный Сайт», чтобы снова прочитать пост или оставить гневный комментарий. К сожалению для «идеальной жертвы», её браузер все ещё хранит сеанс входа в онлайн-банк. Когда она попадает на страницу с атакой CSRF, запрос отправляется на веб-сайт банка (где личность жертвы установлена), и вуаля! - жертва лишилась денег.
Изображение в комментарии (со ссылкой CSRF) не будет отображено, и большинство людей будут думать, что это просто плохой аватар или смайлик. Но на самом деле, это удалённый вызов страницы.
Другой вариант: попытаться завлечь пользователя на страницу, внутри которой будет скрытый iframe, выполняющий аналогичный удалённый вызов (в том числе POST).
Предотвращение атак CSRF
1. Проверка токенов
Заключается в проверке того, что пользователь, отправивший данные на ваш сайт, сделал это добровольно. Самый простой способ сделать это – добавить скрытое поле с уникальным значением. Вы можете сделать это с помощью HTML помощника:
@Html.AntiForgeryToken()Это добавит скрытое поле:
<input type="hidden" value="012837udny31w90hjhf7u" />То же значение сохраняется в сессии и проверяется в методе обработки формы с помощью фильтра метода действия:
[ValidateAntiforgeryToken]2. Идемпотентный GET
public ActionResult Register(…)
Вы можете предотвратить целый класс CSRF-атак, ограничив изменения на вашем сайте только запросами POST. Это включает регистрацию, вход/выход из системы и т.п. Подробнее о методах GET и POST.
3. Проверка HttpReferrer
Проверку HttpReferrer также можно реализовать с помощью создания фильтра метода действия:
public class IsPostedFromThisSiteAttribute : AuthorizeAttribute {Использование:
public override void OnAuthorize(AuthorizationContext filterContext) {
if (filterContext.HttpContext != null) {
if (filterContext.HttpContext.Request.UrlReferrer == null)
throw new System.Web.HttpException("Неверная отправка");
if (filterContext.HttpContext.Request.UrlReferrer.Host != "mysite.com")
throw new System.Web.HttpException("Форма отправлена не с этого сайта!");
}
}
}
[IsPostedFromThisSite]Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 7.
public ActionResult Register(…)
День четырёхсотый. #MoreEffectiveCSharp
5. Убедитесь, что 0 является допустимым состоянием для значимых типов
Инициализация по умолчанию в .NET устанавливает все значения в 0. Невозможно запретить другим программистам создавать экземпляр значимого типа со значениями по умолчанию. Сделайте 0 значением по умолчанию для типа.
Особый случай - перечисления. Никогда не создавайте перечисление, которое не содержит 0 в качестве допустимого значения:
Кроме того, это влияет на объекты, содержащие перечисление:
✅ По возможности выберите наилучшее значение по умолчанию для 0, либо добавьте специальное неинициализированное значение
✅ Для перечислений, являющихся битовыми флагами, убедитесь, что 0 является действительным значением и означает «отсутствие всех флагов». Подробнее о битовых флагах.
⚠️ Перечисления - лишь обёртка для набора целочисленных констант. Если это не обеспечивает нужную вам абстракцию, следует рассмотреть возможность использования другой конструкции языка.
Другая распространённая проблема состоит в инициализации ссылочных полей структур:
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 5.
5. Убедитесь, что 0 является допустимым состоянием для значимых типов
Инициализация по умолчанию в .NET устанавливает все значения в 0. Невозможно запретить другим программистам создавать экземпляр значимого типа со значениями по умолчанию. Сделайте 0 значением по умолчанию для типа.
Особый случай - перечисления. Никогда не создавайте перечисление, которое не содержит 0 в качестве допустимого значения:
public enum PlanetИ
{
// Явно назначенные значения
// По умолчанию начинаются с 0
Mercury = 1,
Venus = 2,
Earth = 3,
…
}
Planet sphere = new Planet();
var anotherSphere = default(Planet);
sphere
, и anotherSphere
имеют значение 0, которое не является допустимым. Любой код, предполагающий, что перечисления ограничены определённым набором значений, возможно, будет работать неверно. Кроме того, это влияет на объекты, содержащие перечисление:
public struct PlanetData
{
private Planet planet;
private double magnitude; //яркость
}
var data = new PlanetData();
data
имеет яркость 0, что нормально, но значение планеты недопустимое.✅ По возможности выберите наилучшее значение по умолчанию для 0, либо добавьте специальное неинициализированное значение
None = 0
, которое можно будет изменить позже.✅ Для перечислений, являющихся битовыми флагами, убедитесь, что 0 является действительным значением и означает «отсутствие всех флагов». Подробнее о битовых флагах.
⚠️ Перечисления - лишь обёртка для набора целочисленных констант. Если это не обеспечивает нужную вам абстракцию, следует рассмотреть возможность использования другой конструкции языка.
Другая распространённая проблема состоит в инициализации ссылочных полей структур:
public struct LogMessage
{
public int ErrLevel;
public string Message;
}
LogMessage myMsg = new LogMessage();
myMsg
содержит null
в поле Message
. Невозможно принудительно инициировать поле другим значением, но можно локализовать проблему, используя свойства. Добавьте логику в свойство, чтобы возвращать пустую строку вместо null
:public struct LogMessageИспользуйте свойство и в коде типа. Это позволит локализовать проверку на
{
public int ErrLevel;
private string msg;
public string Message
{
get => msg ?? string.Empty;
set => msg = value;
}
}
null
в одном месте. Аксессор свойства почти наверняка будет встроен при компиляции, поэтому вы получите эффективный код и сведёте к минимуму ошибки.Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 5.
День четыреста первый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
29. Не надейтесь на магию
Если вы наблюдаете за какой-то деятельностью или процессом со стороны, может показаться, что всё просто. Менеджеры без опыта разработки думают, что программировать просто, а программисты без опыта управления так же думают о работе менеджеров.
Самая сложная часть программирования - размышления - наименее заметна и меньше всего ценится непосвященными. За десятилетия разработки было много попыток убрать из процесса потребность в этом особом мышлении. Одной из самых ранних и запоминающихся является попытка Грейс Хоппер создать более понятный язык программирования, что, по мнению некоторых, должно было вообще снять потребность в специальности «Программист». Результат (язык COBOL) внёс существенный вклад в привлечение в отрасль новых программистов в последующие десятилетия.
Настойчивые попытки упростить разработку ПО так, чтобы вообще сделать программистов ненужными, для тех программистов, кто понимает, что из себя представляет процесс на самом деле, кажутся весьма наивными. Но мыслительный процесс, приводящий к таким ошибочным суждениям, является частью человеческой природы, и программисты склонны рассуждать так же, как и все остальные.
В любом проекте, вероятно, есть много вещей, в которых отдельный программист не принимает непосредственного участия: формирование требований, утверждение бюджета, настройка сервера сборки, развёртывание для тестирования и сдача в эксплуатацию, миграция из старых бизнес-процессов или программных сред в новые и т. д.
Когда вы не принимаете активного участия в каком-то процессе, вы бессознательно предполагаете, что он прост и происходит «по волшебству». Пока «магия» работает, всё хорошо. Но когда (именно «когда», а не «если») магия прекращается, вот тут и начинаются проблемы.
Я видел, как проект терял недели разработки, потому что никто не понимал, насколько он зависим от «правильной» версии подгружаемой DLL. Когда начались проблемы, члены команды искали проблемы везде, прежде чем кто-то заметил, что загружается «неправильная» версия DLL.
Другой пример – отдел, который прекрасно работал: проекты выполнялись вовремя, никаких ночных сессий экстренной отладки, никаких срочных исправлений. Он работал настолько гладко, что высшее руководство решило, что всё просто работает само по себе, и отдел может обойтись без менеджера проекта. В течение полугода отдел стал такими же, как и остальные отделы компании: задержки, ошибки, экстренные исправления…
Вам не нужно понимать всю магию, которая заставляет ваш проект работать, но неплохо было бы разбираться хотя бы в некоторой её части и ценить тех, кто понимает то, чего не понимаете вы.
Самое главное, убедитесь, что, когда магия перестанет работать, кто-то знает, как «включить» её обратно.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Alan Griffiths
97 Вещей, Которые Должен Знать Каждый Программист
29. Не надейтесь на магию
Если вы наблюдаете за какой-то деятельностью или процессом со стороны, может показаться, что всё просто. Менеджеры без опыта разработки думают, что программировать просто, а программисты без опыта управления так же думают о работе менеджеров.
Самая сложная часть программирования - размышления - наименее заметна и меньше всего ценится непосвященными. За десятилетия разработки было много попыток убрать из процесса потребность в этом особом мышлении. Одной из самых ранних и запоминающихся является попытка Грейс Хоппер создать более понятный язык программирования, что, по мнению некоторых, должно было вообще снять потребность в специальности «Программист». Результат (язык COBOL) внёс существенный вклад в привлечение в отрасль новых программистов в последующие десятилетия.
Настойчивые попытки упростить разработку ПО так, чтобы вообще сделать программистов ненужными, для тех программистов, кто понимает, что из себя представляет процесс на самом деле, кажутся весьма наивными. Но мыслительный процесс, приводящий к таким ошибочным суждениям, является частью человеческой природы, и программисты склонны рассуждать так же, как и все остальные.
В любом проекте, вероятно, есть много вещей, в которых отдельный программист не принимает непосредственного участия: формирование требований, утверждение бюджета, настройка сервера сборки, развёртывание для тестирования и сдача в эксплуатацию, миграция из старых бизнес-процессов или программных сред в новые и т. д.
Когда вы не принимаете активного участия в каком-то процессе, вы бессознательно предполагаете, что он прост и происходит «по волшебству». Пока «магия» работает, всё хорошо. Но когда (именно «когда», а не «если») магия прекращается, вот тут и начинаются проблемы.
Я видел, как проект терял недели разработки, потому что никто не понимал, насколько он зависим от «правильной» версии подгружаемой DLL. Когда начались проблемы, члены команды искали проблемы везде, прежде чем кто-то заметил, что загружается «неправильная» версия DLL.
Другой пример – отдел, который прекрасно работал: проекты выполнялись вовремя, никаких ночных сессий экстренной отладки, никаких срочных исправлений. Он работал настолько гладко, что высшее руководство решило, что всё просто работает само по себе, и отдел может обойтись без менеджера проекта. В течение полугода отдел стал такими же, как и остальные отделы компании: задержки, ошибки, экстренные исправления…
Вам не нужно понимать всю магию, которая заставляет ваш проект работать, но неплохо было бы разбираться хотя бы в некоторой её части и ценить тех, кто понимает то, чего не понимаете вы.
Самое главное, убедитесь, что, когда магия перестанет работать, кто-то знает, как «включить» её обратно.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Alan Griffiths
День четыреста второй. #DesignPatterns
Паттерны проектирования
15. Паттерн «Фасад» (Facade)
В большинстве приложений используется лишь часть функциональности сложной подсистемы. Паттерн «Фасад» позволяет сделать более простой интерфейс общения с ней, который максимально подходит для специфических сценариев приложения.
Назначение: предоставляет унифицированный интерфейс вместо набора интерфейсов некоторой подсистемы. Фасад определяет интерфейс более высокого уровня, который упрощает использование подсистемы.
Причины использования:
Библиотеки классов обычно предназначены для решения целого спектра задач. С помощью ADO.NET можно выполнять простые команды на стороне базы данных, а можно использовать транзакции и выходные (output) параметры хранимых процедур. Наличие сложных сценариев делает библиотеку полезной, но это же может усложнить решение с её помощью простых задач. Это приводит к появлению различных оболочек, упрощающих решение простых задач, или реализацию сценариев, специфичных для конкретного приложения. Такие оболочки являются фасадами, которые скрывают исходную сложность библиотеки или модуля за более простым и, возможно, специфичным для приложения интерфейсом.
Классическая диаграмма приведена на рисунке ниже:
-
-
Преимущества
- Инкапсуляция работы со сложной библиотекой в одном месте позволяет корректно использовать её всеми разработчиками независимо от их опыта.
- При выходе новой версии библиотеки достаточно протестировать лишь фасад.
- Благодаря фасаду приложение не так сильно завязано на библиотеку, так что переход на другую библиотеку потребует лишь создание еще одного фасада.
Многие библиотеки или подсистемы приложений содержат встроенные фасады, которые являются высокоуровневыми классами, предназначенными для решения типовых операций. Если клиенту нужна лишь базовая функциональность, достаточно воспользоваться фасадом; если её недостаточно, можно использовать более низкоуровневые классы модуля или библиотеки напрямую.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 13.
Паттерны проектирования
15. Паттерн «Фасад» (Facade)
В большинстве приложений используется лишь часть функциональности сложной подсистемы. Паттерн «Фасад» позволяет сделать более простой интерфейс общения с ней, который максимально подходит для специфических сценариев приложения.
Назначение: предоставляет унифицированный интерфейс вместо набора интерфейсов некоторой подсистемы. Фасад определяет интерфейс более высокого уровня, который упрощает использование подсистемы.
Причины использования:
Библиотеки классов обычно предназначены для решения целого спектра задач. С помощью ADO.NET можно выполнять простые команды на стороне базы данных, а можно использовать транзакции и выходные (output) параметры хранимых процедур. Наличие сложных сценариев делает библиотеку полезной, но это же может усложнить решение с её помощью простых задач. Это приводит к появлению различных оболочек, упрощающих решение простых задач, или реализацию сценариев, специфичных для конкретного приложения. Такие оболочки являются фасадами, которые скрывают исходную сложность библиотеки или модуля за более простым и, возможно, специфичным для приложения интерфейсом.
Классическая диаграмма приведена на рисунке ниже:
-
Facade
— фасадный класс прячет детали реализации подсистемы от клиентов;-
Client
— клиент работает с фасадом, а не с классами подсистемы.Преимущества
- Инкапсуляция работы со сложной библиотекой в одном месте позволяет корректно использовать её всеми разработчиками независимо от их опыта.
- При выходе новой версии библиотеки достаточно протестировать лишь фасад.
- Благодаря фасаду приложение не так сильно завязано на библиотеку, так что переход на другую библиотеку потребует лишь создание еще одного фасада.
Многие библиотеки или подсистемы приложений содержат встроенные фасады, которые являются высокоуровневыми классами, предназначенными для решения типовых операций. Если клиенту нужна лишь базовая функциональность, достаточно воспользоваться фасадом; если её недостаточно, можно использовать более низкоуровневые классы модуля или библиотеки напрямую.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 13.