15 ноября 2013

Books and films

Около года назад я прочитал книгу Ender’ game автора Orson Scott Card. Книга мне понравилась, читал в оригинале. Изначально цель была улучшить английский, и, чтобы не забросить, выбрал любимый жанр – фантастику. После первой книги автор не остановился и написал еще несколько, но начав читать одну из них мне стало скучно – видимо Ender’s game выглядела для меня настолько законченным произведением, что не хотелось портить впечатление сиквелами. А вот недавно с удивлением обнаружил что по книге сняли одноименный фильм. Хочу сходить посмотреть.

Кроме того, снова проснулся интерес к фантастике – и теперь я думаю что бы еще такого прочитать.

07 ноября 2013

программист = рабочий

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

Для разработчика важно знать, как общаться с компьютером и как - с людьми. Если человек не умеет общаться с людьми, то, скорее всего, его умение рассказывать компьютеру «что делать» вам не пригодится.

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

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

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

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

02 ноября 2013

Brainbench

Недавно закончились игры на Brainbench. Это такое событие, когда они открывают все свои тесты для бесплатного доступа (обычно тесты стоят 50 долларов) и ведут статистику, из какой страны больше тестов сдали. Вот результаты, штаты впереди, Украина в тройке лидеров.

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

Сдавая тесты, обнаружил интересную приписку на leaderboard о том, что набравший на играх больше всех баллов в каком-то тесте получит годовую подписку. А также обнаружилось, что тесты по .NET Framework и C# имеют общие вопросы (т.е. я встречал в одном тесте вопросы, которые уже видел в другом) – это облегчило прохождение. А так как тестов по .NET Framework там 6 штук, а по C# – 7, то результаты улучшались с каждым тестом. В итоге, получилось сдать C# 3.0 Fundamentals на 5, что и принесло мне в итоге годовую подписку – вот только я не уверен что буду ей пользоваться.

Еще оказалось что по ADO.NET 2, который я сдавал только чтобы закрыть job role, тоже набралось больше всех (хоть и не 5). Если честно, я слегка удивлен результатам, такое впечатление, что тесты попросту не привлекали особого внимания и потому легко было попасть в лидеры.

Что касается качества тестов, то ощущения смешанные – некоторые вопросы были из разряда выбрать метод среди похожих, другие требовали опыта в определенной области. Если сравнивать с Microsoft – то brainbench мне нравится больше. Как мне кажется основная проблема онлайн тестов – это количество вопросов. Рано или поздно вопросы начинают повторяться и это дает возможность идти на тест уже зная ответы. Те попытки защитить вопросы от копирования, предпринимаемые, например, Microsoft, не особенно продуктивны. Думаю, что решением было бы менять вопросы в тесте на протяжении всего времени что тест доступен для сдачи – но тут не обойтись без дополнительных вложений. В итоге, баланс между качеством тестов и вложениями каждый выбирает сам.

Ссылка на мой профиль на brainbench

Статья на DOU про Brainbench Games

20 сентября 2013

Achievements

Прошел сегодня 12,5К шагов, за раз. При моей длине шага, это немного больше 9,5 километров.
Интернет полон статей о том, сколько именно стоит проходить в день, почему это полезно и полезно ли вообще. Я думаю, что при офисном образе жизни стоит пользоваться любой возможностью разообразить двигательную активность - больше ходить, заниматься чем-нибудь в спортзале. Спортзал априори неудобен расположением (насколько я знаю, в радиусе 20 мин ходьбы нет приличного спортзала). Хороший зал дорого стоит, дешевый зал плох по определению. Мой выбор - турники и прогулки.

Проверил свой аккаунт на Coursera - появился statement of accomplishment по курсу Algorithms: Design and Analysis, Part 1 - ну, чего и следовало ожидать. Начал смотреть лекции по курсу Algorithms: Design and Analysis, Part 2, на который записался еще летом. Оказалось что уже 3 недели как идет и дедлайн первой домашки уже прошел - не беда, еще есть возможность наверстать. Еще начинаю курс Analysis of Algorithms, он тоже начался 3 недели назад. В моем списке текущих курсов есть еще два, но я не уверен что у меня будет время для них - есть и много других планов. Из Coursera, издеваясь, прислали письмо, что у них скоро стартуют 80 курсов и у них есть для меня рекомендации.

