День триста семьдесят седьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
25. Не Шутите с Тестовыми Данными
Было уже поздно. Я добавлял тестовые данные для проверки макета страницы, над которой я работал. Я задал в качестве имён пользователей состав группы The Clash. Названия компаний? Подойдут песни Sex Pistols. Теперь мне нужны были некоторые четырёхбуквенные биржевые аббревиатуры. Да, я использовал те самые слова (основные ругательства в английском состоят из 4х букв). Это казалось безобидным. Просто мелочь, чтобы развлечь себя и, возможно, других разработчиков на следующий день, прежде чем я подключу реальный источник данных. На следующее утро менеджер проекта сделал несколько скриншотов для презентации…
История программирования изобилует такими историями. Вещи, которые разработчики и дизайнеры делали по принципу «никто же больше не увидит», неожиданно всплывают на всеобщее обозрение.
Тип утечки может варьироваться, но, когда это происходит, он может быть смертельным для человека, команды или компании. Примеров масса:
- Во время статусной встречи клиент нажимает на кнопку, которая пока не реализована. Выскакивает сообщение: «Не нажимай сюда, придурок».
- Программисту, обслуживающему унаследованную систему, даётся задание добавить диалоговое окно с сообщением об ошибке, и он решает использовать выходные данные существующей внутренней логики. Пользователи внезапно сталкиваются с сообщениями типа «Хьюстон, у нас проблемы!», когда что-то идёт не так.
- Кто-то перепутал реальную и тестовую админку и добавил «забавные» данные. Внезапно в интернет-магазине в продаже появляется «Персональный массажёр в форме Билла Гейтса» за $1 млн.
Есть старая поговорка: «Ложь может обойти полмира пока правда будет надевать ботинки». В наше время новость о вашей ошибке успеют обсудить в Facebook, Twitter и Одноклассниках, прежде чем вы очухаетесь и исправите её.
Даже ваш исходный код не обязательно всегда будет скрыт. В 2004 году, когда архив с исходным кодом Windows 2000 появился в общем доступе, многих развеселило обилие ненормативной лексики, оскорблений и других интересных комментариев. С тех пор я нет-нет, да использую, ставший мемом, комментарий:
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Rod Begbie
97 Вещей, Которые Должен Знать Каждый Программист
25. Не Шутите с Тестовыми Данными
Было уже поздно. Я добавлял тестовые данные для проверки макета страницы, над которой я работал. Я задал в качестве имён пользователей состав группы The Clash. Названия компаний? Подойдут песни Sex Pistols. Теперь мне нужны были некоторые четырёхбуквенные биржевые аббревиатуры. Да, я использовал те самые слова (основные ругательства в английском состоят из 4х букв). Это казалось безобидным. Просто мелочь, чтобы развлечь себя и, возможно, других разработчиков на следующий день, прежде чем я подключу реальный источник данных. На следующее утро менеджер проекта сделал несколько скриншотов для презентации…
История программирования изобилует такими историями. Вещи, которые разработчики и дизайнеры делали по принципу «никто же больше не увидит», неожиданно всплывают на всеобщее обозрение.
Тип утечки может варьироваться, но, когда это происходит, он может быть смертельным для человека, команды или компании. Примеров масса:
- Во время статусной встречи клиент нажимает на кнопку, которая пока не реализована. Выскакивает сообщение: «Не нажимай сюда, придурок».
- Программисту, обслуживающему унаследованную систему, даётся задание добавить диалоговое окно с сообщением об ошибке, и он решает использовать выходные данные существующей внутренней логики. Пользователи внезапно сталкиваются с сообщениями типа «Хьюстон, у нас проблемы!», когда что-то идёт не так.
- Кто-то перепутал реальную и тестовую админку и добавил «забавные» данные. Внезапно в интернет-магазине в продаже появляется «Персональный массажёр в форме Билла Гейтса» за $1 млн.
Есть старая поговорка: «Ложь может обойти полмира пока правда будет надевать ботинки». В наше время новость о вашей ошибке успеют обсудить в Facebook, Twitter и Одноклассниках, прежде чем вы очухаетесь и исправите её.
Даже ваш исходный код не обязательно всегда будет скрыт. В 2004 году, когда архив с исходным кодом Windows 2000 появился в общем доступе, многих развеселило обилие ненормативной лексики, оскорблений и других интересных комментариев. С тех пор я нет-нет, да использую, ставший мемом, комментарий:
// МЕРЗКИЙ, УЖАСНЫЙ, ОЧЕНЬ ПЛОХОЙ ХАКПоэтому при написании любого текста в вашем коде - будь то комментарии, логи, сообщения или тестовые данные - всегда спрашивайте себя, как он будет выглядеть, если он станет общедоступным. Возможно, это спасёт вас от неловких ситуаций в будущем.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Rod Begbie
День триста семьдесят восьмой. #ЗаметкиНаПолях
ASP.NET MVC 5.
Аннотации и Валидация Данных. Начало
Когда мы говорим о проверке в контексте MVC, мы в первую очередь имеем в виду проверку значений модели. Функции валидации в ASP.NET MVC помогают в этом. Они являются расширяемыми: вы можете создавать собственные схемы проверки, но чаще используется декларативный стиль проверки, известный как аннотации данных.
Аннотации данных - это атрибуты в основном из пространства имен
Основные атрибуты валидации данных
Required – обязательное поле:
Display – «дружелюбное» к пользователю имя свойства для отображения:
ReadOnly – запрещает связывателю модели изменять значение свойства, но
ASP.NET MVC 5.
Аннотации и Валидация Данных. Начало
Когда мы говорим о проверке в контексте MVC, мы в первую очередь имеем в виду проверку значений модели. Функции валидации в ASP.NET MVC помогают в этом. Они являются расширяемыми: вы можете создавать собственные схемы проверки, но чаще используется декларативный стиль проверки, известный как аннотации данных.
Аннотации данных - это атрибуты в основном из пространства имен
System.ComponentModel.DataAnnotations
, которыми помечаются свойства модели. Это обеспечивает проверку на стороне сервера, но платформа также поддерживает проверку на стороне клиента. Большинство атрибутов валидации имеют необязательный параметр ErrorMessage
, хранящий сообщение об ошибке, которое получит пользователь.Основные атрибуты валидации данных
Required – обязательное поле:
[Required(ErrorMessage="Пожалуйста, введите имя")]Range – диапазон допустимых значений. Граничные значения включаются. Перегруженная версия принимает тип и две строки, что позволяет задать числа с точкой или даты:
[Range(100,500,ErrorMessage="Введите корректное число")]StringLength – максимальная (необязательно – минимальная) длина строки:
[Range(typeof(decimal), "0.00", "49.99")]
[StringLength(30, MinimumLength=3)]RegularExpression – регулярное выражение для проверки, например, e-mail адреса:
[RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$")]Compare – принимает имя другого свойства модели и проверяет значения на равенство (например, для проверки равенства введённых паролей при регистрации):
[Compare("Password")]Remote – позволяет выполнять валидацию на стороне клиента при помощи обратного вызова на сервер. Принимает имя метода действия и контроллера:
[Remote("CheckUserName", "Account")]Следующие аннотации позволяют помощникам HTML
EditorFor
или LabelFor
правильно отображать свойства модели в представлении:Display – «дружелюбное» к пользователю имя свойства для отображения:
[Display(Name="Название")]DataType – тип данных для отображения:
[DataType(DataType.Text)]DisplayFormat – формат данных для отображения:
[DisplayFormat(DataFormatString = "{0:dd.MM.yyyy}")]HiddenInput – сообщает, что это свойство нужно отобразить как скрытое поле.
ReadOnly – запрещает связывателю модели изменять значение свойства, но
EditorForModel
всё равно отобразит свойство как поле для ввода:[ReadOnly(true)]ScaffoldColumn – скрывает свойство от HTML помощников
EditorForModel
и DisplayForModel
. Однако, связыватель модели всё равно постарается задать ему значение, если найдёт соответствующий параметр в запросе.[ScaffoldColumn(false)]Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 6.
👍1
День триста семьдесят девятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
Аннотации и Валидация Данных. Окончание
Кастомизация и Локализация Сообщений об Ошибке
Сообщение об ошибке может содержать один параметр формата. По умолчанию он будет заменён на дружелюбное название свойства модели:
В мультиязычных приложениях, жёстко закодированные сообщения об ошибках – плохая идея. Атрибуты валидации позволяют отображать разный текст для разных языков:
Пользовательская валидация через аннотации
Включение логики валидации в пользовательскую аннотацию данных позволяет легко повторно использовать эту логику в нескольких моделях. Конечно, при этом код валидации должен быть универсален для работы с различными типами моделей.
Все атрибуты валидации данных происходят из базового класса
1. Обязательный параметр
3. В класс атрибута можно добавлять открытые свойства. Они станут необязательными параметрами атрибута. Их значение можно задавать по имени. Например, можно Заменить сообщение об ошибке:
В случае успеха валидации возвращается специальное статическое значение
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 6.
ASP.NET MVC 5.
Аннотации и Валидация Данных. Окончание
Кастомизация и Локализация Сообщений об Ошибке
Сообщение об ошибке может содержать один параметр формата. По умолчанию он будет заменён на дружелюбное название свойства модели:
[Display(Name="Фамилия")]В этом случае, если пользователь оставит поле пустым, то он получит сообщение об ошибке: «
[Required(ErrorMessage="Заполните поле {0}")]
public string LastName { get; set; }
Заполните поле Фамилия
».В мультиязычных приложениях, жёстко закодированные сообщения об ошибках – плохая идея. Атрибуты валидации позволяют отображать разный текст для разных языков:
[Required(Здесь предполагается, что в проекте есть файл ресурсов именем
ErrorMessageResourceType=typeof(ErrorMessages),
ErrorMessageResourceName="LastNameRequired")]
public string LastName { get; set; }
ErrorMessages.resx
и с соответствующей записью LastNameRequired
.Пользовательская валидация через аннотации
Включение логики валидации в пользовательскую аннотацию данных позволяет легко повторно использовать эту логику в нескольких моделях. Конечно, при этом код валидации должен быть универсален для работы с различными типами моделей.
Все атрибуты валидации данных происходят из базового класса
System.ComponentModel.DataAnnotations.ValidationAttribute
. Поэтому для создания пользовательского атрибута валидации нужно унаследовать от класса ValidationAttribute
. Допустим, мы хотим проверять количество слов в свойстве модели, задавая максимальное значение параметром:public class MaxWordsAttribute : ValidationAttribute {В конструкторе атрибута можно отметить три вещи:
private readonly int _maxWords;
public MaxWordsAttribute(int maxWords)
: base("В поле {0} слишком много слов.") {
_maxWords = maxWords;
}
…
}
1. Обязательный параметр
maxWords
передаётся в конструктор, поэтому атрибут можно вызывать, не указывая имя этого параметра:[MaxWords(10)]2. Вызывается конструктор базового класса, которому передаётся сообщение об ошибке по умолчанию.
3. В класс атрибута можно добавлять открытые свойства. Они станут необязательными параметрами атрибута. Их значение можно задавать по имени. Например, можно Заменить сообщение об ошибке:
[MaxWords(10, ErrorMessage="Слов слишком много")]Кроме этого, нужно переопределить свойство
IsValid
, которое возвращает результат валидации. Первый параметр – значение свойства, а второй – контекст валидации, который позволяет получить доступ к проверяемому объекту:protected override ValidationResult IsValid(object value, ValidationContext validationContext) {Здесь мы делаем довольно наивную проверку количества слов, и в случае неудачи возвращаем объект
if (value != null) {
var len = value.ToString().Split(' ').Length;
if (len > _maxWords) {
var errorMessage = FormatErrorMessage(
validationContext.DisplayName);
return new ValidationResult(errorMessage);
}
}
return ValidationResult.Success;
}
ValidationResult
с сообщением об ошибке. Метод FormatErrorMessage
базового класса ValidationAttribute
принимает строковый параметр для подстановки. Мы передаём в него «дружелюбное» имя поля. В случае успеха валидации возвращается специальное статическое значение
ValidationResult.Success
.Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 6.
День триста восьмидесятый. #MoreEffectiveCSharp
Нашёл ещё одну интересную книгу. “More Effective C#” Билла Уагнера. 50 советов по эффективному использованию языка C#. Буду приводить выдержки по мере прочтения. Начнём с простого.
1. Используйте свойства для доступа к данным
Свойства всегда были особенностью языка C#. Несколько улучшений с первого выпуска языка C# сделали их ещё более выразительными. Свойства - это элементы языка, доступ к которым осуществляется так, как будто они являются элементами данных, но реализованы они как методы.
Преимущества использования свойств:
1. Упрощение валидации данных. При использовании свойств валидация локализована в методах-акцессорах.
2. Библиотеки привязки данных (WPF, Windows Forms, веб-формы, привязка модели в MVC и т.п.) предполагают, что вы будете использовать свойства для публичных членов данных. Привязка не будет работать с публичным полем. Публичные поля являются плохой практикой, поэтому привязка к ним не была добавлена создателями FCL.
3. Поскольку свойства реализованы с помощью методов, упрощается многопоточный доступ. Вы можете обеспечить синхронизированный доступ к данным в методах акцессорах:
Особенности
Свойства - это методы, к которым вызывающий код обращается как к данным. Вследствие этого пользователи свойств возлагают на них определённые ожидания:
- Аксессоры (
- Доступ к свойству не должен значительно отличаться по производительности от простого доступа к данным. Средства доступа к свойствам не должны выполнять длительных вычислений, вызовов между приложениями (например, запросов к базе данных) или других длительных операций, которые не соответствуют ожиданиям ваших пользователей в отношении средства доступа к данным.
Другие советы по разработке свойств.
Подробно об эволюции свойств в C# в докладе Александра Шведова на DotNext 2015.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 1.
Нашёл ещё одну интересную книгу. “More Effective C#” Билла Уагнера. 50 советов по эффективному использованию языка C#. Буду приводить выдержки по мере прочтения. Начнём с простого.
1. Используйте свойства для доступа к данным
Свойства всегда были особенностью языка C#. Несколько улучшений с первого выпуска языка C# сделали их ещё более выразительными. Свойства - это элементы языка, доступ к которым осуществляется так, как будто они являются элементами данных, но реализованы они как методы.
Преимущества использования свойств:
1. Упрощение валидации данных. При использовании свойств валидация локализована в методах-акцессорах.
2. Библиотеки привязки данных (WPF, Windows Forms, веб-формы, привязка модели в MVC и т.п.) предполагают, что вы будете использовать свойства для публичных членов данных. Привязка не будет работать с публичным полем. Публичные поля являются плохой практикой, поэтому привязка к ним не была добавлена создателями FCL.
3. Поскольку свойства реализованы с помощью методов, упрощается многопоточный доступ. Вы можете обеспечить синхронизированный доступ к данным в методах акцессорах:
private object syncHandle = new object();4. Средства доступа к свойству - это два отдельных метода. Вы можете указать различные модификаторы для методов доступа
private string name;
public string Name {
get {
lock (syncHandle)
return name;
}
set {
lock (syncHandle)
name = value;
}
}
get
и set
. Это даёт вам ещё больший контроль над видимостью элементов данных, доступ к которым реализован через свойства:public virtual string Name5. Глядя на IL-код свойства, возникает вопрос о производительности свойств относительно доступа к полям напрямую. Свойства не будут быстрее, но они могут быть не медленнее. JIT-компилятор встраивает некоторые вызовы методов, включая методы доступа свойств. Когда JIT-компилятор встраивает метод, производительность свойства и доступа к полю напрямую одинакова. Но даже в противном случае разница в производительности незначительна.
{
get;
protected set;
}
Особенности
Свойства - это методы, к которым вызывающий код обращается как к данным. Вследствие этого пользователи свойств возлагают на них определённые ожидания:
- Аксессоры (
get
) свойств не должны иметь побочных эффектов (изменять состояние). Мутаторы (set
) свойств, с другой стороны, должны изменять состояние, и пользователи должны видеть эти изменения.- Доступ к свойству не должен значительно отличаться по производительности от простого доступа к данным. Средства доступа к свойствам не должны выполнять длительных вычислений, вызовов между приложениями (например, запросов к базе данных) или других длительных операций, которые не соответствуют ожиданиям ваших пользователей в отношении средства доступа к данным.
Другие советы по разработке свойств.
Подробно об эволюции свойств в C# в докладе Александра Шведова на DotNext 2015.
Источник: Bill Wagner “More Effective C#”. – 2nd ed. Глава 1.
День триста восемьдесят первый. #Оффтоп
DDD – многие знают, что расшифровывается эта аббревиатура как Domain Driven Design. Но очень немногие знают, что это значит и как его применять. Недавно прошёл очередной митап Райффайзен Банка, на котором докладчики попытались хотя бы в общих чертах рассказать, что из себя представляет «Разработка, Направляемая Предметной Областью» и с чем её едят.
Информация скорее для тимлидов и руководителей ИТ отделов. Но, в принципе, и для обычных разработчиков вполне интересное и полезное видео для общего развития, и, что редкость, на русском. Поэтому, если у вас есть 2,5 часа свободного времени, советую посмотреть https://youtu.be/WwRXloRVh74
DDD – многие знают, что расшифровывается эта аббревиатура как Domain Driven Design. Но очень немногие знают, что это значит и как его применять. Недавно прошёл очередной митап Райффайзен Банка, на котором докладчики попытались хотя бы в общих чертах рассказать, что из себя представляет «Разработка, Направляемая Предметной Областью» и с чем её едят.
Информация скорее для тимлидов и руководителей ИТ отделов. Но, в принципе, и для обычных разработчиков вполне интересное и полезное видео для общего развития, и, что редкость, на русском. Поэтому, если у вас есть 2,5 часа свободного времени, советую посмотреть https://youtu.be/WwRXloRVh74
День триста восемьдесят второй. #DesignPatterns
Паттерны проектирования
12. Паттерн «Фабричный метод» (Factory Method). Продолжение
Обобщённый фабричный метод
Существует распространённая проблема: как гарантировать вызов виртуального метода при конструировании любого объекта некоторой иерархии типов? Вызов виртуального метода в конструкторе базового класса не подходит: в языке C# это может привести к непредсказуемому поведению, так как будет вызван метод наследника, конструктор которого еще не отработал.
В этом случае можно воспользоваться фабрикой, которая вызовет виртуальный метод после создания экземпляра. Использование фабрик для выполнения обязательных действий после создания объекта является довольно распространенным подходом. Для решения этой задачи в C# нам понадобятся обобщения, рефлексия и немного магии для корректного пробрасывания исключений.
Примечание: далее я приведу код из книги Теплякова с небольшими своими доработками, которые позже поясню.
Допустим, у нас есть следующая иерархия типов:
1. Предполагалось использовать
2. Изначально предполагалось использовать в фабрике конструкцию:
В общем, вот такой получился «костыль». Спасибо участнику чата @fjod10199 за обнаружение проблемы в коде книги.
Если у вас есть предложения по улучшению этого кода, добро пожаловать в наш чат.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 10.
Паттерны проектирования
12. Паттерн «Фабричный метод» (Factory Method). Продолжение
Обобщённый фабричный метод
Существует распространённая проблема: как гарантировать вызов виртуального метода при конструировании любого объекта некоторой иерархии типов? Вызов виртуального метода в конструкторе базового класса не подходит: в языке C# это может привести к непредсказуемому поведению, так как будет вызван метод наследника, конструктор которого еще не отработал.
В этом случае можно воспользоваться фабрикой, которая вызовет виртуальный метод после создания экземпляра. Использование фабрик для выполнения обязательных действий после создания объекта является довольно распространенным подходом. Для решения этой задачи в C# нам понадобятся обобщения, рефлексия и немного магии для корректного пробрасывания исключений.
Примечание: далее я приведу код из книги Теплякова с небольшими своими доработками, которые позже поясню.
Допустим, у нас есть следующая иерархия типов:
public abstract class Product {Поскольку мы не можем вызвать конструктор напрямую, создаём фабрику, объектов типа:
protected internal abstract void PostConstruction();
}
public class ConcreteProduct : Product {
// Закрытый конструктор не позволит клиентам
// создавать объекты напрямую
private ConcreteProduct() =>
Console.WriteLine("конструктор");
protected internal override void PostConstruction() =>
Console.WriteLine("метод PostConstruction");
}
public static class ProductFactory {Использование:
public static T Create<T>() where T : Product {
try {
// создаём объект через рефлексию
T t = (T)Activator.CreateInstance(typeof(T), true);
// Вызываем постобработку
t.PostConstruction();
return t;
}
catch (TargetInvocationException e) {
// «разворачиваем» исключение и бросаем исходное
var edi = ExceptionDispatchInfo.Capture(e.InnerException);
edi.Throw();
// эта точка недостижима, но компилятор об этом не знает!
return default(T);
}
}
}
var p = ProductFactory.Create<ConcreteProduct>();Итак, в чём отличия от кода в книге:
1. Предполагалось использовать
internal
конструктор и разместить фабрику в той же сборке, чтобы она могла спокойно вызывать его. Проблема здесь в том, что весь код в этой сборке также сможет вызывать конструктор напрямуюvar p2 = new ConcreteProduct();и тем самым нарушать требование обязательного вызова метода
PostConstruction
.2. Изначально предполагалось использовать в фабрике конструкцию:
var t = new T();вместо рефлексии Activator.CreateInstance. Проблема в том, что это требует добавление ограничения
new()
в обобщённый метод Create<T>
фабрики. А такой код не скомпилируется, если у класса нет открытого конструктора.В общем, вот такой получился «костыль». Спасибо участнику чата @fjod10199 за обнаружение проблемы в коде книги.
Если у вас есть предложения по улучшению этого кода, добро пожаловать в наш чат.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 10.
День триста восемьдесят третий. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
26. Не игнорируйте эту ошибку!
Однажды вечером я шел по улице, чтобы встретиться с друзьями в баре. Мы давно не виделись, и я с нетерпением ждал встречи с ними снова. В спешке я не смотрел, куда иду. Я споткнулся о край бордюра и упал. Так мне и надо, я не следил за дорогой. У меня болела нога, но я спешил на встречу с друзьями. Я поднялся и пошёл дальше. Боль усиливалась. Хотя я изначально проигнорировал её, я быстро понял, что что-то не так.
Но я всё равно поспешил в бар. Но весь вечер пошёл насмарку, потому что меня беспокоила нога. Утром я пошёл к врачу и узнал, что у меня сложный перелом голени. Если бы я остановился, когда почувствовал боль, проблем было бы гораздо меньше. Ходьба со сломанной ногой ни к чему хорошему не приводит.
Слишком многие программисты пишут код по тому же принципу.
«Ошибка, какая ошибка? Да, это ерунда. Серьёзно. Можно не обращать внимания.» Это проигрышная стратегия в отношении вашего кода. На самом деле это просто лень (неконструктивная лень). Независимо от того, насколько, по-вашему, маловероятно, что в вашем коде будет ошибка, вы всегда должны предполагать её наличие и обрабатывать её. Всегда. Вы не сэкономите время, если не сделаете этого; вы только будете накапливать потенциальные проблемы на будущее.
Можно сообщать об ошибках в нашем коде несколькими способами, но лучший из них – исключения. Это структурированный, поддерживаемый языком способ сигнализации и обработки ошибок. И вы не сможете проигнорировать их. Или сможете? Я видел много такого кода:
Если вы игнорируете ошибку, закрываете глаза и делаете вид, что ничего не случилось, вы рискуете. Так же, как моя нога пострадала гораздо сильнее, чем если бы я сразу же перестал наступать на неё. Если вы гоните по дороге, игнорируя знаки, ничем хорошим это не закончится. Разбирайтесь с проблемами при первой возможности.
Игнорирование ошибок приводит к:
- Ненадёжному коду, то есть коду, наполненному трудноуловимыми и сложными для исправления ошибками.
- Небезопасному коду. Взломщики часто используют плохую обработку ошибок для взлома программных систем.
- Плохо структурированному коду. Если аккуратная обработка ошибок слишком муторна, скорее всего, это результат плохо продуманного интерфейса. Переделайте его так, чтобы обрабатывать ошибки было не так обременительно.
Точно так же, как вы должны проверять все потенциальные ошибки в вашем коде, нужно делать очевидными для пользователей все возможные ошибочные состояния в ваших интерфейсах. Не скрывайте их, рассчитывая на то, что вашим кодом всегда будут правильно пользоваться.
Почему мы не проверяем код на ошибки? Есть несколько стандартных оправданий. С какими из них вы согласны? Что бы вы возразили на это?
- Обработка ошибок загромождает код, затрудняя его чтение и поиск «нормального» потока выполнения.
- Это дополнительная работа, а у меня дедлайн.
- Я знаю, что вызов этой стандартной функции никогда не вернёт ошибку, а если вернёт, то проблема не у нас.
- Это несерьёзная программа, и её не нужно писать на продакшн уровне.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Pete Goodliffe
97 Вещей, Которые Должен Знать Каждый Программист
26. Не игнорируйте эту ошибку!
Однажды вечером я шел по улице, чтобы встретиться с друзьями в баре. Мы давно не виделись, и я с нетерпением ждал встречи с ними снова. В спешке я не смотрел, куда иду. Я споткнулся о край бордюра и упал. Так мне и надо, я не следил за дорогой. У меня болела нога, но я спешил на встречу с друзьями. Я поднялся и пошёл дальше. Боль усиливалась. Хотя я изначально проигнорировал её, я быстро понял, что что-то не так.
Но я всё равно поспешил в бар. Но весь вечер пошёл насмарку, потому что меня беспокоила нога. Утром я пошёл к врачу и узнал, что у меня сложный перелом голени. Если бы я остановился, когда почувствовал боль, проблем было бы гораздо меньше. Ходьба со сломанной ногой ни к чему хорошему не приводит.
Слишком многие программисты пишут код по тому же принципу.
«Ошибка, какая ошибка? Да, это ерунда. Серьёзно. Можно не обращать внимания.» Это проигрышная стратегия в отношении вашего кода. На самом деле это просто лень (неконструктивная лень). Независимо от того, насколько, по-вашему, маловероятно, что в вашем коде будет ошибка, вы всегда должны предполагать её наличие и обрабатывать её. Всегда. Вы не сэкономите время, если не сделаете этого; вы только будете накапливать потенциальные проблемы на будущее.
Можно сообщать об ошибках в нашем коде несколькими способами, но лучший из них – исключения. Это структурированный, поддерживаемый языком способ сигнализации и обработки ошибок. И вы не сможете проигнорировать их. Или сможете? Я видел много такого кода:
try {Единственный плюс этой ужасной конструкции в том, что она подчёркивает тот факт, что вы делаете что-то сомнительное.
// ...что-то делаем...
}
catch (...) {} // игнорируем ошибки
Если вы игнорируете ошибку, закрываете глаза и делаете вид, что ничего не случилось, вы рискуете. Так же, как моя нога пострадала гораздо сильнее, чем если бы я сразу же перестал наступать на неё. Если вы гоните по дороге, игнорируя знаки, ничем хорошим это не закончится. Разбирайтесь с проблемами при первой возможности.
Игнорирование ошибок приводит к:
- Ненадёжному коду, то есть коду, наполненному трудноуловимыми и сложными для исправления ошибками.
- Небезопасному коду. Взломщики часто используют плохую обработку ошибок для взлома программных систем.
- Плохо структурированному коду. Если аккуратная обработка ошибок слишком муторна, скорее всего, это результат плохо продуманного интерфейса. Переделайте его так, чтобы обрабатывать ошибки было не так обременительно.
Точно так же, как вы должны проверять все потенциальные ошибки в вашем коде, нужно делать очевидными для пользователей все возможные ошибочные состояния в ваших интерфейсах. Не скрывайте их, рассчитывая на то, что вашим кодом всегда будут правильно пользоваться.
Почему мы не проверяем код на ошибки? Есть несколько стандартных оправданий. С какими из них вы согласны? Что бы вы возразили на это?
- Обработка ошибок загромождает код, затрудняя его чтение и поиск «нормального» потока выполнения.
- Это дополнительная работа, а у меня дедлайн.
- Я знаю, что вызов этой стандартной функции никогда не вернёт ошибку, а если вернёт, то проблема не у нас.
- Это несерьёзная программа, и её не нужно писать на продакшн уровне.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Pete Goodliffe
День триста восемьдесят четвёртый. #ЗадачиНаСобеседовании
«О чём спрашивают на собеседовании?» Наверняка такой вопрос попадается вам в чатах программистов чуть ли не каждый день. На самом деле, ответить на него довольно трудно. Почему-то распространено мнение, будто собеседование - это какой-то экзамен по заранее готовым билетам и всегда у одного экзаменатора.
«Надо ли для собеседования знать тему A?», «А что могут спросить по теме Б?» Интересно, какого ответа ждёт спрашивающий? Ведь чтобы ответить на этот вопрос, нужно либо пройти пару десятков собеседований именно по этой теме, либо иметь доступ к некой ноосфере – разуму всех возможных работодателей – и иметь возможность поиска в нём, как в Гугле. Наверное, только тогда можно более-менее точно сказать, что же задумал спросить у кандидатов хитрый интервьюер компании «Макрософт» из города Урюпинска.
В реальности тем для обсуждения на собеседовании настолько много, что можно придумать самый сумасшедший и невероятный вопрос, и его наверняка где-нибудь когда-нибудь уже задавали.
На самом деле, на мой скромный взгляд, всё, что нужно на собеседовании – это честно отвечать на поставленные вопросы и не бояться признать, что ты чего-то не знаешь, потому что знать всё невозможно. Многие боятся, что их завалят при собеседовании, и пытаются, как перед экзаменом, вызубрить всё, что только можно. Но это порочная практика, если только вам заранее не дали список будущих вопросов (что было бы странно). Понятно, что нужно иметь представление о каких-то базовых вещах, вроде принципов ООП, основных алгоритмах или конструкциях языка. То есть о том, что используется постоянно. Но пытаться досконально разобраться во всех возможных технологиях и тонкостях не под силу никому. Лучше всего, конечно, если на собеседовании у кандидата будут интересоваться знаниями о том, чем ему в реальности предстоит заниматься по работе. Но иногда интервьюерам становится скучно, и они решают кандидатов, скажем так, потроллить. Так что, если вы чувствуете, что вас пытаются «завалить» нюансами алгоритмов или работы сборщика мусора, стоит спросить, действительно ли это нужно для будущей работы. А потом подумать, стоит ли работа в этой компании того. Ведь если вас «валит» на собеседовании ваш будущий руководитель, то вполне вероятно, что и методы руководства у него соответствующие.
Ладно, я что-то отвлёкся. Хочу предложить интересное видео о необычной задаче, которую могут поставить на собеседовании. Сразу отмечу, что это, скорее всего, будет собеседование на сеньора или даже системного архитектора, поэтому кода и алгоритмов тут почти нет, тут вопрос о дизайне на высоком уровне:
Есть система контроля версий, в которую разработчики сливают готовые решения. Нужно разработать систему «деплоя и распространения». Она должна собирать исходный код в исполняемые файлы (dll) и распределять готовые ddl-ки по машинам других разработчиков по всему миру. Предположим, что у нас тысячи коммитов в день и десятки тысяч компьютеров по миру, которые должны получить исполняемые файлы новых версий в течение получаса после коммита. Нет, компилятор писать не нужно, предположим, что такой сервис уже есть. Нужно создать систему учёта и контроля релизов.
Да, по началу звучит страшно. Но признаюсь честно, по мере просмотра видео и по мере того, как «кандидат» разбивал эту задачу на более мелкие, я постепенно понимал, что ничего особо ужасного в этом нет. Более того, многие решения мне приходили в голову раньше, чем озвучивались в видео.
Итак, уже упоминаемый ранее Клемент Михайлеску решает задачу по разработке системы на собеседовании: https://youtu.be/q0KGYwNbf-0 (сорян, только на английском).
«О чём спрашивают на собеседовании?» Наверняка такой вопрос попадается вам в чатах программистов чуть ли не каждый день. На самом деле, ответить на него довольно трудно. Почему-то распространено мнение, будто собеседование - это какой-то экзамен по заранее готовым билетам и всегда у одного экзаменатора.
«Надо ли для собеседования знать тему A?», «А что могут спросить по теме Б?» Интересно, какого ответа ждёт спрашивающий? Ведь чтобы ответить на этот вопрос, нужно либо пройти пару десятков собеседований именно по этой теме, либо иметь доступ к некой ноосфере – разуму всех возможных работодателей – и иметь возможность поиска в нём, как в Гугле. Наверное, только тогда можно более-менее точно сказать, что же задумал спросить у кандидатов хитрый интервьюер компании «Макрософт» из города Урюпинска.
В реальности тем для обсуждения на собеседовании настолько много, что можно придумать самый сумасшедший и невероятный вопрос, и его наверняка где-нибудь когда-нибудь уже задавали.
На самом деле, на мой скромный взгляд, всё, что нужно на собеседовании – это честно отвечать на поставленные вопросы и не бояться признать, что ты чего-то не знаешь, потому что знать всё невозможно. Многие боятся, что их завалят при собеседовании, и пытаются, как перед экзаменом, вызубрить всё, что только можно. Но это порочная практика, если только вам заранее не дали список будущих вопросов (что было бы странно). Понятно, что нужно иметь представление о каких-то базовых вещах, вроде принципов ООП, основных алгоритмах или конструкциях языка. То есть о том, что используется постоянно. Но пытаться досконально разобраться во всех возможных технологиях и тонкостях не под силу никому. Лучше всего, конечно, если на собеседовании у кандидата будут интересоваться знаниями о том, чем ему в реальности предстоит заниматься по работе. Но иногда интервьюерам становится скучно, и они решают кандидатов, скажем так, потроллить. Так что, если вы чувствуете, что вас пытаются «завалить» нюансами алгоритмов или работы сборщика мусора, стоит спросить, действительно ли это нужно для будущей работы. А потом подумать, стоит ли работа в этой компании того. Ведь если вас «валит» на собеседовании ваш будущий руководитель, то вполне вероятно, что и методы руководства у него соответствующие.
Ладно, я что-то отвлёкся. Хочу предложить интересное видео о необычной задаче, которую могут поставить на собеседовании. Сразу отмечу, что это, скорее всего, будет собеседование на сеньора или даже системного архитектора, поэтому кода и алгоритмов тут почти нет, тут вопрос о дизайне на высоком уровне:
Есть система контроля версий, в которую разработчики сливают готовые решения. Нужно разработать систему «деплоя и распространения». Она должна собирать исходный код в исполняемые файлы (dll) и распределять готовые ddl-ки по машинам других разработчиков по всему миру. Предположим, что у нас тысячи коммитов в день и десятки тысяч компьютеров по миру, которые должны получить исполняемые файлы новых версий в течение получаса после коммита. Нет, компилятор писать не нужно, предположим, что такой сервис уже есть. Нужно создать систему учёта и контроля релизов.
Да, по началу звучит страшно. Но признаюсь честно, по мере просмотра видео и по мере того, как «кандидат» разбивал эту задачу на более мелкие, я постепенно понимал, что ничего особо ужасного в этом нет. Более того, многие решения мне приходили в голову раньше, чем озвучивались в видео.
Итак, уже упоминаемый ранее Клемент Михайлеску решает задачу по разработке системы на собеседовании: https://youtu.be/q0KGYwNbf-0 (сорян, только на английском).
День триста восемьдесят шестой. #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/