понедельник, 28 декабря 2015 г.

Критика книги Боба Мартина «Профессиональный программист»

У меня со стариной Бобом складываются довольно сложные односторонние отношения. Когда-то, он был моим чуть ли не кумиром, но после внимательного прочтения его книги «Принципы, паттерны и методики гибкой разработки» мое мнение сильно изменилось. Теперь же любой его труд мне читать стало заметно сложнее, поскольку явно начал проявляться «баг» под названием «подтверждение предвзятости». Я стал находить все больше и больше непонятных мне моментов и все меньше полезных советов. Но поскольку большинство книг «дядюшки» Боба весьма известны и обладают высоким рейтингом, я не могу пройти мимо и не поделиться с вами своим впечатлением от прочтения очередного его творения.

Книга «Профессиональный программист» (Clean Coder: A Code of Conduct for Professional Programmers) относится к жанру, который я называю «философией программирования», по названию одноименного форума на rsdn.ru, где было принято обсуждать вопросы стиля, кодинга, гайдлайдов, технического флейма по поводу языков программирования и тому подобных вещей. Популяризаторами этого жанра были такие замечательные авторы как Хант с Томасом и своим «Программистом-прагматиком», Джоэл Спольски со своими записками о программировании и многие другие.

Я вижу две ключевые пользы от таких книг:

  • Расширения кругозора
  • Повышение мотивации

Например, читая книгу Энди Ханта и Дейва Томаса вы узнаете о «теории разбитых окон»; правиле Деметры; вы узнаете о пользе и сложностях общения в коллективе; поймете, что важно говорить «нет»; убедитесь, что сбор требований – дело сложное и пользователь сам не знает, чего он хочет; узнаете о трюке с резиновым утенком при отладке и будете с осторожностью заявлять о багах в компиляторе и операционной системе и станете больше уделять внимания своим собственным ошибкам. Вы познакомитесь с десятками разных концепций и пополните копилку книг для чтения в будущем.

четверг, 24 декабря 2015 г.

О трудозатратах на саморазвитие

У меня к вам внезапный вопрос: а сколько вы тратите времени в неделю на саморазвитие? Час? 5, 10, 20? Я спрашиваю не из праздного интереса. Мне самому довольно часто задают этот вопрос и мне бы хотелось собрать некоторую статистику.

Если брать статистику по отрасли, то там будет все довольно печально. Есть статистика, что процентов 90 программистов не читают ни единой книги в год и прочитывают не более одной статьи в неделю. В общем, с одной стороны, все довольно печально, а с другой – все просто прекрасно: потребуется не так уж много усилий, чтобы выделиться из толпы.

Цель этой заметки, дать вам вменяемое представление о том, сколько разумно тратить времени на собственное развитие, что при этом делать и каких результатов ожидать.

вторник, 1 декабря 2015 г.

О дружбе значимых типов с ООП

Камрад @ViIvanov в своем блоге поднял интересный вопрос о значимых типах и ООП. По сути, это был развернутый комментарий к моему посту «Пишем простой анализатор с помощью Roslyn», в котором я упомянул, что структуры плохо дружат с ООП. Вячеслав высказал очень разумную мысль, что наследование не является ключевой особенностью ООП, а значит ограничение значимых типов в этой части не должны делать из них граждан второго сорта. Ну что ж, пришло время развернуть мою мысль поглубже.

Начнем с того, чем же для меня является и не является ООП. Мое ИМХО в том, что ООП, как и проектирование в целом, основано на двух китах – абстракции и инкапсуляции (а не только на инкапсуляции, как выразился Вячеслав). Абстракция позволяет выделить существенные аспекты поведения, а инкапсуляция является тем инструментом, который позволяет спрятать ненужные подробности и детали реализации с глаз долой.

воскресенье, 29 ноября 2015 г.

Анонс конференции DotNext 2015 Moscow

Я редко делаю анонсы конференций, но в этот раз я решил сделать исключение. Во-первых, сразу двое организаторов этой конференции пригласили меня участвовать;), ну а во-вторых, такого уровня .NET конференции проходят у нас не часто. Поскольку в этот раз мое участие осложнено маленьким семейным обстоятельством, то мне не остается ничего другого, как познакомиться читателей с предстоящим интересным событием.

