вторник, 23 августа 2011 г.

О книге “MS Visual C++ 2010 в среде .NET. Библиотека программиста”

Если посмотреть на мои обзоры книг (*), то может возникнуть подозрение в предвзятости, поскольку отзывы либо положительные, либо восторженные. Объясняется эта ситуация довольно просто: прежде чем браться за чтение книги разумно совершить «разведку боем» и выяснить, насколько чтение той или иной книги полезно и актуально. Если отзывы на книгу хорошие, автор внушает доверие, а тема интересна, то есть все шансы на то, что и вы не пожалеете о потерянном времени. Если же отзывы сугубо отрицательные и за версту тянет стилем изложения «Для чайников» в самом плохом смысле этого слова, то и время на такую книгу тратить не стоит.

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

--------------------------------

clip_image002Периодически я просматриваю новинки, которыми нас балуют наши отечественные издатели и вот на днях я увидел, что издательство Питер выпустило книгу под названием «MS Visual C++ 2010 в среде .NET» из серии «Библиотека программиста» (**) о Visual C++ от некоего Зиборова В.В. Поскольку сам факт выхода книги в такой серии много чего значит, то я не поленился прочитать аннотацию, пролистать содержание и фрагмент одной из глав, и вот, что я об этом думаю.

1. Название и аннотация

Название книги, как и ее обложка является важной составляющей любой книги, поскольку именно с них начинается знакомство с ней потенциального читателя. При этом желательно, чтобы название давало хотя бы минимальное представление о том, что читателя ожидает внутри, а взгляд на обложку не вывихивал глаз. Название этой книги намекает на то, что речь в ней пойдет о C++/CLI (это подтверждает и аннотация), но вот что о чем оно не говорит, так это о том, что книга является сборником рецептов.

Легкое гугление по фамилии автора дает понять, что это далеко не первое творение товарища Зиборова; помимо этой книги у него есть еще две: «Visual Basic 2010 на примерах» и «Visual C# на примерах» и даже беглое чтение аннотаций дает понять, что это три брата-акробата упакованные в разные обличия. Однако, в отличие от двух предыдущих книг, изданных издательством «БХВ-Петербург», товарищи из издательства «Питер» решили не отпугивать потенциальных читателей всякими «примерами», а назвать книгу более обтекаемо, что вполне логично.

Цитата: «Представлено много различных авторских оригинальных решений задач программирования, которых читатель не сможет найти в интернете.»

Создатель аннотации откровенно жжот. Я все понимаю, у каждого из нас есть склонность к преувеличению, но писать о том, что в сборнике советов есть «оригинальные авторские решения», это явный перебор. Да и вообще, как в наш век интернета можно говорить об уникальных решениях, которые нельзя найти в интернете? Ведь если они такие уникальные, то о них будут трубить на всех известных форумах по разработке ПО и они через неделю они перестанут быть уникальными. Хотя, нужно признать, «уникальные» советы в книге правда присутствуют, но об этом позднее.

2. Содержание

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

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

Теперь давайте посмотрим на содержание:

Глава 1. Простейшие программы с экранной формой и элементами управления.

Пример 6. Управление стилем шрифта с помощью элемента управления CheckBox
Пример 7. Побитовый оператор «исключающее ИЛИ»
Пример 8. Вкладки TabControl и переключатели RadioButton

Во-первых, накой начинать знакомство с новым языком программирования (а ведь если судить по аннотации, то это одна из целевых аудиторий книги) с пользовательского интерфейса, а не с простого консольного приложения? Я знаю, что есть категория читателей, которые с минимальными усилиями хотят увидеть «готовое приложение», но какое это имеет отношение к языку C++/CLI? Ведь в этом случае, читатель знакомится не только с новым языком программирования, но еще и с библиотекой Win Forms, что значительно усложняет восприятие материала.

Потом, мне вообще не понятна группировка тем. Ну кто потом догадается найти пример с «исключающим ИЛИ» в главе о «простейших программах с экранной формой», да еще и между примерами с CheckBox-ом и TabControl-ом? Да и вообще, раз взялись за битовые операторы, так разумно довести дело до конца и рассмотреть их все.

Глава 2. Программирование консольных приложений ... 47
Пример 12. Ввод и вывод в консольном приложении ... 47
...
Пример 14. Вызов метода MessageBox::Show в консольном приложении. Формат даты и времени ... 51
Пример 15. Вызов функций Visual Basic из программы С++ ... 52
Пример 16. Замечательной структурой данных является словарь Dictionary ... 53

Мне сложно себе представить, какое количество совершенно разнородной информации наваливается на бедного читателя на всего-лишь десятке страниц книги (я специально привел номера страниц). В чем ценность рассмотрения формата даты и времени в примере с MessageBox-ом, да еще и в главе о консольных приложениях? А в чем польза вызова функций Visual Basic из программы С++? Чего-то мне сдается, что это не самая распространенная задача и она нисколько не поможет продвинуться в изучении языка С++. А название примера 16 вообще похоже на неудачно переведенную электронным переводчиком фразу из книги «C# за 15 минут».

