середу, 18 вересня 2013 р.

Книги по C++ -- загальні міркування

(с)  Chetan Gole
Останнім часом часто доводиться рекомендувати підручники по C++ людям, які тільки починають вивчення цієї, дуже мною любимої, але, все ж, складної, мови. 

Вирішив підсумувати свої міркування --- як вибирати та запропонувати список конкретних книг, щоб, замість повторювання --- просто скеровувати сюди. 

Зрозуміло, що в міркуваннях є доля суб'єктивності. Хоча, базуються вони на поглядах (і діагнозах) гуру С++ --- явно не сам придумав! Є дуже багато спрощень --- пост і так завеликим виходить.

Справа в тому, що проблема вибору книг для вивчення С++ складна. Чому? Тому що дуже багато зовсім-зовсім поганих --- відверто шкідливих; багато ніяких. І зовсім мало, у відносній частці, хороших.  C++ --- складна. Спільнота програмістів виробила правила, як ту складність використовувати на користь своїй роботі. Однак більшість авторів книг про це нічого не знають. Крім того, мові минуло 30 років, проягом яких вона активно розвивалася. Книги виходили та застарівали. Так ще й частина забули вийти з епохи 90-х. Відкриваєш книгу 2003-2005-2008 років: MS-DOS, десь на горизонті Windows, far i near вказівники... Бррр! Ще одна поширена хвороба --- забути, що крім Visual C++/Borland CBuilder/ще чогось, існують інші компілятори та середовища.


Коротко --- що таке С++?


Перш ніж перейти до рекомендацій, дуже коротко спробую сформулювати, що таке C++. Тобто, зрозуміло, що це --- мова програмування. ;-) Але як визначити, що є коректною програмою на С++, а що ні? 

Так ось, популярна віра: "коректна, принаймні синтаксично, програма на С++ --- те, що успішно компілює мій компілятор" --- єретична. Коректна (синтаксично) програма --- та, яка відповідає стандарту на С++. Всі основні компілятори намагаються відповідати йому. Всі мають якісь відхилення, як в наслідок недопрацювань, так і в цілях надати якийсь додатковий функціонал. (Іноді -- необхідний, часто --- такий, який можна виразити засобами чистого С++, але розробникам чи їх менеджерам дуже хочеться зробити по своєму). By the way, побічний ефект цього --- програму варто компілювати, хоч час від часу, різними компіляторами --- для перехресної перевірки.

Стандарт С++, образно кажучи --- конституція, кримінальний, процесуальний, цивільний і т.д. кодекси мови. Коректно написана програма компілюватиметься будь-яким стандартним --- відповідним стандарту, компілятором. Звідси ще одна метафора. Якщо ви говоритимете літературною мовою, всюди де живуть її носії, вас розумітимуть. А якщо діалектом? ;-) У Львові характерні карпатські словечка розуміє більшість. Яка частка зрозуміє їх у Києві чи Харкові?

Перший стандарт було прийнято в 1998 році (ISO/IEC 14882:1998, С++98), поправки до нього --- в 2003 (ISO/IEC 14882:2003, C++03 чи С++98/03). Актуальний стандарт --- С++11, ISO/IEC 14882:2011. (Поправки до нього очікуються в 2014, новий стандарт --- в 2017, хоча, комітет славиться своїми затримками, 11-й теж мав бути 09-м). Він включив у мову дуже багато корисного, виправив ряд давніх проблем. Хороша штука. Однак, хоча останні версії всіх основних компіляторів в достатній мірі його підтримують, практичне впровадження його ще тільки розпочалося. Тому, поки, в основному, все ж орієнтуватимемося на (вже дещо застарілий) C++98/03.

Загальні рекомендації

Почну із мета-правил. 