Известное дело, что в конференции самое главное – это спикеры. Все конференции DotNext, коих прошло уже несколько, отличаются тем, что организаторы стараются собрать ключевых дотнетчиков рунета, а потом еще разбавить их парочкой зарубежных специалистов. В этом посте я хочу познакомить вас со спикерами, часть которых я знаю лично, другую часть – только по интернетам.

Итак, поехали.

четверг, 26 ноября 2015 г.

Как я изучаю английский язык

Один из читателей прислал следующий вопрос:

«Вы переводили много статей с английского, читаете свободно книги, а сейчас работаете в англоязычной стране. Не могли бы Вы немного рассказать о Вашем пути в изучении английского языка. Хорошая школьная/университетская база? Или перевод статей позволил настолько прокачаться? :)»

Ну что ж, почему бы не поделиться своими тайными знаниями. Но, как и с любыми знаниями/подходами к изучению, нужно понимать, что если что-то работает для меня, то не факт, что будет работать для вас.

Ну, если что, я вас предупредилJ

понедельник, 16 ноября 2015 г.

Дайджест интересных материалов за ноябрь 2015

Сейчас только ленивый не выпускает свои собственные подборки интересных материалов. Вот и я решил не отставать от мейнстрима и добавил новую и, надеюсь, постоянную рубрику в свой блог.

Подобные дайжесты обычно являются субъективными и прежде всего покрывают темы, которыми интересуется его автор. Данные подборки не будут исключениями и будут касаться прежде всего .NET-направления, дизайна/архитектуры, ну и разработки ПО в целом. При этом, в ней могут встречаться ссылки не только на новые материалы, но и на что-то довольно старое, и всем давно известное, но открытое автором сего блога лишь недавно. Главный критерий будет отдаваться не столько новизне, сколько качеству материала.

Итак, начнем.

понедельник, 9 ноября 2015 г.

Контракты и удаленный код

Как вы, наверное, знаете, библиотека Code Contracts использует переписывание IL кода для реализации контрактного программирования. Это «архитектурное» решение является вполне логичным, с одной стороны, поскольку позволяет использовать эту библиотеку с любыми языками программирования на платформе .NET. Но, с другой стороны, это приводит к массе проблем, поскольку ccrewrite должен «реверс-инжинирить» IL код в высокоуровневые конструкции и переписывать его специальным образом.

Сегодня я хочу рассмотреть одно из последствий работы на IL уровне, которое может приводить к неожиданным результатам и порассуждать о возможных решениях.

понедельник, 2 ноября 2015 г.

Дрейфусы, аджайлы и прочие страшные слова

Есть такой замечательный товарищ по имени Энди Хант. Известен он, прежде всего, авторством замечательной книги «Программист-прагматик. Путь от подмастерья к мастеру». Некоторые же знают его как одного из авторов Agile Manifesto, и автора интересной книги “Pragmatic Thinking and Learning: Refactor Your Wetware”.

В своей книге “Pragmatic Thinking and Learning” Энди Хант рассматривает много интересных моментов, связанных с работой нашего с вами серого вещества и уделяет немало внимания его работе в контексте разработки ПО. Так вот, есть один интересный момент, на который должны обратить внимание менеджеры и разработчики, в душах которых тлеет огонь надежды на успешное применение модного нынче понятия “agile development”.

И связан он с моделью Дрейфуса, которая, в свою очередь сильно напоминает известную с древности концепцию Сюхари.

четверг, 22 октября 2015 г.

Пишем простой анализатор с помощью Roslyn

С выходом новой версии студии (VS2015) у каждого из нас появилась возможность почувствовать себя причастным к разработке инструментов для разработчиков. Камрады из команд компиляторов C#/VB проделали отличную работу по «выставлению» внутренностей компилятора наружу, что позволяет теперь писать свои собственные анализаторы кода, затрачивая вполне разумные на это силы.

Но, прежде чем приступать к обсуждению примеров, давайте рассмотрим, для чего они могут понадобиться.

Для чего нужны свои собственные анализаторы?

