Суть терзаемого опуса сводится к тому что в С++ де всё что есть всё плохо, и Страуструпа надо жечь на костре. При этом автор смело обличает и срывает покровы, не удосуживаясь привести хоть какие-то факты (именно факты а не субъективные ощущения). Если выбрать самые козырные «разоблачения», то получится весьма интересная подборка. Начнем?
Когда-то давно я наткнулся на статью одного МГУ'шного деятеля (Алексея Борескова) - “За что я не люблю С++” , которая вызвала целую волну праведного гнева с моей стороны - “Как же так? Да как он посмел наехать на мой людимый С++?”. Ну покипятился немного, с кем не бывает? Молодой был ещё... Однако совсем недавно судьба снова вывела на этот сайт, и освежив в памяти все указанные там тезисы, я понял — ответу быть! Ответ написан в стиле “безумцы в атаке”, поэтому не стоит ждать стройности изложения. Чуть-чуть юмора, чуть-чуть фактов, чуть-чуть философии и чуть-чуть Питона. Да-да, чтобы мыслью по древу не растекаться и было больше конкретики, я выбрал именно этот язык для сравнения с C++.
Суть терзаемого опуса сводится к тому что в С++ де всё что есть всё плохо, и Страуструпа надо жечь на костре. При этом автор смело обличает и срывает покровы, не удосуживаясь привести хоть какие-то факты (именно факты а не субъективные ощущения). Если выбрать самые козырные «разоблачения», то получится весьма интересная подборка. Начнем?
“Также хотелось сделать язык таким, чтобы компилятор мог сразу же находить все возможные ошибки...”
Все ошибки в программе найти невозможно — это не под силу ни человеку (поверьте мне как опытному тестировщику), ни автотесту (поверьте мне как опытному автотестеру), ни тем более компилятору (поверьте мне как опытному программисту, хе-хе)) вот такой я спец во всём ). Знал ли это Бьярн? Да знал. Потому что дураки компиляторы не пишут, и языки, становящиеся стандартом де-факто в промышленности, не создают, а следовательно он был умным человеком. Речь шла об ошибках, которые реально под силу распознать компилятору. Не найден метод в базовом классе? Получите ошибку. Неправильно написали if? Пожалуйста — ошибка в строке N. Вызвали метод с неправильными параметрами? Вот он мерзавец. Причем это все на этапе компиляции. Что это значит в боевых условиях? Это значит, что не надо для отладки запускать тестовый стенд на котором вылезет эта ошибка. Не надо подкладывать какие-то сложные тестовые данные. А просто перекомпилировали модуль и порадовались жизни. В Питоне все несколько иначе, например такая косячная программа будет корректно работать:
def f():
print "f()"
if 0 == 1:
f( 1 , 2 , 3 )
Функция никаких параметров не принимает, а мы их ей аж три штуки напихали. Непорядок. Но интерпретатор этого не замечает и с радостью запускает программу.
“Только вот как понимать ОО - я не думаю, что программисты, пишущие на Smalltalk'е, сочтут С++ объектно - ориентированным языком.”
Да программисты на Смоллтоке есть истина в последней инстанции. Уж если они говорят что C++ говно, то значит так оно и есть )). Но мы-то не гордые, «стрёмности» C++ стыдиться не будем, а продолжим не смотря ни на что писать программы и зарабатывать на этом денюжку.
“А как дела у С++ с интеграцией со скриптовыми языками - Perl, Python, Tcl, Ruby и др?”
Про интеграцию с Питоном ответственно заявляю — все работает очень резво, что называется с адским свистом. Аж уши закладывает ). Класс для работы с питоновскими скриптами был написан за 1 день. Причем даже не написан а «нарисован», другого слова подобрать не могу, ибо так все красиво получилось.
“А вот Python умеет легко работать даже с такой кривой объектной моделью как СОМ...”
Блин, ну тут даже не знаю что сказать. Может Борескову это и не известно, но C++ тоже может работать с COM.
“Кроме того, С++ вообще не различает два существенно РАЗНЫХ понятия - абстрактнывй тип данных (АТД) и объект.”
Тут видимо автор дюже сильно разоблачать начал, наверное даже кровавая пелена глаза застлала )), уверенно заявил что объект и АТД в C++ это одно и тоже. Дайте две (цэ).
“кстати посмотрите в книге Андрея Александреску на каких компиляторах он весь код свой проверял, скорее всего вы ни одного из них просто не знаете.”
Конечно, эти компиляторы известны только Борескову, и то только потому что Александреску их по секрету сдал Борескову. Теперь они оба молчат аки партизаны и никому о них не говорят, в то время как все программисты в мире прозябают в невежестве и дикости, компилируя мелкомягким компилятором )).
“Итак, с объектной ориентированнностью получается плохо - есть какая-то странная смесь АТД и объектов (половина от одного, половина от другого), объектной модели нет вообще, основная гибкость относится ко времени компиляции.”
Согласно общепринятым определениям ООП - это наследование, полиморфизм и инкапсуляция. Каждая из перечисленных фич присутствует в C++. Каких-то некритичных вещей не хватает, но это не умаляет эффективности и мощи языка.
“Вспомним “Вы не платите за то, чем не пользуетесь”.
А как же исключения (exceptions)”
Никто не насилует. Не нравится — не используй.
“а как же RTII ?.”
Отключается в настройках компилятора.
“а Вы знаете что в английском языке сокращение STD расшифровывается как Sexually Transmitted Deseases?”
Видимо больная для Борескова тема )).
Помнится при оформлении на военную кафедру надо было принести справку из кожно-венерологического диспансера о том что у будущей элиты Российских ВС все нормально с “размножалкой”. Ну значит пришли мы с другом в это заведение, сели на лавочку и стали анекдоты травить на тему “называем писю членом и начинаем лечить сифилис”. Нам-то пофигу - у нас все в порядке со здоровьем. А вот местный контингент юмора не оценил, люди стояли сосредоточенные и смурные. т.к. лечение проходило по схеме “Доктор, ЭТО туда не влезет! Нет больной, влезет. Снимайте штаны!” (сам то я ни при делах, мне просто рассказывали)) ). Ну значит облаяли нас, подмахнули все справки и выгнали, чтобы не раздражали пациентов )).
“Вывод по этому пункту - можно писать эффективно, но пройдет несколько лет, прежде чем Вы начнете это делать. А пока, скорее всего, об эффективности можете забыть.”
Прежде чем что-то делать надо сначала выучиться а потом подумать, при этом если хотя бы один из этих пунктов отсутствует, то правильный результат будет скорее случайностью.
“Простейшим примером ситуации, когда у в Вашей программе на С++ может потечь память является автоматическое создание (и их вызов) операторов присваивания и copy-конструкторов.”
Простейшим примером ситуации, когда в Вашей программе на Питоне может потечь память является образование циклических ссылок. Что? Есть модуль gc? Хм, тогда похоже вы знаете толк в извращениях.
“Мне как-то пришлось искать почему программа, написанная аспирантом ф-та ВМиК МГУ падает через пару недель работы (она должна была работать на сервере месяцами). Именно по этой самой причине - копирование и уничтожение объектов при хранении объектов в контейнерных классах.”
Ну что можно сказать? Этот человек не прошел бы собеседование со мной )).
“Конечно это лечится :))) - нужно написать правильные copy-конструктор, оператор присваивания и декструктор.”
Борескову видимо опять неизвестно, что правильно надо писать не только перечисленные функции а вообще все функции в программе. Хотя конкретно с этими четырьмя функциями можно схитрить – на определенном этапе написания программы можно вообще забыть про конструкторы/деструкторы/присваивание, т.к. компилятор создаст их сам, причем сделает это абсолютно корректно. Вот что имею ввиду:
class A{
public:
A( void )
{
std::cout<<"A::A( void )"<<std::endl;
}
A( const A & a )
{
std::cout<<"A::A( const A & a )"<<std::endl;
}
~A()
{
std::cout<<"A::~A()"<<std::endl;
}
A & operator=( const A & a )
{
A tmp;
std::cout<<"A & A::operator=( const A & a )"<<std::endl;
return( tmp );
}
};
class B{
public:
A a;
};
int main( int argc , char * argv[] )
{
B b1;
B b2( b1 ) ;
b1 = b2;
_getch();
return( 0 );
}
Для класса “В” не определено ни одного конструктора/деструктора/оператора присваивания, все сгенерировал компилятор, на основании вызова соответствующих методов полей, если быть конкретнее, то объекта “а” класса “А”. Причем все работает корректно.
“Но оказалось, что выпускник ВМиК МГУ (работающий в программистской фирме) этого не сделал. И на клинического дебила при этом не похож.”
Да, точно, такие ошибки будучи в аспирантуре только одноклеточные совершают. Или блатные.
“Известных консультант по ООП, Алистер Коберн в своей книге “Surviving object-oriented projects” считает, что при отсутствии значительного опыта “С++ представляет собой наиболее серьезный технический риск для выживания проекта”. И призывает не надеятся, что программисты на С смогут легко перейти на С++.”
Переход на язык и изучение немного разные вещи. C++ поддерживает процедурно-ориентированную парадигму программирования. А с ней-то у сишников не должно быть проблем. Не нравятся ссылки? Не понятно что это такое? Используйте указатели. Не нравятся классы? Работайте без них.
“Ему принадлежит следующее высказывание - “Легче научить программиста на С Smalltalk'у, чем С++”. Подумайте об этом, этот человек видел и консультировал очень много проектов.”
С горы всегда проще катиться вниз, чем взбираться на неё.
“И при всем этом компилятор зачастую не ловит даже простейших ошибок.”
См. выше.
“Боле того, оказывается, что компилятор в ряде случаев не ловит даже такую ошибку, как лишние параметры. Известен случай, когда в библиотеке векторов для обозначения скалярного произведения переопределили оператор ','.”
За перегрузку запятой в нормальных конторах яйца отрывают. Чтобы тот опЕздыл, который это сделал, больше никогда не размножался и его род прервался навсегда.
“Причем, что самое главное, компилятор в принципе может обнаруживать лишь ошибки в структуре языка. В то время как набор тестов способен определять ВСЕ ошибки.”
Да нет не все, а только ошибки в тех текст-кейсах, которые тестировались. Однако проблема не в автотестах. А в стоимости их написания. Я уже рассказывал о том, как можно проводить автотестирование в «экономном» режиме. От автотестирования GUI придется либо отказаться, либо потратить на это огромные деньги.
Для многих тайна что основные косяки вылезают на стыке модулей, фреймворков, компонент, программ. С линейным ростом числа этих сущностей зартраты на тестирование растут очень нехорошими темпами, поэтому отлавливание хотя бы части ошибок на этапе компиляции это уже плюс. И если интерпретатор слабоват в обнаружении ошибок... Что ж тестируйте до потери пульса.
“Однако в случае многонитевых приложений подобная политика запросто приводит к возникновению т.н. raise condition, например, одна нить может уничтожить одну переменную, а другая - что-то записать в нее. При этом сущесвтует вероятность того, что произойдет обращение к уже освобожденному блоку памяти и падению программы.
Можно, конечно возразить, что никто не обещал, что STL будет успешно работать в многонитевых приложениях. Однако в ряде реализаций не выдается даже предупреждения на стадии компиляции о возможных проблемах.”
Очень интересно как эта проблема решена в Objective-C. Но автор почему-то нам не рассказал об этом.
“А как правило, каждый раз, когда Вы используете класс map, для него заново генерируется код и включатся в выполнимый файл.”
Не всегда. Только тогда, когда шаблон инстанциируется новым типом.
“А как Вам очень распространенное предупреждение компилятора в VC 6 о том, что длина идентификатора превысила 255 символов?”
Лично мне пофиг.
“При этом следует иметь в виду, что все эти встроенные классы и методы для работы с ними были написаны на чистом С и сильно соптимизированы, поэтому скорость работы может в ряде случаев оказаться даже выше чем у эквивалентной С++ программы (при несравненно меньшем объеме кода).”
Почему-то автор опять не снизошел до демонстрации примеров. Так же очень хотелось бы посмотреть во что обходятся все самые вкусные фичи Objective-C, которые так фанатично пиарит Боресков. Чудес не бывает, как бы эльфам из страны цветов этого не хотелось бы.
“А возврщаеясь к скриптовым яызкам - там почему-то все очень легко и просто, и внутри всего лежит именно reference counting.”
Причем подсчет ссылок абсолютно не работает с циклическими ссылками. Но их обрабатывают другие более сложные алгоритмы, которые работают в разы медленнее. Что же нам делать? Побежим покупать дополнительную планку памяти?
Итоги той статьи я даже комментировать не стал, там чистый бред. Сами почитайте.
Ладно, пора закругляться. В заключении оговорюсь, что статья была написана не для того чтобы “закозлить” Борескова, и тем более не для того чтобы закозлить Питон, который является очень хорошим языком (по моему сугубо личному мнению). А для того чтобы показать, что все программы создаются с оглядкой на индустрию, на программистов, на существующие машинные мощности. Что всегда будет сделка между желаемым и дествительным. И что никогда, ни при каких условиях не будет все хорошо в мире промышленного программирования (да и вообще в мире человеческом). Всегда будет борьба насмерть, из которой выйдут победителями только Мастера. Те кто сможет почувствовать, понять и принять слабости выбранного языка программирования. Ибо только осознание собственных слабостей заставляет ярче сиять нашу силу, определяющую победителя в вечной борьбе. Силу, которая, соединяясь с мастерством, превращает программиста в Демиурга. Те кто не смогут этого понять, будут быдлокодить за еду и метаться в панике при выходе каждого нового фреймворка, но победителям до них не будет никакого дела...