Знаете, почему книга Джона Скита “C# In Depth” читается так легко? По одной простой причине: Джон рассматривается одну концепцию за раз (его знаменитая фраза “one step at a time”, которую он использует десяток раз в своей книге). Это позволяет читателю «абстрагироваться» от ненужных в данный момент времени деталей и сосредоточиться на главном: на изучении определенной концепции языка. В программировании мы ведь постоянно поступаем таким же образом для борьбы с неотъемлемой сложностью ПО; ведь мы гарантированно получим «месс», если свалим в одну сущность десяток не связанных друг с другом концепций.

Глава 12. Другие задачи, решаемые с помощью Windows Application
Пример 98. Управление прозрачностью форме
Пример 99. Время по Гринвичу в полупрозрачной форме
Пример 102. Воспроизведение звуков операционной системы

Если в главах, посвященных определенной тематике была чехарда, то что говорить о главе, которая специально посвящена всему и сразу. Когда воспроизведение звуков (кстати, тоже весьма сомнительная тема) рассматривается рядом со временем по Гринвичу, да еще и в полупрозрачной форме то это вызывает, как минимум улыбку. Неужто время по Гринвичу в непрозрачной форме или без формы вообще получить нельзя?

Между главами 2 и 12 автор рассматривает практически все темы, на которые у Троелсена ушло порядка тысячи страниц: начиная от работы с файлами, заканчивая технологией ADO.NET и использованием функций AutoCAD и созданием PDF-файла. Видимо взаимодействие с AutoCAD является действительно киллер-фичей, поскольку об этом говорится в аннотации, но мне почему-то кажется, что это не является такой уж частой задачей, ну да ладно, это дело вкуса. Идем дальше. Точнее, возвращаемся на одну главу назад, которой хочется посвятить отдельный раздел.

3. Глава 11. Использование технологии LINQ.

Этой главе стоит уделить отдельный раздел по двум причинам. Во-первых, в C++/CLI нет никакого синтаксического сахара для создания анонимных делегатов (лямбды C++ 0x не в счет, это совсем другое дело), что делает использование LINQ-а весьма ... скажем так, «многословным» делом. А во-вторых, именно эта глава лежит в открытом доступе на сайте издательства, так что мы можем познакомиться не только с содержанием, но и с содержимым.

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

bool Предикат(String ^ S)
{
  // Если число букв равно шести, то возвращаем true:
  bool A = false;
  if (S->Length == 6) A = true;
  return A;
}
String ^ Предикат2(String ^ S)
{
  // Переводим строку в верхний регистр:
  S = S->ToUpper();
  return S;
}

Итак, в аннотации сказано, что эта книга предназначена «для начинающих программистов, программистов среднего уровня, а также для программистов, имеющих опыт разработки на других языках и желающих ускоренными темпами освоить новый для себя язык MS Visual C++/CLI». Но здесь же в десятке строк кода целый букет «запахов»:

  1. использование русскоязычных имен;
  2. использование неинформативных имен функций и переменных; никогда, никогда, никогда, нет, вы не поняли, вообще никогда не называйте подобным образом имена функций и переменных; это бред сивой кобылы, не имеющий права на существование даже в примерах! Самое смешное, что самый первый раздел этой книги называется так: Что такое «хороший стиль программирования»?, видимо автор взял последние три слова в кавычки преднамеренно. Что за имена Предикат и Предикат2, а чем читателю поможет имя переменной A?
  3. изменение значение параметров; напомню, что изменение значения параметров считается моветоном, поскольку читатель кода должен четко понимать, что исходный объект S в методе Предикат2 не изменился, поскольку сама ссылка передается по значению.
  4. неверный стиль наименования; параметры и локальные переменные в среде .Net принято называть в виде camelCase-а, имена типа S и A этому правилу противоречат.
  5. Предикат2 – это не предикат; мне, например, всегда казалось, что предикат – это такая хрень, возвращающая true или false, и быстрое гугление это мнение подтверждает.

Я вообще не говорю о том, что можно сократить число строк в методе с 3-х до одной:

bool LengthEqualToSix(String^ s)
{
    return s->Length == 6;
}

Дальше идет использование всех этих «предикатов» с помощью статических методов класса Enumerable. Но поскольку в языке C++/CLI нет таких штук как методы расширения и Method Group Conversion, то вглядит это не самым лучшим образом:

// Из массива имен получаем список имен, длина которых - шесть букв:
auto Запрос = Enumerable::Where<String^>(Имена, gcnew
                                  Func<String ^,bool>(Предикат));