19 сентября 2013

Javascript by Flanagan

Дочитал книгу Javascript The Definitve Guide by David Flanagan.
К сожалению, сравнить в плане Javascript мне не с чем, но тем не менее - книга действительно описывает очень многие аспекты JS-разработки. Рассказывается как о самом языке, так и о том, как его применять - клиентские API, серверные, библиотеки, перспективы развития.

Первая часть книги - описание языка, вторая - API на клиенте (браузере), третья и четвертая - справочники. Справочники не читал :)
Не очень понимаю, зачем они тут. Прочитав справочник - его не запомнишь, а при разработке online-ресурс удобнее листания книги. И, к тому же, книга не обновляется.

Моя точка зрения на JS немного поменялась, узнав как устроено ядро языка, теперь будет намного проще в отладке. Кроме того, стало ясно отчего jQuery так популярна - без подобных библиотек разрабатывать что-то, что может работать во всех основных браузерах - сущий ад.

Книгу я бы рекомендовал всем, кто берется за client-side разработку. Будет намного больше понимания что, как и почему работает.


26 августа 2013

Algorithms

Завершился курс Algorithms: Design and Analysis by Tim Roughgarden, это первая часть. Вторая часть начнется в сентябре, через неделю.

В этом году я уже проходил курс по алгоритмам, от Боба Седжвика, этой осенью будет повтор:
Algorithms, Part I
Algorithms, Part II

Курс Седжвика мне понравился больше. Мне он показался более структурированным, логичным, лаконичным. Начиная с простых алгоритмов, на их основе идет рассказ о более сложных. Отдельного слова заслуживает механизм оценки домашних заданий - задание должно удовлетворять ряду критериев, помимо правильности ответа. Поскольку результатом задания является код на Java - он должен пройти ограничения по корректности результатов, соответствия заданному API, размеру памяти, скорости исполнения и стилю кодирования. Впрочем, за стиль штрафных очков не начислялось.
Тема курса - алгоритмы - и он рассказывает о сортировках, деревьях, графах, архивации, о разных проблемах в этих областях и способах их решения.

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

А еще, осенью анонсирован курс Седжвика Analysis of Algorithms.
Боб - довольно известная личность в computer science. Его научным руководителем был Дональд Кнут, возможно это имя покажется вам знакомым :)
Так что я рекомендую курсы по алгоритмам к прохождению. Мало того что это освежает знания (либо восполняет пробелы) - так еще и код писать интересно.

21 июня 2013

Знакомство с Moq

Moq - один из популярных фреймворков для создания mock-объектов. Его возможности широки настолько, насколько позволяет наследование в .NET. Под капотом - Castle, как и у Rhino.Mocks. В Moq нет разнообразия типов создаваемых объектов - они все mock-и. Есть только два режима работы mock-ов - это упрощает понимание и работу.
А вот что усложняет - так это то, что кроме собственно генерируемых объектов, Moq использует экземпляры класса Mock для настройки поведения объекта и проверок, было ли вызвано то, что ожидалось. Дальше по тексту Mock означает конкретный класс, а mock - сгенерированный экземпляр нужного нам типа. Для примеров я буду использовать вот такой интерфейс:
public interface IRepository
{
    string ReadData();

    string Storage { get; set; }

    void SetData(object o);

    event EventHandler OnReading;
}

Создание объектов

Объект можно создать несколькими способами.
Во-первых, можно вызвать
Mock<IRepository> mock = new Mock<IRepository>();
Этот конструктор создает Mock как для класса так и для интерфейса. Есть перегруженные варианты - можно указать режим, в котором должен работать mock, и параметра конструктора, если надо создать mock для класса, в котором нет конструктора по-умолчанию.
Режимы - это:
  • Loose - никогда не бросает исключений, пытается вернуть значения по-умолчанию
  • Strict - бросает исключения если вызван метод\свойство, поведение которого не задано предварительно.
