День триста шестьдесят девятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
HTML Helpers. Начало
HTML helpers (помощники) - это методы, которые вы можете вызывать на свойстве
Каждое представление Razor наследует свойство
Методы расширения используются по двум причинам:
1. Они доступны только тогда, когда пространство имён метода расширения находится в области видимости. Все методы расширения MVC для
2. Вы можете создавать собственные методы расширения для замены или дополнения встроенных помощников.
Помощники существуют для любых HTML элементов, используемых в формах:
-
Тем же способом помощники можно использовать в строго типизированных представлениях. Однако для этого больше подойдут строго типизированные помощники. Они отличаются от обычных наличием суффикса For и принимают первым параметром лямбда-выражение для выбора свойства модели. Например, в строго типизированном представлении для отображения класса
Продолжение следует…
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
ASP.NET MVC 5.
HTML Helpers. Начало
HTML helpers (помощники) - это методы, которые вы можете вызывать на свойстве
Html
представления для генерации HTML-разметки. Их цель - облегчить создание представления. Например, помощник BeginForm
можно использовать для создания тега формы для формы поиска (вместо конструкции using
можно использовать помощник EndForm
, закрывающий форму):@using (Html.BeginForm("Search", "Home", FormMethod.Get)) {Скорее всего будет выведена та же разметка, что и в предыдущем посте. Однако за кулисами помощник координирует свою работу с механизмом маршрутизации для создания правильного URL-адреса, поэтому код более устойчив к изменениям и при развертывании приложения.
<input type="text" name="q" />
<input type="submit" value="Search" />
}
Каждое представление Razor наследует свойство
Html
из своего базового класса. Свойство Html
имеет тип System.Web.Mvc.HtmlHelper<T>
, где T
- это тип модели для представления (по умолчанию dynamic
). Однако метод BeginForm
, как и большинство других, определён как метод расширения.Методы расширения используются по двум причинам:
1. Они доступны только тогда, когда пространство имён метода расширения находится в области видимости. Все методы расширения MVC для
HtmlHelper
находятся в пространстве имен System.Web.Mvc.Html
(которое находится в области видимости благодаря ссылке на него в файле Views/web.config
). Вы можете удалить его.2. Вы можете создавать собственные методы расширения для замены или дополнения встроенных помощников.
Помощники существуют для любых HTML элементов, используемых в формах:
-
Label
– метка label
- BeginForm
, EndForm
– форма form
- TextBox
– поле для ввода input type=”text”
- TextArea
– многострочное поле textarea
- CheckBox
- флажок input type=”checkbox”
- RadioButton
– переключатель input type=”radio”
- DropDownList
– выпадающий список select
- ListBox
– список с множественным выбором select multiple
- Hidden
– скрытое поле input type=”hidden”
- Password
– поле пароля input type=”password”
Большинство помощников для полей проверяют наличие значений для отображения в коллекции ViewData (ViewBag). Например, если в методе действия задать:ViewBag.Price = 10.0;а в представлении использовать
@Html.TextBox("Price")то будет выведен следующий HTML код:
<input id="Price" name="Price" type="text" value="10" />Это также работает со свойствами объектов, помещённых в
ViewData
:ViewBag.Product = new Product { Title=”Book”, Price=11 }Строго типизированные помощники
…
@Html.TextBox("Product.Title")
@Html.TextBox("Product.Price")
Тем же способом помощники можно использовать в строго типизированных представлениях. Однако для этого больше подойдут строго типизированные помощники. Они отличаются от обычных наличием суффикса For и принимают первым параметром лямбда-выражение для выбора свойства модели. Например, в строго типизированном представлении для отображения класса
Product
:@model MyStore.Models.Productможно использовать строго типизированные помощники:
@Html.TextBox(m => m.Title)Преимуществами использования строго типизированных помощников являются доступность IntelliSense, проверка ошибок во время компиляции и упрощенный рефакторинг (если вы измените имя свойства в вашей модели, Visual Studio может автоматически изменить код в представлении).
@Html.TextBox(m => m.Price)
Продолжение следует…
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
День триста семидесятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
HTML Helpers. Окончание
Помощники и Метаданные модели
Кроме поиска данных внутри
Шаблонизированные Помощники
Шаблонизированные помощники строят HTML, используя метаданные и шаблон. Метаданные включают в себя информацию о значении модели (его имя и тип), а также метаданные модели (добавляются с помощью аннотаций или поставщика метаданных). В качестве шаблонизированных помощников выступают
Используя шаблонизированные помощники, вы просите среду выполнения подобрать наиболее подходящий элемент для отображения или редактирования. Например,
Помощники
Помощники по Рендерингу
Помощники по рендерингу создают ссылки на другие ресурсы внутри приложения, а также частичные представления.
Html.ActionLink и Html.RouteLink
Метод
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
ASP.NET MVC 5.
HTML Helpers. Окончание
Помощники и Метаданные модели
Кроме поиска данных внутри
ViewData
, помощники также используют доступные метаданные модели. Например, если свойство модели пометить атрибутом DisplayName
:public class Product {а в представлении использовать помощник
[DisplayName("Название")]
public string Title { get; set; }
…
}
@Html.Label("Title")то будет выведен следующий код HTML:
<label for="Title">Название</label>Помощник запрашивает среду выполнения, доступны ли какие-либо метаданные модели для свойства
Title
, и среда выполнения предоставляет информацию из атрибута DisplayName
. Более подробно об атрибутах модели в следующих постах.Шаблонизированные Помощники
Шаблонизированные помощники строят HTML, используя метаданные и шаблон. Метаданные включают в себя информацию о значении модели (его имя и тип), а также метаданные модели (добавляются с помощью аннотаций или поставщика метаданных). В качестве шаблонизированных помощников выступают
Html.Display
(Html.DisplayFor
) и Html.Editor
(Html.EditorFor
), а также их аналоги для целой модели Html.DisplayForModel
и Html.EditorForModel
.Используя шаблонизированные помощники, вы просите среду выполнения подобрать наиболее подходящий элемент для отображения или редактирования. Например,
EditorFor
сгенерирует тот же код HTML, что и TextBoxFor
. Однако, его можно настроить с помощью аннотаций. Например, следующая аннотация:[DataType(DataType.MultilineText)]Приведёт к тому, что
public string Title { get; set; }
EditorFor
сгенерирует многострочное поле textarea
.Помощники
DisplayForModel
и EditorForModel
создают HTML-код для целой модели. Используя их, вы можете добавлять новые свойства в модель и мгновенно видеть изменения в пользовательском интерфейсе, не внося никаких изменений в представления.Помощники по Рендерингу
Помощники по рендерингу создают ссылки на другие ресурсы внутри приложения, а также частичные представления.
Html.ActionLink и Html.RouteLink
Метод
ActionLink
визуализирует гиперссылку на другой метод действия или контроллер. Он использует API маршрутизации для создания URL-адреса. @Html.ActionLink("Ссылка", "AnotherAction")Это производит следующую разметку для маршрута по умолчанию:
<a href="/Home/AnotherAction">Ссылка</a>Помощник
RouteLink
следует тому же шаблону, но также принимает имя маршрута и не имеет аргументов для контроллера и метода действия:@Html.RouteLink("Ссылка", new {action="AnotherAction"})Html.Partial и Html.RenderPartial
Partial
визуализирует частичное представление. Как правило, оно содержит общую разметку, которую вы хотите отобразить в нескольких представлениях:@Html.Partial("ProductDisplay")Здесь указано только имя представления. Среда выполнения ищет нужное представление, используя все доступные механизмы. Кроме того, методу можно передать модель и коллекцию
ViewData
.RenderPartial
похож на Partial
, но он пишет код непосредственно в выходной поток. По этой причине RenderPartial
нужно помещать внутрь блока кода. Следующие две строки приведут к одинаковому выводу в выходной поток:@{ Html.RenderPartial("ProductDisplay"); }Html.Action и Html.RenderAction
@Html.Partial("ProductDisplay")
Action
и RenderAction
аналогичны Partial
и RenderPartial
. Но, тогда как Partial отображает код из другого представления, Action
, выполняет другой метод контроллера и отображает его результат. Action
предлагает больше гибкости, потому что метод контроллера может построить другую модель и использовать другой контекст:[ChildActionOnly]В представлении:
public ActionResult Menu() {
var menu = GetMenuFromSomewhere();
return PartialView(menu);
}
@Html.Action("Menu")Обратите внимание, что метод-действие
Menu
помечен атрибутом ChildActionOnly
. Атрибут не позволяет среде выполнения вызывать метод напрямую через URL. Он может быть вызван только через Action
или RenderAction
. Атрибут ChildActionOnly
не требуется, но обычно рекомендуется для дочерних методов-действий.Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
День триста семьдесят первый. #NetInternals
3. Можно ли использовать методы расширения с dynamic?
Нет. Код можно проверить здесь
Источник: Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
3. Можно ли использовать методы расширения с dynamic?
Нет. Код можно проверить здесь
using System;Это потому, что методы расширения компилируются в статические. Код выше фактически компилируется в это:
public class Program {
public static void Main() {
int x = 5;
x.Extend();
dynamic y = x;
y.Extend();
}
}
static class Foo {
public static void Extend(this int x) {
Console.WriteLine(x);
}
}
IL_0004: call void Foo::Extend(int32)В C# вы могли бы написать его как:
Foo.Extend(x);Однако DLR (Динамическая Среда Выполнения) ищет методы объекта во время выполнения, поэтому вы не можете использовать расширения с динамическими переменными.
Источник: Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
День триста семьдесят второй. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
23. Языки предметной области
Когда вы слушаете дискуссию между экспертами в любой области, будь то шахматисты, воспитатели детских садов или страховые агенты, вы заметите, что их словарный запас сильно отличается от повседневного языка. Это то, что называется «язык предметной области» (Domain Specific Language): набор слов и выражений, описывающий вещи, характерные для данной предметной области.
DSL - это исполняемые выражения на языке, специфичном для данной области, с использованием определённого словарного запаса и грамматики, которые читаемы, понятны и (лучше всего, если) предложены для использования экспертами в предметной области. DSL, предназначенные для разработчиков ПО или ученых, существуют уже давно. Например, «маленькие языки» в конфигурационных файлах Unix или языки, созданные с помощью макросов LISP.
DSL обычно делят на внутренние или внешние.
Внутренние DSL написаны на языке программирования общего назначения, синтаксис которого был изменён, чтобы выглядеть наиболее похожим на естественный язык. Это проще сделать в языках, которые предлагают много синтаксического сахара и возможностей форматирования (например, Ruby и Scala), чем в других (например, Java). Большинство внутренних DSL являются обёртками для существующих API и библиотек и предоставляют оболочку для более понятного доступа к функциональности. Они исполняются напрямую. В зависимости от области и реализации они могут использоваться для построения структур данных, определения зависимостей, запуска процессов или задач, взаимодействия с другими системами или проверки ввода пользователя. Синтаксис внутреннего DSL ограничен языком программирования, в котором он создан. Существует много шаблонов - например, построитель выражений, цепочка методов и аннотации - которые могут помочь вам изменить основной язык под ваш DSL. При участии эксперта в области внутренний DSL может быть разработан довольно быстро.
Внешние DSL - это текстовые или графические представления языка, причём текстовые, как правило, встречаются чаще. Текстовые выражения могут обрабатываться набором инструментов, который включает в себя лексический анализатор, грамматический разбор, преобразователь модели, генераторы и другие виды постобработки. Внешние ЯПО часто преобразуются во внутреннюю модель, представляющую базис для дальнейшей обработки. Хорошо помогает задать грамматику (например, расширенную форму Бэкуса-Наура). Грамматика обеспечивает отправную точку для генерации частей цепочки инструментов (например, редактор, визуализатор, синтаксический анализатор). Для простых DSL может быть достаточно парсера, написанного вручную, например, с помощью регулярных выражений. Пользовательские парсеры могут стать громоздкими, если от них слишком много просят, поэтому имеет смысл взглянуть на инструменты, разработанные специально для работы с языковыми грамматиками и DSL, например openArchitectureWare, ANTLR, SableCC, AndroMDA. Определение внешнего DSL как диалекта XML также довольно распространено, хотя читаемость часто является проблемой, особенно для тех, кто не знаком с XML.
Вы всегда должны принимать во внимание целевую аудиторию вашего DSL: разработчики, менеджеры, бизнес-клиенты или конечные пользователи. Вы должны адаптировать технический уровень языка, доступные инструменты, синтаксическую справку (например, IntelliSense), раннюю проверку, визуализацию и представление для целевой аудитории. Скрывая технические детали, DSL могут расширить возможности пользователей, предоставляя им возможность адаптировать системы к их потребностям без помощи разработчиков. Это также может ускорить разработку из-за потенциального распределения работы после создания исходной языковой структуры. Язык может развиваться постепенно.
Неплохой пример DSL для тестирования описан в этом видео.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Michael Hunger
97 Вещей, Которые Должен Знать Каждый Программист
23. Языки предметной области
Когда вы слушаете дискуссию между экспертами в любой области, будь то шахматисты, воспитатели детских садов или страховые агенты, вы заметите, что их словарный запас сильно отличается от повседневного языка. Это то, что называется «язык предметной области» (Domain Specific Language): набор слов и выражений, описывающий вещи, характерные для данной предметной области.
DSL - это исполняемые выражения на языке, специфичном для данной области, с использованием определённого словарного запаса и грамматики, которые читаемы, понятны и (лучше всего, если) предложены для использования экспертами в предметной области. DSL, предназначенные для разработчиков ПО или ученых, существуют уже давно. Например, «маленькие языки» в конфигурационных файлах Unix или языки, созданные с помощью макросов LISP.
DSL обычно делят на внутренние или внешние.
Внутренние DSL написаны на языке программирования общего назначения, синтаксис которого был изменён, чтобы выглядеть наиболее похожим на естественный язык. Это проще сделать в языках, которые предлагают много синтаксического сахара и возможностей форматирования (например, Ruby и Scala), чем в других (например, Java). Большинство внутренних DSL являются обёртками для существующих API и библиотек и предоставляют оболочку для более понятного доступа к функциональности. Они исполняются напрямую. В зависимости от области и реализации они могут использоваться для построения структур данных, определения зависимостей, запуска процессов или задач, взаимодействия с другими системами или проверки ввода пользователя. Синтаксис внутреннего DSL ограничен языком программирования, в котором он создан. Существует много шаблонов - например, построитель выражений, цепочка методов и аннотации - которые могут помочь вам изменить основной язык под ваш DSL. При участии эксперта в области внутренний DSL может быть разработан довольно быстро.
Внешние DSL - это текстовые или графические представления языка, причём текстовые, как правило, встречаются чаще. Текстовые выражения могут обрабатываться набором инструментов, который включает в себя лексический анализатор, грамматический разбор, преобразователь модели, генераторы и другие виды постобработки. Внешние ЯПО часто преобразуются во внутреннюю модель, представляющую базис для дальнейшей обработки. Хорошо помогает задать грамматику (например, расширенную форму Бэкуса-Наура). Грамматика обеспечивает отправную точку для генерации частей цепочки инструментов (например, редактор, визуализатор, синтаксический анализатор). Для простых DSL может быть достаточно парсера, написанного вручную, например, с помощью регулярных выражений. Пользовательские парсеры могут стать громоздкими, если от них слишком много просят, поэтому имеет смысл взглянуть на инструменты, разработанные специально для работы с языковыми грамматиками и DSL, например openArchitectureWare, ANTLR, SableCC, AndroMDA. Определение внешнего DSL как диалекта XML также довольно распространено, хотя читаемость часто является проблемой, особенно для тех, кто не знаком с XML.
Вы всегда должны принимать во внимание целевую аудиторию вашего DSL: разработчики, менеджеры, бизнес-клиенты или конечные пользователи. Вы должны адаптировать технический уровень языка, доступные инструменты, синтаксическую справку (например, IntelliSense), раннюю проверку, визуализацию и представление для целевой аудитории. Скрывая технические детали, DSL могут расширить возможности пользователей, предоставляя им возможность адаптировать системы к их потребностям без помощи разработчиков. Это также может ускорить разработку из-за потенциального распределения работы после создания исходной языковой структуры. Язык может развиваться постепенно.
Неплохой пример DSL для тестирования описан в этом видео.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Michael Hunger
День триста семьдесят третий. #DesignPatterns
Паттерны проектирования
12. Паттерн «Фабричный метод» (Factory Method)
Когда при обсуждении дизайна упоминается фабрика, то в подавляющем большинстве случаев имеется в виду одна из разновидностей паттерна «Фабричный метод».
Назначение: определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс создавать. Фабричный метод позволяет классу делегировать создание объекта подклассам.
Причины использования:
Иерархии классов обеспечивают гибкость за счет полиморфного использования, но привносят дополнительную сложность. Абстрактная фабрика решает задачу полиморфного создания семейства объектов, но очень часто возникает более простая задача — создание одного экземпляра иерархии наследования.
На практике встречаются три вида паттерна «Фабричный метод», которые приведены на рисунке ниже:
-
-
-
-
1. Классический фабричный метод является частным случаем паттерна «Шаблонный метод», переменный шаг которого отвечает за создание нужного типа объекта. Это значит, что фабричный метод привязан к текущей иерархии типов и не может быть использован повторно в другом контексте.
2. Статический фабричный метод является самой простой версией. Основное отличие его от классического в том, что тип создаваемого объекта определяется не типом наследника, а аргументами, переданными методу. Типичная реализация такого метода содержит оператор
3. Полиморфный фабричный метод определяет интерфейс фабрики, а за создание конкретного экземпляра продукта отвечает конкретная фабрика. Является стратегией создания экземпляров некоторого семейства типов, что позволяет использовать одну фабрику в разных контекстах. Тип создаваемого объекта определяется типом фабрики и обычно не зависит от аргументов фабричного метода.
Конструктор vs. фабричный метод
В большинстве случаев конструкторы прекрасно справляются со своей задачей. Но есть две причины использовать фабричный метод вместо конструктора:
1. Именованные конструкторы. В языке C# невозможно использовать два конструктора с одним набором и типом параметров. Хорошим примером такого ограничения является структура
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 10.
Паттерны проектирования
12. Паттерн «Фабричный метод» (Factory Method)
Когда при обсуждении дизайна упоминается фабрика, то в подавляющем большинстве случаев имеется в виду одна из разновидностей паттерна «Фабричный метод».
Назначение: определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс создавать. Фабричный метод позволяет классу делегировать создание объекта подклассам.
Причины использования:
Иерархии классов обеспечивают гибкость за счет полиморфного использования, но привносят дополнительную сложность. Абстрактная фабрика решает задачу полиморфного создания семейства объектов, но очень часто возникает более простая задача — создание одного экземпляра иерархии наследования.
На практике встречаются три вида паттерна «Фабричный метод», которые приведены на рисунке ниже:
-
Creator
— объявляет абстрактный или виртуальный метод создания продукта, использует фабричный метод в своей реализации;-
ConcreteCreator
— реализует фабричный метод, который возвращает ConcreteProduct
;-
Product
— определяет интерфейс продуктов, создаваемых фабричным методом;-
ConcreteProduct
— определяет конкретный вид продуктов.1. Классический фабричный метод является частным случаем паттерна «Шаблонный метод», переменный шаг которого отвечает за создание нужного типа объекта. Это значит, что фабричный метод привязан к текущей иерархии типов и не может быть использован повторно в другом контексте.
2. Статический фабричный метод является самой простой версией. Основное отличие его от классического в том, что тип создаваемого объекта определяется не типом наследника, а аргументами, переданными методу. Типичная реализация такого метода содержит оператор
switch
, в котором происходит выбор создаваемого типа. Вместо этого можно воспользоваться словарём, ключом которого будет некоторый идентификатор (строка, перечисление и т. п.), а значением — делегат, который будет создавать объект нужного класса. Статический метод позволяет обойти ограничения конструкторов. Например, тип создаваемого объекта может зависеть от аргументов метода, экземпляр может возвращаться из кэша, а не создаваться заново или же фабричный метод может быть асинхронным.3. Полиморфный фабричный метод определяет интерфейс фабрики, а за создание конкретного экземпляра продукта отвечает конкретная фабрика. Является стратегией создания экземпляров некоторого семейства типов, что позволяет использовать одну фабрику в разных контекстах. Тип создаваемого объекта определяется типом фабрики и обычно не зависит от аргументов фабричного метода.
Конструктор vs. фабричный метод
В большинстве случаев конструкторы прекрасно справляются со своей задачей. Но есть две причины использовать фабричный метод вместо конструктора:
1. Именованные конструкторы. В языке C# невозможно использовать два конструктора с одним набором и типом параметров. Хорошим примером такого ограничения является структура
Timespan
. Очень удобно создавать интервал времени по количеству секунд, минут, часов и дней, но сделать несколько конструкторов, каждый из которых принимает один параметр типа double
, невозможно. Для этого структура Timespan
содержит набор фабричных методов.public struct Timespan {2. Тяжеловесный процесс создания. Обычно логика конструктора относительно простая, но слишком тяжеловесную логику лучше вынести в статический фабричный метод. Если для конструирования объекта требуется обращение к внешним ресурсам, то лучше сразу же выделять эту логику в фабричный метод. Это позволяет сделать фабричный метод асинхронным, а также упростить эволюцию решения и разбиение данного класса на более мелкие составляющие в случае необходимости.
public Timespan(double ticks) {…}
public static Timespan FromMilliseconds(double value) {…}
public static Timespan FromSeconds(double value) {…}
public static Timespan FromMinutes(double value) {…}
…
}
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 10.
День триста семьдесят четвёртый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
24. Не бойтесь что-то сломать
Каждому работнику сферы ИТ, несомненно, приходилось работать над проектом, код которого был, мягко говоря, ненадёжным. Система плохо спроектирована, и изменение одной вещи всегда приводило к нарушению другой не связанной функции. Всякий раз, когда добавлялся новый модуль, цель программиста состояла в том, свести изменения к минимуму и молиться при каждом релизе. Это программный эквивалент игры Дженга, где надо извлекать из небоскрёба несущие балки. Рано или поздно такая игра закончится катастрофой.
Причина, по которой внесение изменений настолько болезненно, в том, что вся система больна. Системе нужен врач, иначе её состояние будет только ухудшаться. Вы уже знаете, что не так с вашей системой, но вы боитесь разбить яйцо, чтобы приготовить омлет. Опытный хирург знает, при операции сначала нужно резать по живому, но он также знает, что разрезы являются временными и заживают. Сразу после операции будет больно, но потом пациенту станет лучше, чем было до операции.
Не бойтесь своего кода. Кого волнует, если что-то сломается во время ремонта? Парализующий страх перемен — вот что привело ваш проект в это состояние. Вложение времени в рефакторинг окупит себя многократно в течение жизненного цикла вашего проекта. Дополнительным преимуществом является то, что опыт вашей команды в работе над больной системой позволит всем специалистам узнать, как она должна работать. Примените эти знания, а не игнорируйте них. Работа над системой, которую вы ненавидите, — это не то, на что нужно тратить своё время.
Переопределите внутренние интерфейсы, реструктурируйте модули, уберите дублирующийся код и упростите дизайн, уменьшив количество зависимостей. Вы можете значительно уменьшить сложность кода, устраняя проблемные пограничные случаи, возникающие из-за неправильно связанных функций. Постепенно переведите старую структуру в новую, не забывая выполнять тесты по мере перехода. Попытка выполнить большой рефакторинг за «один большой шаг» вызовет достаточно проблем, чтобы заставить вас подумать о том, чтобы бросить всё на полпути.
Будьте хирургом, который не боится вырезать больные части, чтобы освободить место для здоровых. Такая смелость заразительна и вдохновит других начать работать над проектами по рефакторингу, которые они откладывали. Составьте список «гигиенических» процедур, которые, по мнению команды, пойдут на благо проекту. Убедите руководство, что даже если эти задачи могут не дать видимых результатов сейчас, они уменьшат расходы и ускорят будущие релизы. Никогда не переставайте заботиться об общем «здоровье» кода.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Mike Lewis
97 Вещей, Которые Должен Знать Каждый Программист
24. Не бойтесь что-то сломать
Каждому работнику сферы ИТ, несомненно, приходилось работать над проектом, код которого был, мягко говоря, ненадёжным. Система плохо спроектирована, и изменение одной вещи всегда приводило к нарушению другой не связанной функции. Всякий раз, когда добавлялся новый модуль, цель программиста состояла в том, свести изменения к минимуму и молиться при каждом релизе. Это программный эквивалент игры Дженга, где надо извлекать из небоскрёба несущие балки. Рано или поздно такая игра закончится катастрофой.
Причина, по которой внесение изменений настолько болезненно, в том, что вся система больна. Системе нужен врач, иначе её состояние будет только ухудшаться. Вы уже знаете, что не так с вашей системой, но вы боитесь разбить яйцо, чтобы приготовить омлет. Опытный хирург знает, при операции сначала нужно резать по живому, но он также знает, что разрезы являются временными и заживают. Сразу после операции будет больно, но потом пациенту станет лучше, чем было до операции.
Не бойтесь своего кода. Кого волнует, если что-то сломается во время ремонта? Парализующий страх перемен — вот что привело ваш проект в это состояние. Вложение времени в рефакторинг окупит себя многократно в течение жизненного цикла вашего проекта. Дополнительным преимуществом является то, что опыт вашей команды в работе над больной системой позволит всем специалистам узнать, как она должна работать. Примените эти знания, а не игнорируйте них. Работа над системой, которую вы ненавидите, — это не то, на что нужно тратить своё время.
Переопределите внутренние интерфейсы, реструктурируйте модули, уберите дублирующийся код и упростите дизайн, уменьшив количество зависимостей. Вы можете значительно уменьшить сложность кода, устраняя проблемные пограничные случаи, возникающие из-за неправильно связанных функций. Постепенно переведите старую структуру в новую, не забывая выполнять тесты по мере перехода. Попытка выполнить большой рефакторинг за «один большой шаг» вызовет достаточно проблем, чтобы заставить вас подумать о том, чтобы бросить всё на полпути.
Будьте хирургом, который не боится вырезать больные части, чтобы освободить место для здоровых. Такая смелость заразительна и вдохновит других начать работать над проектами по рефакторингу, которые они откладывали. Составьте список «гигиенических» процедур, которые, по мнению команды, пойдут на благо проекту. Убедите руководство, что даже если эти задачи могут не дать видимых результатов сейчас, они уменьшат расходы и ускорят будущие релизы. Никогда не переставайте заботиться об общем «здоровье» кода.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Mike Lewis
День триста семьдесят пятый. #Оффтоп
Продолжаю серию постов «попалось мне тут в рекомендациях ютуба». На канале Up and Atom симпатичная девушка (что выгодно отличает этот канал от других 😊) довольно доступно, интересно, и не без доли юмора рассказывает о различных научных темах.
А попалось мне в рекомендациях видео про самую большую неразрешённую проблему в компьютерной науке: «Равенство классов P и NP». Собственно проблема состоит в следующем: если положительный ответ на какой-то вопрос (допустим, верность решения судоку) можно довольно быстро проверить (за полиномиальное время), то правда ли, что ответ на этот вопрос можно довольно быстро найти (также за полиномиальное время и используя полиномиальную память)? Другими словами, действительно ли решение задачи проверить не легче, чем его отыскать?
В видео подробно объясняется, в чём, собственно, проблема, зачем нам это знать и как бы выглядел мир, если бы P было равно NP.
PS: уже стандартное замечание, касающееся чуть менее, чем всех, интересных видео: оно на английском.
Продолжаю серию постов «попалось мне тут в рекомендациях ютуба». На канале Up and Atom симпатичная девушка (что выгодно отличает этот канал от других 😊) довольно доступно, интересно, и не без доли юмора рассказывает о различных научных темах.
А попалось мне в рекомендациях видео про самую большую неразрешённую проблему в компьютерной науке: «Равенство классов P и NP». Собственно проблема состоит в следующем: если положительный ответ на какой-то вопрос (допустим, верность решения судоку) можно довольно быстро проверить (за полиномиальное время), то правда ли, что ответ на этот вопрос можно довольно быстро найти (также за полиномиальное время и используя полиномиальную память)? Другими словами, действительно ли решение задачи проверить не легче, чем его отыскать?
В видео подробно объясняется, в чём, собственно, проблема, зачем нам это знать и как бы выглядел мир, если бы P было равно NP.
PS: уже стандартное замечание, касающееся чуть менее, чем всех, интересных видео: оно на английском.
День триста семьдесят шестой. #юмор
Да, бывает))) Всем продуктивной рабочей недели.
Да, бывает))) Всем продуктивной рабочей недели.
День триста семьдесят седьмой. #Оффтоп #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