// Сортируем полученный список в алфавитном порядке:
Запрос = Enumerable::OrderBy(Запрос, gcnew
                                  Func<String ^,String ^>(Предикат2));

Есть и другие перлы, типа определения поля с именем: bool КуритЛи; в классе Сотрудник, или создание списка сотрудников по массиву сотрудников перед использованием методов класса Enumerable (видимо автор не знает, что к массиву статические методы класса Enumerable применимы точно так же, как и листу); и предикаты следующего вида:

bool Предикат(Сотрудник S)
{
  // Если сотрудник не курит, то заносим его в список некурящих:
  bool A = false;
  if (S.КуритЛи == false) A = true;
  return A;
  // Можно было бы записать короче:
  // return !S.КуритЛи;
  // но более запутанно
}

Месяц Предикат2(Месяц t)
{
  return t;
}

Чем автору не понравилась альтернативная запись и почему переменная типа Месяц называется t и почему только в этом случае имя переменной записано в нижнем регистре, я не знаю.

Заключение

Я хочу, чтобы меня поняли правильно: у меня нет ни малейших претензий к автору, который написал одну книгу и растиражировал ее, используя примеры на разных языках программирования. И у меня не было бы никаких вопросов к издательству, если бы обложка этой книги была бы пожелтее и вышла бы она в серии «Для чайников». Но выпускать ТАКОЕ в популярной и известной серии, рядом со знаменитыми работами таких признанных мировых экспертов, как Спольски, Бокс, Хант, Макконнелл и многих других, кажется просто преступлением.

Ребята издатели, существует масса интересных книг по программированию на платформе .Net, в том числе и на языке C++/CLI, которые могут занять достойное место в библиотеке программиста, но эта книга явно не из таких (***).

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

Да, чуть не забыл, чтобы долго не рылись, вот содержание, а вот фрагмент главы.

---------------

(*) Все мои рецензии, а также некоторые обзоры и анонсы книг можно найти здесь.

(**) Нужно сказать, что в этой серии выходят неплохие книги, такие, например, как «Философия Java» Эккеля, «Чистый код» Мартина, «Паттерны проектирования» банды четырех и многие другие. Я имею ввиду, что это не серия типа «Изучи все на свете за 15 минут во сне», это вполне серьезная серия книг.

(***) В качестве отправной точки при поиске книг по программированию на платформе .Net можно отталкиваться от следующего списка: Классические книги по C#/.NET.

9 комментариев:

  1. Шедевр, великолепный пример академических опердений.

    ОтветитьУдалить
  2. А зачем ты на ЭТО тратишь время. Есть столько всего интересного...

    ОтветитьУдалить
  3. А мы недавно сидели с камрадами на работе и откровенно рубились с содержания и фрагмента главы про LINQ. Вот и решил запечатлеть свои впечатления.

    ОтветитьУдалить
  4. Вот на счет русских букофф :)
    как то видел одно приложение, которое управляет каким то учетом, где куча сущностей, которые на английский язык если и переведешь, то будет не совсем понятно. Это были дата объекты: такие как Справка, Выписка, ну и более составные сложные имена.
    Программисты взяли и использовали русские названия. В первый раз когда я такое увидел, я спросил, это что за 1С вообще? :)
    Код естественно был написан на английском. Но когда начал смотреть код, оказалось, что сущности характерные только для России, очень удобно читать в русском эквиваленте.
    В общем я к тому, что использование русского языка в коде иногда может облегчить его чтение и понимание, но в книжном примере, тем более по основам языка, считаю - недопустимо.
    Пример кода который я смотрел, был разумным использованием.

    ОтветитьУдалить
  5. )) И ведь таких шедевров тьма.
    з.ы. Только, наверное, все-таки "моветон", а не "муветон".

    ОтветитьУдалить
  6. @Слава: если честно, то даже в этом случае я бы предпочел использовать англоязычные аналоги и в комментариях привести русскоязычный вариант. Просто потому что русское имя класса и английские методы выглядят ужасно. (хотя, возможно, вам было виднее).

    @clogic: ага, таких шедевров правда много.

    З.Ы. мУветон - исправил. Спасибо.

    ОтветитьУдалить
  7. Хе-хе. Тут мне довелось по работе рассматривать git-дерево китайских коммитов (не в смысле языка, а в смысле "сделано китайцами"), очень напомнило твоё выражение по мешанину нескольких концепций. В один патч в дереве вливается несколько изменений разного характера (исправление форматирования текста исходника, опечатки и собтвенно "основного фикса"), причём комит-меседж был очень краткий и не описывал даже половину изменений. Про качество кода уж промолчу - совсем грустно становится.

    ОтветитьУдалить
  8. Ооо, Троелсен. Можно было бы сверху просто написать: русский Троелсен, бессмысленный и беспощадный ;).

    ОтветитьУдалить