среда, 10 декабря 2008 г.

Книга Кента Бека "Шаблоны реализации корпоративных приложений"

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

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

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

В целом, достаточно интересно и занимательно, если бы не ряд "но".

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

Во-вторых, это перевод. Книга называется "Шаблоны реализации корпоративных приложений", причем "корпоративные приложения" придуманы отечественными локализаторами и в названии оригинала не фигурируют. Если следовать принципам, на основе которых переведена эта книга, то она должна называться так: "Паттерны имплементации интерпрайзных аппликаций". В книге в огромном количестве встречаются "имплементации", "репрезентации", "вариации", "декларации" и множество других неверно переведенных терминов. При чтении мне вспомнился перевод инструкции к усилителю Pioneer: "Усилитель предназначен для подключения дигитальных компонентов с трехдиминзионным звуком". Помимо ужасного перевода терминологии, многие предложения построены так, что понять замысел автора практически невозможно. К этому нужно добавить Smalltalk прошлое Кента Бека и его непривычную терминологию, которая добавляет сложность к восприятию материала.

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

Книга Тома Демарко и Тимоти Листера "Человеческий фактор: успешные проекты и команды"

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

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

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

Авторы значительное внимание уделяют месту обитания разработчика - офисной среде. Они описывают причины потери времени и меры, которые можно предпринять для создания стабильной, способствующей работе обстановки. И если вопросы "мебельной полиции" могут быть не слишком актуальны для вашей организации, другие вопросы, связанные с офисной средой являются очень важными. Так, одной из проблем, о которых стоит задумываться каждому из нас, является состояние глубокого, почти медитативного погружения в работу (авторы называют это состоянием потока) и то, насколько офисная среда препятствует этому. "Если в среднем входящий телефонный звонок отнимает пять минут, а ваш период повторного входа в поток - пятнадцать минут, общая стоимость такого звонка, исчисляемая в потерянном времени потока (непосредственной работы), - двадцать минут. Десяток телефонных звонков израсходуют половину рабочего дня. Еще десяток других вмешательств и вот уже рабочий день пропал".

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

P.S. Книга написана удивительно простым языком, содержит много лирических отступлений из практической деятельности авторов в качестве руководителей или консультантов. Книга однозначно must have для каждого, кто работает в коллективе, занятом интеллектуальным трудом и совсем не обязательно этим трудом является разработка программного обеспечения.

среда, 3 декабря 2008 г.

Книга Джозефа C. Раттца-мл. "LINQ. Язык интегрированных запросов в C# 2008 для профессионалов"

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

Не является исключением из этого правила и новая технология Майкрософт под названием Language Integrated Query (LINQ) призванная решить многие проблемы доступа к данным, которые возникают у разработчика в его повседневной деятельности. И в связи с огромным вниманием к этой технологии со стороны разработчиков, первая книга по LINQ, переведенная на русский язык, также будет крайне востребованной. В связи с этим хотелось бы знать стоит ли она потраченного времени и денег.

Для начала хотелось бы отметить тот факт, что сам автор в течение длительного времени хотел написать какую-либо книгу, но никак не мог выбрать для этого подходящую тему. Либо он слишком слабо разбирался в предмете, либо об этом уже было написано достаточно и не было смысла в появлении еще одной книге по данной тематике. И вот в 2005 году, узнав о работе Майкрософт над новой технологией, Джозеф Раттц пришел к выводу, что это именно то, что нужно. И не страшно, что он об этой технологии не имел ни малейшего понятия, главное, что о ней также не знал и никто другой. Итак, выбор пал на LINQ и спустя 17 месяцев плодотворной работы в ноябре 2007-го года одновременно с официальным выходом Visual Studio 2008 (а вместе с ней и технологии LINQ) в свет вышла книга с незамысловатым названием "Pro LINQ Language Integrated Query In C# 2008".

Книга состоит из 5 частей. В первой части автор рассматривает нововведения C# 3.0, без которых существование LINQ было бы невозможно. Эта тема достаточно избита, ей уделено большое количество внимания в различных источниках, поэтому сказать об этой части ничего нельзя, ни хорошего, ни плохого.

Часть 2 книги полностью посвящена LINQ to Objects. Помимо пространных рассуждений на тему доступа к данным, восхищением новыми возможностями и краткому обзору Query Expressions, основная доля этой части приходиться на описание методов расширения. Причем автор поставил перед собой цель описать каждую перегруженную версию каждого метода, и даже если методы практически ни чем не отличаются друг от друга, все равно им посвящается отдельный раздел с кратким описанием и примером использования. Примеры - это отдельная тема для разговора. Чтобы они были самодостаточными, каждый пример состоит из трех частей: получения тестовых данных (5-6 строк), запрос (1-2 строки), результаты (до 1 страницы). Сложив все это вместе, мы получаем более ста страниц текста, с надуманными примерами, несмешными шутками автора и отсутствием полноценной картины в голове у читателя. Эту сотню страниц, можно смело заменить одной нормальной статьей по LINQ to Objects и справкой Майкрософт.

Помимо этого, в тексте встречаются и откровенные "ляпы". Вот, например, автор указывает в одной из своих заметок, что операция OrderBy является нестабильной (unstable), в то время как операция ThenBy является стабильной (stable), хотя официальная документация Майкрософт придерживается несколько иного мнения (обе операции являются стабильными). Но более интересен не сам факт приведения неверного совета, а то, что я нашел на сайте Майкрософт обсуждение, в котором некий Джозеф Раттц обсуждает стабильность/нестабильность операции OrderBy с одним из сотрудников Майкрософт. И в рамках этого обсуждения, дается четкий ответ на то, что операция OrderBy является стабильной и почему поведение этой операции именно таково. Данное обсуждение датировано маем 2007 года, но, видимо, сроки давят не только на разработчиков программного обеспечения, но и на авторов книг, поэтому Джозеф Раттц не успел исправить эту досадную промашку к выходу книги в ноябре 2007 года.