Второй способ создания, это получить сразу mock-объект:
IRepository repo = Mock.Of<IRepository>();
Можно получить бесконечную коллекцию и выбрать столько экземпляров, сколько нужно:
IQueryable<IRepository> repos = Mocks.Of<IRepository>();
Чтобы получить возможность настроить поведение - для mock-объекта нужно получить соответствующий экземпляр Mock класса:
Mock<IRepository> mock = Mock.Get(repo);

Что может Mock

Этот класс дает возможность настроить поведение mock-объекта, выполнить проверки.
Вот его свойства:
  • Behavior - посмотреть в каком режиме был создан, Loose или Strict
  • CallBase - надо ли вызывать базовый класс, если не заданы ожидания
  • DefaultValue - что именно возвращать в режиме Loose. Можно возвращать null для reference-типов, а можно попытаться для них тоже создавать mock-и (для sealed классов mock создать не получится)
  • Object - экземпляр mock-объекта


Настройка поведения

Для настройки поведения есть куча методов:
  • Setup нужен для задания ожиданий для методов, возвращающих значения.
  • SetupGet - для вызова getter-ов свойств
  • SetupSet - для setter-ов свойств
  • SetupProperty - задает "property behavior" для свойства. Это значит, что свойство будет работать как хранилище: что ему присвоили - то и возвращает.
  • SetupAllProperties - то же что и SetupProperties - только для всех свойств скопом
Вся эта куча методов позволяет настраивать ожидания, используя цепочку вызовов (Fluent интерфейс): сначала задается член класса, потом - что он возвращает. Например:
mock.Setup(r => r.ReadData()).Returns(() => "some result");

mock.Setup(r => r.ReadData())
     .Callback(() => Console.WriteLine("Read call"))
     .Throws<ApplicationException>();

mock.Setup(r => r.ReadData()).Verifiable();

Довольно интуитивно: Returns задает что возвращать, Throws - что бросать, Callback - что вызывать.
Verifiable нужен для валидации. Все Verifiable ожидания будут проверены скопом при вызове Verify().

Есть еще SetReturnsDefault - он задает значение по умолчанию для некоего типа. Например String    это value тип. Соотвественно по умолчанию его значение - null. Но это можно изменить:
mock1.SetReturnsDefault("abc");
Теперь все значения строк по-умолчнию для mock1 будут "abc".

Если неизвестны заранее значения аргументов, передаваемых членам класса - это можно учесть с помощью класса It.
mock.Setup(r => r.SetData(It.IsInRange("a", "c", Range.Exclusive)));
mock.Setup(r => r.SetData(It.IsAny<int>()));
mock.Setup(r => r.SetData(
    It.IsRegex("^4[0-9]{12}(?:[0-9]{3})?$")));//VISA credit card
Можно вообще любой код проверки подключить:
Expression<Func<string, bool>> fridayPredicate =
    v => v == "HelloWorld" &&
    DateTime.Now.DayOfWeek == DayOfWeek.Friday;
mock.Setup(r => r.SetData(It.Is(fridayPredicate)));

Настройка валидации

Здесь Fluent интерфейса нет, а есть куча методов Verify, аналогичных Setup.
Можно проверить все заданные ожидания, помеченные как Verifiable - или просто все, вне зависимости от помеченности (методы Verify и VerifyAll).
Есть возможность проверить, был ли вызов конкретного члена класса. При проверке конкретного свойства\метода можно указать сообщение об ошибке и сколько раз должен был быть совершен вызов (куча вариантов - начиная от Never до диапазона).
var mock = new Mock<IRepository>();

mock.Verify();

mock.VerifyAll();

mock.Verify(r=>r.ReadData(), "Read Data was not called");
mock.Verify(r=>r.SetData(123));

mock.VerifyGet(r => r.Storage, Times.AtLeast(4));

mock.VerifySet(r => r.Storage = "", 
    Times.Between(1, 10, Range.Exclusive));

Для проверки параметров можно использовать уже знакомый класс It:
var mock = new Mock<IRepository>();

mock.Object.Storage = "b";

mock.VerifySet(r=>
    r.Storage = It.IsInRange("a", "c", Range.Exclusive));

События