Вопрос вполне разумный. Есть «реактивные мозги», есть DevExpress, есть же мелкомягкие товарищи из DevDiv-а, которые пилят инструменты для разработчиков. Зачем мне разбираться со всякими иммутабельными синтаксическими деревьями и control flow анализом? Это довольно весело, но разве этого достаточно, чтобы тратить на это свое ценное время?

Любой инструмент общего назначения рассчитан на решение наиболее типичных задач. Достаточно открыть список анализаторов Решарпера, чтобы понять, о чем идет речь. Такие анализаторы отлично справиться с поиском недостижимого кода или с предупреждением о неправильной реализации синглтона, но он не «подскажет» о правилах специфичных для вашего проекта и/или библиотеки.

Например, вы можете захотеть реагировать более жестко на некорректное логгирование исключений (детектить и «бить по пальцам», если вашему методу логирования передается ex.Message, а не ex.ToString()), или же это может быть кастомное правило, запрещающее использовать LINQ в определенных сборках во избежание потери производительности. Если в вашей команде есть правило или набор правил, которому должны следовать все члены команды, но которое нельзя выразить в виде правил FxCop/StyleCop. Все эти задачи отлично будут решаться с помощью самописных анализаторов.

среда, 23 сентября 2015 г.

Элегантная реализация «слабых событий»

Камрад @v2_matveev указал на прекрасную реализацию слабых событий в коде Roslyn-а.

Проблема стара как мир: подписка на события долгоживущего объекта со стороны короткоживущего продлевает время жизни последнего. Сложно? Может быть. Но столкнуться с проблемой довольно легко: если у вас есть синглтон с событиями, поздравляю, в вашем приложении есть эта проблема и связанные с ней утечки памяти. Поскольку событие содержит корневую ссылку на хендлер, то любой подписчик будет жить до тех пор, пока он не отпишется от события или пока поставщик событий не умрет (что в случае синглтона произойдет лишь при выгрузке домена или окончания работы приложения).

Решается эта проблема разными способами. Самый правильный способ – не использовать события в синглтонах. Второй способ – отписываться от событий вовремя. Третий способ – хипстерский, воспользоваться той или иной реализацией Weak Event Pattern-а, например, с помощью WeakEventManager или чего-то подобного. Но раз уж зашла речь за слыбые события, то их можно реализовать по разному и далее показана самая изящная реализация.

Вначале демонстрируем проблему: добавляем синглтон с событиями и короткоживущий объект, который на них подписывается:

четверг, 13 августа 2015 г.

Начать ли использовать контракты?

Тут народ на rsdn-е интересуется, а стоит ли пользоваться Code Contracts,  вопрос интересный. Ответ такой вопрос звучит обычно так:“it depends”, но я могу помочь понять, от чего и что depends.

Краткий экскурс в историю контрактов

Сама идея контрактного программирования появилась в 80-х годах в голове Бертрана Мейера и основывалась на матанских выкладках Хоара и других умных дядек.

Заключалась она в следующем: программа сама по себе не является корректной или не корректной, это понятие применимо лишь к паре – (программа, ожидаемое поведение). А поскольку ожидаемое поведение обычно является совершенно непонятным делом, то хочется иметь возможность в кратком и implementation-agnostic виде выразить это самое поведение. Причем сделать это как можно ближе к реализации этого самого поведения.

Для выражения ожидаемого поведения (a.k.a. спецификации) использовались утверждения, а чтобы понять, кто в программе не прав, вызывающий или вызываемый код, то добавлено несколько видов утверждений:

четверг, 6 августа 2015 г.

Обзор возможностей C# 6.0

О новых возможностях языка C# написано чуть более, чем достаточно, но мне тоже хочется внести свою лепту. Я тут пару недель хакатонил и в новом проекте активно использовался C# 6.0, поэтому появился дополнительный опыт, которым можно уже поделиться.

Итак, ниже представлены фичи языка C# 6.0 в порядке их полезности для меня на данный момент времени.

String Interpolation

Да, интерполяция строк мне показалась самой полезной возможностью. Ведь очень часто приходится формировать строки и впихивать в них дополнительные данные. Вот, например, нужно сгенерировать исключение и добавить в сообщение значение одного из аргументов:

class UserNotFoundException : Exception
{
   
public UserNotFoundException(string
userId)
        :
base($"User '{userId}' was not found!")
    { }
}

вторник, 21 июля 2015 г.

Code Contracts в VS2015

В последние несколько недель я активно занимался доработкой Code Contracts, исправлением некоторых неприятных ошибок и добавлением поддержки VS2015. А поскольку VS2015 только что увидела свет, то подобная поддержка будет весьма кстати. Теперь обо всем об этом по порядку, да еще и с рядом технических подробностей.

Итак, первое, что нужно знать о Code Contracts, что эта штука жива. Код лежит в открытом доступе на гитхабе (https://github.com/Microsoft/CodeContracts) и есть ряд людей, которые активно занимаются наведением там порядка. Я являюсь owner-ом репозитория, но занимаюсь этим в свое свободное время. Помимо меня есть еще несколько человек, которые наводят порядок в Code Contracts Editor Extensions (@sharwell) и в некоторых других областях.

Code Contracts можно разделить на несколько составляющих:

  • ccrewrite – тул, который занимается «переписыванием» IL-а, выдиранием утверждений (Contract.Requires/Ensures/Assert/Assume/if-throw) и заменой их на нужные вызовы методов контрактов, в зависимости от конфигурации.
  • cccheck - тул, который занимается статическим анализом и формальным доказательством во время компиляции, что программа является корректной.
  • Code Contracts Editor Extensions – расширение к VS, которое позволяет «видеть» контракты прямо в IDE.

Есть еще ряд тулов, например, для генерации документации, а также плагин к ReSharper, который упрощает добавление предусловий/постусловий и показывает ошибки ccrewrite прямо в IDE.

Я занимаюсь двумя составляющими – ccrewrite и плагином, но сейчас хочу остановиться именно на ccrewrite и на сложностях, с которыми я столкнуться при добавлении поддержки VS2015.

вторник, 7 июля 2015 г.

Идиома ForEachAsync

Давайте продолжим рассматривать приемы, которые будут полезными при работе с TPL.

В прошлый раз мы рассмотрели идиому, которая позволяет обрабатывать результаты в порядке окончания работы задач, а не в порядке их запуска. Но там был пропущен один интересный момент. Вот, например, у нас есть все тот же сервис погоды и желание получить результаты по всем городам как можно быстрее. Означает ли это, что можно взять все города мира и послать одновременно тысячи запросов? Сервис погоды может посчитать, что клиент сошел с ума и попробует затроттлить (throttle) запросы, превышающие определенный лимит (кстати, этот самый троттлинг – это один большой pain in the ass для всех облачных сервисов, причем как для авторов сервисов, так и для клиентов этих самых сервисов).

Так вот, нам нужно как-то ограничить число таких запросов или каких-то других асинхронных операций.

Вообще, с ограничением числа задач есть одна небольшая беда. В случае CPU Intensive операций (числодробилки, операции, которые нагружают CPU/GPU) есть простая эвристика – число работающих задач должно быть ограничено числом вычислительных устройств. Но, в случае с IO Intensive операциями таких ограничений нет. Более того, нет и встроенных инструментов для контроля за числом таких операций.

воскресенье, 28 июня 2015 г.

Идиома Process Tasks By Completion

При работе с тасками часто возникает такая задача: у нас есть набор входных данных и для обработки каждого элемента используется длительная операция.

Можно подойти к этой задаче в лоб. Крутим цикл, запускаем таски, обрабатываем результаты по одному:

private Task<Weather> GetWeatherForAsync(string city)
{
   
Console.WriteLine("[{1}]: Getting the weather for '{0}'"
, city,
       
DateTime.Now.
ToLongTimeString());
   
return WeatherService.
GetWeatherAsync(city);
}


[
Test]
public async Task
ProcessOneByOneNaive()
{
   
var cities = new List<string> { "Moscow", "Seattle", "New York"
};

   
var tasks =
        from city in
cities
       
select new { City = city, WeatherTask =
GetWeatherForAsync(city) };

   
foreach (var entry in
tasks)
    {
       
var wheather = await entry.
WeatherTask;

        ProcessWeather(entry
.
City, wheather);
    }
}

private void ProcessWeather(string city, Weather
weather)
{
   
Console.WriteLine("[{2}]: Processing weather for '{0}': '{1}'"
, city, weather,
       
DateTime.Now.ToLongTimeString());
}

Здесь мы обращаемся к некоторому сервису погоды, для получения температуры в каждом городе, затем обрабатываем полученные результаты путем вывода города и температуры на экран.

четверг, 18 июня 2015 г.

Небольшой трюк при работе с ConcurrentDictionary

У использования ConcurentDictionary есть одна особенность: в некоторых случаях он может вести себя не совсем так, как вы того ожидаете. Вот небольшой пример. Допустим, нам нужно запилить небольшой кэш, чтобы результаты дорогостоящей операции брались из кэша, если они там есть, ну и добавлялись в кэш прозрачным образом, если Акела промахнулся.

Простая реализация некоторого провайдера с cache aside паттерном будет выглядеть примерно так:

public class CustomProvider
{
   
private readonly ConcurrentDictionary<string, OperationResult> _cache =
        new ConcurrentDictionary<string, OperationResult>
();

   
public OperationResult RunOperationOrGetFromCache(string
operationId)
    {
       
return _cache.GetOrAdd(operationId, id =>
RunLongRunningOperation(id));
    }

   
private OperationResult RunLongRunningOperation(string
operationId)
    {
       
// Running real long-running operation
        // ...
        Thread.Sleep(10
);
       
Console.WriteLine("Running long-running operation"
);
       
return OperationResult.Create(operationId);
    }
}

 

пятница, 12 июня 2015 г.

Синдром “придумано не нами”

Ваш код сегодняшний, коллега
Напоминает даунхил:
Среди деревьев и гов#@ща –
Велосипед и костыли ...
Народная мудрость

Пару лет назад я сделал небольшой цикл заметок о паттернах поведения: Технический долг, Синдром рефакторинга и Эффект второй системы. Пришло время обсудить еще один, наверное, самый известный и популярный паттерн поведения – синдром «Придумано не нами» (NIH, Not Invented Here).

Мало кто любит чужой код. Букв в нем обычно много, докапываться до сути сложно, читать между строк получается не у всех, а читать мысли автора без хрустального шара и крови ягненка пока вообще не научились. Другое дело, пилить что-то с нуля: система развивается поэтапно, ты знаешь, какие были компромиссы на каждом шаге разработки и понимаешь, почему было принято то или иное решение. Ты учишься, поскольку информация о системе аккуратно складывается в голове в цельную картину. Но как только на твоем месте оказывается другой человек, то он, почему-то, не ценит твои усилия и стремиться все выкинуть и переписать заново.

У «забить на существующее и сделать по-своему» есть несколько причин.

понедельник, 8 июня 2015 г.

Обязательные аргументы в PowerShell

Я не понимаю PowerShell. А раз так, то нужно попробовать устаканить свои знания и поделиться ими с миром.

Главная проблема PowerShell, ИМХО, – динамическая типизация и «адаптивная» система типов. PowerShell всеми силами старается избежать ошибки времени исполнения путем конвертации типов туда и обратно (Хоббит, блин!).

Чтобы избежать этого, я стараюсь сделать контракт методы максимально четким. Если что-то должно быть строкой, то я хочу упасть как можно раньше, если кто-то подсунет что-то другое. Если аргумент не может быть Null, то падать нужно как можно раньше, а не передавать его дальше по стеку вызовов. Если аргумент является обязательным и пользователь забыл его указать, то нужно четко сказать об этом, а не просить пользователя ввести его руками.

Параметр метода в PowerShell может быть $Null в одном из двух случаев: пользователь явно передал $Null в качестве значения аргумента. Или же пользователь вообще не указал данный аргумент при вызове метода. Мне, как автору метода, обычно все равно, почему параметр отсутствует. Я просто хочу гарантировать, что он не будет Null. Но, чтобы добиться этого, придется использовать разные подходы.

понедельник, 11 мая 2015 г.

Майкрософт, часть 2. Карьерная лестница

Все, о чем я здесь пишу, является моим личным мнением, которое не является официальным мнением моего работодателя. Так, на всякий случай!

С момента начала работы в Майкрософте уже прошло 8 месяцев, а значит уже можно сравнить местную внутреннюю кухню с кухней отечественной.

Киевские софтверные «гиганты» и общая культура IT компаний очень сильно отличаются от американских. Прежде всего, это связано с культурными отличиями, средним возрастом сотрудников и размерами компаний. Средний возраст влияет на то, как ведут себя люди в офисе, как они одеваются, и о чем говорят на кухне или в курилке. Средний возраст сотрудников киевской IT компании существенно ниже, чем в американской или европейской. Этот показатель у нас тоже начинает расти, но разница все еще остается очень существенной. Прибавьте сюда наш менталитет и общительность, и получите довольно большую разницу в том, как проходит неформальное общение. В киевском офисе ржачь стоял с завидным постоянством, ничего подобного в Штатах я не видел. Хотя вру, в нью-йорской конторе такое было, прямо перед тем, как ту команду разогнали;)

