Применим ли Си++ в серьезном коде?
От: Maxim S. Shatskih Россия  
Дата: 11.06.04 07:13
Оценка: 100 (18) +1 :))) :))) :))) :))) :))) :)))
Нижеследующий текст написан нашим соотечественником, работающим в микрософтовской команде компиляторов.

Ко мне этот текст попал в конце 91го года. Он довольно старый, и старше, чем релиз .NET.

Предлагаю обсудить.

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

Вы знаете, я вообще-то достаточно долго занимался разработкой компиляторов. Как-то, разговаривая с Игорем Васильевичем Поттосиным (одним из крупнейших специалистов в области оптимизирующих компиляторов) лет 15 назад -- я тогда был еще молодой -- я поинтересовался, с какой целью мы тратим невероятные усилия на разработку новых методов оптимизации и проч., если процессоры, согласно закону г-на Мура, становятся вдвое быстрее каждые полтора года? -- обычно код, порожденный предельно тупым компилятором ("что вижу, то и пою"), медленнее оптимального ну в полтора, ну в два раза (для RISC и CISC архитектур); поскольку в скором времени "плохой" код на новой машине будет работать столь же быстро, как и хороший на старой, имеет ли смысл так упираться?

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

И.В., безусловно, прав. Вы все помните, как здорово работал Ворд на 286. На 386 он бы просто взлетел, но эти редиски -- наши коллеги из Офиса -- перенесли его на Винды и сделали графическим (появилась новая вычислительная мощность -- чего бы ее не занять?). Появился 486 и, казалось, Ворд снова должен взлететь, так нет, вставили туда какую-то проверку орфографии текста, которая работает всегда, и снова вычислительных ресурсов стало остро не хватать. И т.д. и т.п. Если кто-то думает, что 1.5 ГГц Пентиума-4 хватит на все случаи жизни, то он глубоко ошибается. 1.5 GHz P-4 -- примерно половина того, что нужно для сжатия телевизионного сигнала в реальном времени, я уже не говорю о полноценном распознавании речи.

Таким образом, скорость работы программы важна. Практика показывает, что если программа (серьезная, а не демонструшка в 1000 строк) работает слишком быстро, в нее немедленно добавляется какая-нибудь забавная функциональность, которая увеличивает объем продаж на 10% и съедает все ресурсы.

Ни программы на Java, ни на C# -- по 100 разных причин -- не работают и никогда не будут работать столь быстро, как на Си. Ну язык левой ногой задизайнен, что тут сделаешь, -- разработчики компиляторов не винованы, что создатели Жабы были в языках программирования и компиляторах ни уха ни рыла, посему там грабли разложены очень ровным слоем просто везде. Жаба, господа, это просто атас, а реализация ВМ (виртуальной машины) Саном -- это песня. Смотришь, и сразу понятно, -- ребята делают первую в их жизни ВМ. Ляп тут, ляп здесь, засада за углом, обломс там... Скажем все дружное спасибо фирме Сан, которая вбахала в пропаганду и распространие этого убожества несколько миллиардов баксов и таки добилась своего.

Кроме того, есть еще один очень существенный момент. Собственно написание кода -- это мелочи. Это 5-10% времени и стоимости разработки. Сотни миллиарды долларов и миллионы человеко-лет (без преувеличения), как в трубу, вылетают на поддержание (тестирование, правку багов и проч) софта. Вот это и есть настоящая проблема. Да еще программисты наповадились с места на место бегать каждые 2-4 года, -- только человек освоится и годик поработает продуктивно, -- глядишь, он уже опять в лес намыливается...

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

Чтобы код был читаем и легко модифицируем, крайне желательно, чтобы он был локально понятен. Так, чтобы новый человек, посмотрев на процедуру, смог достаточно быстро понять, что она делает и как.

И вот тут начинается веселье с конструкторами, деструкторами, виртуальными функциями, наследованием, исключительными ситуациями и проч.

Ну скажите мне, часто ли в Си встречаются указатели на функции? -- исключительно редко, и только по делу. Поэтому, увидев вызов функции в Си, как правило сразу понятно, какая именно функция вызвалась, можно сходить и посмотреть, что она делает.

В ОО-же языках, где народ (в особенности вчерашние студенты) любят, ой как любят переоперделять функции, хрен поймешь, какой из 15 виртуальных методов будет вызван в данном контексте, и читать текст их всех дело утомительное. В результате починка бага занимает в 3-5 раз больше времени.

Перейдем к деструкторам и конструкторам. Видит программист описание локальной переменной, которая нигде не используется, и, ничтоже сумняшеся, херит его. Программа перестает работать. Что за бред? -- оказывается, конструктор этой переменной устанавливает связь с Exchange'ем (реальный пример из Аутлука). Конечно, за такие фокусы (я имею в виду создание такого конструктора) нужно увольнять, но -- что написано пером, не вырубишь топором.