Теперь перейдем к части 3 LINQ to XML. Эта часть написана в таком же стиле, как и предыдущая: немного теории, восхищение новой технологией, немного юмора (не всегда уместного) и подробное описание API функций с примерами применения. Примеры, опять же, надуманы и не пытаются раскрыть тему целиком, а всего лишь показывают применение единственной функции в очень ограниченном контексте. Глава 8 вообще не содержит никакой новой информации, а по сути, дублирует описание функций из предыдущей главы.

Четвертая часть книги LINQ to DataSet больше всего понравилась распространенным применением шаблонов написания кода типа Copy-Paste. Так, например, описание функций Distinct, Except, Intersect, Union и SequenceEqual занимают 10! страниц, причем многие абзацы отличаются друг от друга единственным словом (именем метода).

Наиболее крупной частью книги является часть 5, посвященная LINQ to SQL. И это не удивительно, ведь при описании этой технологии нужно объяснить суть объектно-реляционного отображения, роль сущностных классов, что такое DataContext, схемы и атрибуты, проблему параллелизма и многое другое. Автор рассматривает все эти темы, но делает это как-то скомкано и несколько сумбурно. Начинает объяснять одно, затрагивает другое, при этом откладывая детальное описание затронутой проблемы на потом. В этой части мне особенно понравилась глава, посвященная атрибутам. Автор приводит пример кода, который использует три атрибута и всего 7 свойств. После этого на 14 страницах следует описание всех атрибутов со всеми свойствами, без единого примера. И если некоторые атрибуты и свойства являются интуитивно понятными, то многие требуют дополнительного пояснения, которого, к сожалению, не наблюдается. И когда автор в конце главы, в резюме пишет о том, что он поздравляет читателя с тем, что он стал экспертом в области объектно-реляционного отображения, это не вызывает ничего кроме улыбки.

Так какой из этого следует вывод? Стоит приобретать эту книгу или нет?

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

вторник, 2 декабря 2008 г.

LINQ to XML правда здорово?

В последнее время я работаю над корпоративным приложением, которое состоит из серверной части и из нескольких клиентских. Для логгирования работы этих приложений используюется замечательный инструмент log4net. Его использование обусловлено не тем, что у нас продвинутые пользователи и они будут смотреть, как наше приложение работает, а исключительно удобством решения проблем непосредственно у клиента. Идея предложить пользователю открыть far и ручками поменять logLevel, как-то не вдохновляет, поэтому возникла идея настройки уровней логгирования программным способом. Для этой цели как нельзя лучше подошли новые инструменты в виде LINQ to XML.

// Вызов ToList обусловлен устранением отложенности

// операции Select

var configFiles = (from fn in

                   Directory.GetFiles(Application.StartupPath, "*.log4net").ToList()

                   select new {Filename = fn, Xml = XDocument.Load(fn)}).ToList();

// Здесь я получаю набо объектов анонимного класса, которые

// содержат имя конифгурационного файла, имя логгера, уровень

// логгирования, а также атрибут, который нужен для обновления

// уровня логгирования

var loggers = from cf in configFiles

              from lvl in cf.Xml.Descendants("level")

              let fi = new FileInfo(cf.Filename)

              select new { Filename = fi.Name,

                  Logger = (string)lvl.Parent.Attribute("name"),

                  Level = (string)lvl.Attribute("value"),             

                  Attribute = lvl.Attribute("value")};

//Обновление также не составляет труда!

foreach (var l in loggers)

{    

    l.Attribute.SetValue("INFO");

}

//Теперь нужно сохранить все конфиги обратно

foreach (var cfg in configFiles)

{    

    cfg.Xml.Save(cfg.Filename);

}

Кратко, понятно и вообще этот код прекрасно демонстрирует преимущества декларативного стиля программирования над императивным!

LINQ to Objects. VS2008 SP1 Bug!

Не так давно, работая над одним проектом столкнулся с проблемой. Начало выпадать исключение в уже проверенном коде. Проковырявшись с отладчиком с полчаса я нашел место возникновения ошибки: var bytes = Enumerable.Range(1, 5).Select(i => (byte)i); Данный оператор валился с исключением InvalidCastException. Особенно грустно было то, что я этот код проверял и тестировал и никаких ошибок не было. Да и не может здесь быть никаких InvalidCast-ов, т.к. я руками спокойно могу преобразовать int-ы в диапазоне от 1 до 5 к byte-у. Попробовав еще раз проверить этот код за домашним компьютером, я понял в чем причина! Причина в установленном SP1 к Visual Studio 2008. Приведу более полный фрагмент кода: namespace TestLINQ {

class Program

{

static void A()

{

var bytes = Enumerable.Range(1, 5).Select(i => (byte)i);

foreach (var b in bytes)

{

Console.WriteLine(b);

}

}

static void B()

{

var bytes = Enumerable.Range(1, 5).Cast<byte>();

foreach (var b in bytes)

{

Console.WriteLine(b);

}

}

static void Main(string[] args)

{

A();

B();

}

}

}

Функция А() выполняется нормально и, как и ожидается, выводит цифры в диапазоне от 1 до 5, а вот функция B() вываливается с InvalidCastException.

Причем такое поведение наблюдается только после установки SP1 для VS2008, без оного все прекрасно работает!

Кстати, эта ошибка уже всплывала в Visual Studio 2008 Beta 2 (здесь) и вот появилась снова!