Средний возраст и размер компаний очень сильно влияют на карьерный рост. В украинской компании, если тебе 25 и ты не синьер, то ты явно что-то делаешь не так. Это же приводит к определенным проблемам, когда тебе тридцать и у тебя есть амбиции расти в техническом плане. У нас (да, я все еще отношу себя к «нам») относительно легко продолжить расти в тим-лидах или ПМ-ах, но чисто техническая лестница оказывается довольно короткой. Есть позиция архитектора, но архитектор в 30 – это все же вынужденная мера отечественного аутсорса для выделения касты «продвинутых синьеров», их нельзя сравнивать с архитекторами МС-а или Гугла. Поверьте.

четверг, 16 апреля 2015 г.

Разница между шаблонами и паттернами

Выбор правильного термина – дело непростое. Выбор русскоязычного варианта – еще и неблагодарное. Занимаясь научным редактированием переводов книг по IT-тематике я всегда сталкивался с проблемой выбора правильного русскоязычного варианта. Сложность заключается в отсутствии единого мнения по поводу перевода некоторых важных терминов, что приводит к проблеме выбора «наименьшего зла» между распространенным, но неточным термином и более емким, но никому неизвестным вариантом.

С термином “pattern” тоже была интересная история. Изначально, этот термин был переведен как «шаблон», и в первых книгах начала нулевых использовался в основном этот термин, а спустя некоторое время, все больше стал набирать популярность вариант «паттернов проектирования».