Мета-правило 1. (У авторів, яких незаслужено ображу цим правилам --- прошу вибачення, і з задоволенням ознайомлюся із їхніми роботами). Однак, переважну більшість книг авторів, які походять  з колишнього СРСР --- України, Росії, Білорусії, слід просто уникати. В кращому випадку --- відсутність стилю. В кращому. В типовому --- маразм. Книжки про С++, де від С++  одна назва. Книги, які, будучи надрукованими в 2003-2010 роках, не в курсі, що під DOS зараз майже не програмують, а крім Borland C є ще компілятори. Про те, що більшість із них нічого не чули про стандарт C++, хоча б 98-го року, потреби окремо згадувати не виникає. 

Слід зауважити, що частина із них, на момент написання, 1989-99 (?) були цілком достойними. Але оновити їх "забули".  Хронічна хвороба наших авторів. Як канонічний приклад згадую книжку із астрономії. Цілком хорошу. Візьмемо, скажімо, опис Титану. Сторінка тексту. Ну, не дивно --- на момент виходу було відомо не так багато. Чергове перевидання. Після прильоту Cassini–Huygens. Після того як Huygens відпрацював. Після того, як наші знання про Титан збільшилися на порядки! В книжці до згаданої глави додано абзац. Із двох коротких речень. Кілька слів змінено в тексті вище. Геніально.

Називати конкретні творіння не буду. Їх хвалять, передають із рук в руки, обговорюють. Але основне враження --- НЕ БЕРІТЬ ТУ ГИДОТУ В РУКИ. "Почну вчитися по тому, потім знайду щось краще" знаходиться десь між "Хай поки дитину вчить говорити двірник-дагестанець, який заледве знає нашу мову, потім перевчу" і "навчитеся плавати, дамо воду".

Спільними зусиллями із студентами вдалося відкопати одну середнього рівня і пару терпимих. Ще якась кількість залишилася невідкопаними... Не ризикуйте.

Мета-правило 2. Не беріть в руки книжки по "С/С++" --- С і С++. Ви будете вчити мову по "Підручник української та білоруської мови"? Тут --- та ж ситуація. Так, C++ зародилася в лоні С, так, на загал майже будь-який код C буде коректним кодом С++. Так, базові конструкції дуже схожі. Однак це в біса різні мови. Із різною ідеологією, різним підходом. Я доволі впевнено знаю С++. Однак С знаю ледь-ледь, хоча і відносно добре знайомий із синтаксисом.


Простих рекомендацій, як швидко відрізнити погану книжку від хорошої немає.  

 Однак, запропонувати ряд експрес-тестів можна.

Тест 0. Перший стандарт вийшов у 1998 році. Він запровадив ряд важливих змін до загальноприйнятих тоді практик. Якщо книжка написана до 98 включно (для перекладених --- мова про час друку оригіналу!) --- не беріть її. Вона може бути дуже хорошою! В мене теж є ряд таких. Однак вона застаріла. Навчитеся С++ --- можете повернутися до неї, почерпнути нові ідеї і т.д. Але не вчіться по ній! 

Аналогія така. Уявіть, що ви  --- француз, готуєтеся їхати в Росію. Ви будете вчити російську по підручнику епохи дореволюційної, ("імперської"), граматики? З ятями і т.д? Так, вас напевне зрозуміють, та й ви розумітимете сяк-так. Однак, ідея не дуже хороша. (Я вже не говорю, що більшість "місцевих" підручників по С++ відповідають, швидше, давньоруській мові.)

Тест 0-A. Якщо книга не згадує про стандарт --- придивіться до неї уважніше. Ймовірно, позитивним буде не один тест.

Тест 1. Зокрема, стандарт рекомендував для заголовків стандартної бібліотеки вживати варіант без розширення, скажімо <iostream> замість <iostream.h>. Якщо в книзі стандартні (увага! не взагалі -- будь-які, а лише стандартні!) файли заголовків вживаються з .h --- не беріть її. Вона або застара, або автори не надто слідкують за тим, про що пишуть.