В результате программист (по-хорошему) вынужден прочитать описания всех конструкторов и деструкторов по всей цепочке наследования всех локальных cтруктурных переменных процедуры. Кому хочется шариться по 40 файлам, чтобы понять, что делается в процедуре? — да никому. Никто этого и не делает, в результате через 3 года в программе, лихо написанной на ОО языке, не разберется никто.

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

Я уже не говорю про перекрытие операторов, конструкторов копирования и проч. Творческое пользование темплейтами также сможет доставить потомкам немало приятных минут. А чего стоят исключительные события?

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

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

Хотите проинициализировать переменную? -- вызовите процедуру. Надо вызвать функцию? -- зовите ее напрямую. Не надо вот этого -- посылания сообщения в Жаба-скрипт, который исполнит XML (взяв его из Registry), который запустит ActiveX контрол, который и сделает, что надо, позвав вашу процедуру через COM-интерфейс (Вы смеетесь? -- зря. Я именно такой код чинил год назад. Очень надеюсь, что создатель этого маразма больше в МС не работает).

Связная тема -- сложность языка программирования. Стардарт языка Си -- 200 страниц. Си++ -- почти 1000 (и достаточно много отдано на волю разработчика компилятора). Та отписка, которая должна подразумевать собой описание семантики Жабы, -- это просто смех.

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

Очевидно, что чем проще язык программирования, тем трудней сделать на нем семантическую ошибку. Если достаточно полное и предельно краткое описание языка занимает более 1000 страниц, можно ли ожидать, что рядовой программист будет знаком хотя бы с 50% особенностей языка? -- навряд ли. Тогда откуда может быть уверенность, что достаточно навороченная конструкция представляет собой именно то, что хотел сказать программист?

Далее. Стандартные библиотеки. Опять же, с точки зрения промышленного программирования, — чем проще, тем лучше. Если в стандартной библиотеке (к тому же динамически подгружаемоей) есть баг, то это беда. Если программисты его не нашли -- значит, найдут пользователи. Если нашли и обошли, то проблемы начнутся после того, как пользователь обновит библиотеки и в новой версии баг будет починен (а все ведь под него проточено, не так ли?). Наконец, необходимым требованием является 100% backward compatibility библиотек. Ну скажите мне, хоть одна библиотека для Жабы удовлетворяет этому требованию? А есть ли там хоть одна процедура без какого-либо ляпа? Я уже не говорю о том, что на изучение этих библиотек может уйти полжизни.

Опять же, смежная проблема. Возраст языка. Чем старше язык, тем лучше и глубже его знают программисты. Что касается Си, то всем известно, что можно делать, чего нельзя, а что можно, но лучше не нужно. С новомодными языками дело обстоит сложней, и опыт, равно как устав караульной службы, пишется кровью [программистов]. Наконец, не следует забывать, что разработчики компиляторов тоже не боги и могут ошибаться, посему вероятность обнаружить ошибку в компиляторе с Си гораздо ниже, чем в компиляторе с Си++ (чтобы найти баги в компиляторе с Жабы, в особенности Сановском, напрягаться не нужно, -- баги Вас сами найдут).

Резюмирую. При создании операционных систем и большинства других серьезных проектов предъявляются очень жесткие требования к производительности и надежности.

Первое существенно зависит от языка программирования. Второе зависит от как от тестирования, так и от дисциплины программирования и читаемости/модифицируемости кода, которые также достаточно сильно связаны с языком.

Если внимательно посмотреть, то все хорошие серьезные программы на Си с примесью ассемблера. Ворд. Эксель. Ядро НТ. Ядро Линукса. Кодогенераторы (VC, GNU, etc. Гнусный кодогенератор, конечно, никуда не годится, но про удачном расположении звезд может и правильный код породить). Единственная хорошая программа, написанная на Си++, знакомая мне, -- это MS SQL сервер.

Посмотрим же теперь на софт, написанный на Си++. Exchange Server. Outlook. PowerPoint. WMP. Нужны комментарии?

Конечно, все вышесказанное относится к большим промышленным проектам, где объем кода измеряется миллионами и десятками миллионов строк и над которым работает хотя бы человек 50. К софту класса "t.c" длиной в 100 строк это не относится -- это можно писать на любом языке программирования.

пи-эс. Я тут много пинал Жабу и мало -- C#. Однако, учитывая вышесказанное и тонкую связь, имеющую место быть между этими двумя языками, полагаю, что есть основания считать, что и проблемы у них будут достаточно общими. Хрен, он ведь редьки не слаще.
Занимайтесь LoveCraftом, а не WarCraftом!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.