Сам по себе, выбор русскоязычного термина не играет большой роли, если у пользователя термина формируется правильное понимание того, что за ним кроется. Человек склонен проводить параллели между новым термином и известными ему понятиями, что может сослужить плохую службу.

среда, 8 апреля 2015 г.

Как правильно развиваться?

Это несколько расширенная версия ответа на похожий вопрос, который был задан в русскоязычном ru.stackoverflow.com. А поскольку повторное использование – это наш все, к тому же, этот вопрос мне задают с завидным постоянством, то я решил оформить свои мысли отдельным постом.

Эффективное развитие – это очень субъективная тема. Это значит, что если что-то подходит мне, это не обязательно подойдет и тебе. Самое главное для саморазвития – это стабильная мотивация в течение длительного времени. И только вы сможете найти правильный баланс между теорией и практикой, подобрать правильную частоту переключения между темами и найти стимул к изучению чего-то нового.

«Правильно» в этом вопросе означает баланс между затраченными усилиями и результатом, который будет оптимальным и эффективном именно для тебя. Несмотря на индивидуальность этого процесса, в процессе развития есть несколько важных моментов, которые могут упростить этот путь.

  1. Хорошие источники
  2. Упор на получение стабильных знаний
  3. Итеративность обучения и практика
  4. Относительно четкий план развития
  5. Разнообразие тем
  6. Мотивация

Теперь по порядку.

понедельник, 6 апреля 2015 г.

Кэширование объектов StringBuilder

В текущем проекте народ очень серьезно подходит к вопросам производительности: куча структур, кастомный внешний кэш, и свой собственный object pool для хранения тяжеловесных объектов. Одним из типов объектов, которые хранятся в пуле и используются повторно являются объекты StringBuilder. И я задался вопросом, насколько это полезно.