Тест 2. Якщо побачите:
void main() 
не беріть їй. Це не те що до-стандартне. Це --- сива давнина. (Див. також тут --- теж вже цілу вічність тому написане). Те ж стосується авторів, які кажуть, що можна і так: void main() і так: int main().

Тест 3. Якщо бачите використання <conio.h> --- не беріть її. Це мало того, що сива давнина, так ще й із прив'язкою до DOS.

Тест 4. Якщо книга надміру орієнтована на конкретне середовище (компілятор/IDE), а то й конкретне середовище конкретної епохи (зазвичай --- DOS), подумайте, чи вона вам аж так потрібна? Не завжди це погано. Принаймні, якщо середовище не занадто древнє. Цілком нормально, коли автор наводить приклади в одному конкретному середовищі. Однак, уникайте плутати конкретний діалект C++ із мовою взагалі.

Тест 4-A. Суміжний тест. Якщо в книзі жорстко говориться про фіксовані розміри фундаментальних типів, таких як int --- вона явно занадто прив'язана до конкретного середовища. На розміри типів є обмеження, наприклад: char не менше 8 бітів, short не менше 16, long -- не менше 32, char <= short <= int <= long, але це --- все.


Тест 5. Шаблони, виключення, STL --- невід'ємна і критично важлива частина С++. Я вже мовчу про класи і перевантаження операторів. Якщо про них не згадується, або згадується занадто коротко --- не беріть таку книжку. Це --- не зовсім С++, а можливо --- зовсім не С++. Мало які сюрпризи в ній ще заховані.

Тест 6. Якщо книга дає погані рекомендації по стилю -- стережіться. Зрозуміло, що тільки вивчаючи мову, важко зрозуміти, що добре, а що погано. Однак, активне використання goto, глобальних змінних, інших подібних брудних трюків, однозначно вказують --- поклади каку і більше не бери. Увага! Згадка про ці засоби чи помірне використання їх, із детальним обґрунтуванням, чому йдеться на таке, цілком припустимі! Але не більше.

Тест 7. Рекомендація злочинних практик. Звертання до звільненої пам'яті, покладання на порядок обчислення виразів-аргументів функцій, повернення вказівників на локальні змінні і т. д. і т.п. Всього того, що називається "undefined behaviour" --- "невизначена поведінка". Чітко сказано -- результат таких дій непередбачуваний. Вони можуть працювати до пори до часу. До оновлення компілятора. До зміни його опцій. До зміни фази Місяця. Ні за яких умов не користуйтеся такого плану літературою. (З цього правила є ряд специфічних, вузькоспеціалізованих винятків, не розглядатимемо їх тут.)

Тест 8. Найскладніший для початківця. Спосіб спробувати відрізнити слабеньку книжку від нормальної. Описані вище тести стосуються розпізнавання зовсім поганих. Цей --- трішки м'якший. Мова про систематичне використання не дуже хороших практик: 
  • Ігнорування констант, використання замість них #define.
  • Широке використання коротких, часто --- позбавлених сенсу, імен функцій та змінних.
  • Надмірно великі функції.
  • Використання вказівників там, де достатньо посилань (references).
  • Передача по значенню (void print(A a); )там, де достатньо константного посилання ( void print(const &A); ).
  • Зловживання відкритими полями класів або set/get методами.

Метаправило: якщо тест 6 або два довільних тести із 0-8 дали позитивний результат, не беріть її!!! Якщо один, крім 6-го --- добре подумайте, але краще --- не беріть. Книжкою, якої стосується тільки правило 8, теоретично, можна користуватися, але це --- не дуже здорова ідея. Метафорично кажучи, вітаючись із групою професорів, казати "Хай, чуваки" не дуже розумна ідея, хоч і не така небезпечна, як вітатися із міліцією "Здрастє, муд#ли" (тест 6 ;-).

Див. також статтю: "A few Tips for Choosing a C or C++ TextBook".

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

Немає коментарів:

Дописати коментар