Интересная возможность Moq - это работа с событиями. Для этого у класса Mock есть метод Raise. В качестве первого параметра передается делегат, который должен добавлять обработчик тому событию, которое нужно вызвать. Второй параметр - EventArgs для события. Хитрость в том, что Moq выполняет делегат в особом контексте, отслеживая какие вызовы каких членов класса были сделаны. Фреймворк ловит add метод события и понимает какое именно событие нужно вызвать. Метод может вызывать только virtual события (что логично - не virtual события могут быть инициированы только классом в котором они объявлены).
Выглядит вот так:
string called = "one";

var mock = new Mock<IRepository>();
IRepository repo = mock.Object;
repo.OnReading += (sender1, eventArgs) => { called += "called"; };

EventHandler sampleHandler = (sender, args) =>
    { throw new NotImplementedException(); };

mock.Raise(r => r.OnReading += sampleHandler, new EventArgs());

Assert.AreEqual(called, "onecalled");

Код присваиваемого делегата не важен - Moq перехватывает присваивание и не производит его фактически.

Заключение

Фреймворк довольно легкий и гибкий в использовании, интерфейс интуитивен и прост в освоении, нет излишней сложности, оставшейся из-за процесса развития библиотеки. Устаревшие конструкции помечены [Obsolete], код хорошо документирован.

Исходники выглядят неплохо, откровенной лапши не наблюдается, используются атрибуты [SuppressMessage] для управления анализом кода - почистить сообщения на методах, которые не могут быть сделаны иначе by design.

Я описал не все конструкции Moq, в нем есть еще чем воспользоваться, но, на мой взгляд, в сложных случаях возможностей может не хватить. Например: нет легкого пути проверить очередность вызовов (что вызовы совершаются в определенном порядке). Хотя необходимость подобных тестов сомнительна, уж слишком хрупкие они будут.

Moq понравился мне больше чем Rhino.Mocks, в обоих есть свои плюсы и минусы, но простота и организованность победили.

27 мая 2013

Знакомство с Rhino Mocks

Rhino Mocks, фреймворк для создания mock-объектов, появился в 2005 году. Изменений в нем не происходило уже два года и недавно автор объявил о том, что не собирается его больше поддерживать. Потом нашелся доброволец, готовый взять проект в свои руки. Я просмотрел исходники - ему там будет чем заняться. Код запущен, документацию фиг найдешь.
Вот, в 2011 последний раз обновлялось.

13 мая 2013

mocking frameworks

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

05 мая 2013

18 записей

За время существования блога в нем набралось 17 сообщений, приблизительно по 7 сообщений в год, реже, чем раз в месяц.
Это показывает, что смысл существования этого блога - "чтоб было".
По крайней мере, таким смысл был раньше.

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

04 апреля 2013

Authentication and authorization

Эти два понятия часто путают.

Authentication - это процесс подтверждения, что Вася - это Вася. Он нужен для того, чтобы Петя не мог представиться Васей и сделать что-нибудь плохое от его имени. Пример - вход на сайт с логином и паролем. Проблемы этого процесса - это хитрые Пети, придумывающие как все-таки представиться Васями, обманув систему.

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

Authentication обычно происходит до Authorization.

28 марта 2013

NET сегодня

Jeff Atwood переключился на Ruby.

В каком-то смысле он прав.

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


.NET на коротком поводке Microsoft, технологии меняются очень быстро. Я бы не стал сейчас изучать Silverlight или Windows Phone. Может потому, что Windows Phone 7 быстро оказался не у дел? Или потому что у Silverlight не видно будущего? Нет никаких гарантий, что завтра, технологию, которую вы используете для разработки, не будет решено заменить другой. 
Популярных open-source проектов на WPF, Silverlight, Windows Phone я тоже не наблюдаю. NET, конечно, мощная штука - но только для разработки под MS инфраструктуру. Если у вас нет Windows - вам не нужен NET. А если есть, то неплохо бы еще Visual Studio. И MS SQL Server. Целая корзина продуктов, связанных друг с другом. 

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

08 января 2013

make it so

Compiler that accepts "make it so" hasn't been invented. Yet.