Начиная с .NET 4.0 реализация StringBuilder-а была существенно переработана. В первых версиях реализация напоминала классический вектор – для хранения создаваемой строки использовалась изменяемый объект System.String (*), размер которой увеличивался вдвое при ее полном заполнении.

(*) Строки являются неизменяемыми лишь с точки зрения внешних кода, но с точки зрения внутреннего (internal) кода pre-.NET4.0 строки были очень даже изменяемыми.

вторник, 31 марта 2015 г.

Предусловия в конструкторах наследников

Существует одна типичная проблема с проверкой аргументов в конструкторах классов-наследников, которые должны передавать «куски» своих аргументов базовому классу. Простой пример этой проблемы выглядит так:

abstract class Base
{
   
private readonly int _length
;

   
protected Base(int length
)
    {
       
if (length <= 0) throw new ArgumentOutOfRangeException("length"
);

       
_length = length
;
    }
}

internal class Derived : Base
{
   
public Derived(string s
)
        :
base(s.Length
)
    {
       
// Проверка бесполезна!
        if (string.IsNullOrEmpty(s
)) throw new ArgumentNullException("s");
    }
}

Проблема в том, что конструктор базового класса вызывается до тела метода конструктора Derived (*). В результате, если конструктор наследника принимает составной объект и «выкусывает» часть, которая нужна конструктору базовому классу, то нормально проверить валидность составного объекта не получиться.

понедельник, 23 марта 2015 г.

Простой Syntax Highlighter на базе Roslyn

Roslyn – очень классная штука, с помощью которой можно не только анализаторы делать, но и много других интересных штук.

Вот, например, сколько потребуется усилий, чтобы сделать раскрашиватель синтаксиса, который будет печатать C#-файл в консоль и подсвечивать ключевые слова, строковые литералы и т.п вещи?

Вот как это можно сделать.

пятница, 20 марта 2015 г.

О разработке ПО и книге Крега Лармана “Applying UML and Patterns”

DISCLAIMER: это моя типичная рецензия, в ней больше рассуждений на тему книги, чем информации о самой книге! Так что, не проходите мимо!

У стандартного процесса обучения есть интересная особенность. Как только мы решили узнать что-то новое, мы садимся за учебники, идем на курсы и получаем новые знания всеми доступными способами. Через время мы говорим себе «Фффатит!», забиваем на обучение и переходим к практике (на ранних этапах теория переплетается простыми практическими задачами, но они не оказывают существенного значения). После чего, мы начинаем применять наши новые знания на практике, и через время они практически полностью выветриваются из нашей славной головешки и их место занимает опыт.

Итак, что мы имеем? А имеем мы водопадную модель развития, когда на ранних этапах идет обучения, после которого начинается практика. И в чем проблема? А проблема здесь аналогична водопадной модели разработке ПО. Мы просто не в состоянии без должного опыта осознать все прелести сакральных знаний, которые нам пытаются вбить в голову на этапе обучения. У нас еще нет собственных набитых шишек, чтобы оценить эти советы по достоинству.

воскресенье, 15 марта 2015 г.

О роли сборок

В наших с вами интернетах (точнее, у меня в Г+) развернулась небольшая дискуссия на предмет того, когда стоит выделять сборки (.NET Assemblies) в приложении, а когда нет. Там же развернулась и еще одна дискуссия на предмет того, что считать слоем (layer), а что считать слоем (tier). Обсуждение последнего вопроса придется пока отложить, а сегодня я хочу поговорить подумать о том, когда нужно выделять сборки.

ПРИМЕЧАНИЕ
Вот Г+ запись (Лейеры, и Тиры, и Партиции), в которой я цитирую Лармана с объяснением исходной терминологии понятий layer, tier и partition.

Любой букварь про C# и .NET, коих написано over 9000, говорит о том, что сборка (assembly) – это единица развертывания (deployment). Там же обычно говорится о том, что они (сборки) версионны и что CLR обладает мощной системой поиска правильной версии, со всеми GAC-ами, assembly redirect-ами и прочей магией. Что dll hell позади, и теперь мы наконец-то можем заменить одну сборку приложения прямо в продакшне, не сломав все к чертям собачим!

вторник, 10 марта 2015 г.

Анализатор исключений на базе Roslyn-а

Уже давно хотел поразбираться с анализаторами на основе Розлина. Тем более, что меня уже был опыт создания плагинов для Resharper-а (R# Contract Editor Extension), поэтому хотелось сравнить разные инфраструктуры и удобство использования. Есть идея переписать этот плагин с помощью анализаторов Roslyn-а, но я решил начать с чего-то попроще.

Цель недельного проекта была такая: сделать простой анализатор, который будет показывать типовые ошибки обработки исключений. Самые болезненные с моей точки зрения такие:

  • Повторная генерация исключений с помощью throw ex;
  • “Проглатывание” всех исключений с помощью пустых блоков catch {} или catch(Exception) {}.
  • “Проглатывание” исключений в определенных ветках блока catch.
  • Сохранение в логгах только сообщения ex.Message, теряя при этом потенциально важную информацию о месте возникновения исключения.
  • Некорректное пробрасывание новых исключений из блока catch.

понедельник, 2 марта 2015 г.

Закрытый конструктор базового класса

Вопрос: может ли конструктор абстрактного базового класса Base быть закрытым? Возможно ли в этом случае создать класс-наследник Derived и его экземпляр?

abstract class Base
{
   
// WTF! Что с этим делать!
    private
Base()
    {
       
Console.WriteLine("B.ctor");
    }
}

Очевидно, что я бы не задавал этот вопрос, если бы сделать это было невозможно. Существует два способа создать наследника базового класса с закрытым конструктором: один вполне вменяемый и второй, совершенно невменяемый.

четверг, 26 февраля 2015 г.

О сложности

Фред Брукс в своем «Мифическом человеко-месяце» еще 30 лет назад описал пару понятий, которые я считаю ключевыми в проектировании. Это понятия случайной (accidental) и естественной (essential) сложности.

Разница между ними в том, что естественная сложность является частью самой задачи и от нее невозможно избавиться. Случайная сложность привносится в процессе решения и обусловлена ошибками проектирования, плохим выбором языка программирования или базы данных, неудачной декомпозицией системы и просто грязным кодом. Все эти иерархии наследования, принципы проектирования, cohesion & coupling, все это направлено на уменьшение случайной сложности. На то, чтобы обуздать естественную сложность задачи и сделать ее максимально очевидной.

Мне кажется, очень важно осознавать разницу между этими понятиями.

Сколько раз вы ловили себя на мысли, что совершенно не можете понять, что же делает некоторый код? Вы видите кучу блоков if-else, switch, foreach, перехват и логирование исключений. Все это хорошо. Но, какую же задачу этот код решает на самом деле? Затем вы начинаете распутывать этот клубок, добавляете комментарии, выделяете новые методы, переносите обработку исключений на более высокий уровень, и оказывается, что решается очень простая задача, которую можно описать парой предложений.

вторник, 6 января 2015 г.

Ретроспектива 2014

Прошел Новый Год, на носу Рождество, а значит пришло время подводить итоги прошедшего года.

Этот год был практически полностью посвящен паттернам и принципам проектирования. В основном из-за того, что я таки решился на написание книги, а публикация черновых материалов в блоге дает очень полезную обратную связь и повышает мотивацию.

Специфичных постов о языке C# практически не осталось, хотя хорошо это или плохо, сказать сложноJ. В этом году я планирую добить книгу по паттернам, а значит, часть постов будет посвящено именно этой теме. С переходом в Майкрософт времени стало немного меньше, но желание писать пока не убавилось.

Ниже представлен перечень наиболее интересных и значимых постов, сгруппированных по тематике. Гляньте, а вдруг чего-то интересное пропустили!

SOLID принципы
Паттерны проектирования
Философия программирования
Другое
C#/.NET
Книги

З.Ы. Я беру перерыв в блоггинге где-то на месяц. Надеюсь, что этого времени хватит, чтобы добить книгу по паттернам и отправить ее для редактирования.