Вы знаете, я вообще-то достаточно долго занимался разработкой компиляторов. Как-то, разговаривая с Игорем Васильевичем Поттосиным (одним из крупнейших специалистов в области оптимизирующих компиляторов) лет 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#. Однако, учитывая вышесказанное и тонкую связь, имеющую место быть между этими двумя языками, полагаю, что есть основания считать, что и проблемы у них будут достаточно общими. Хрен, он ведь редьки не слаще.
MSS>>Ко мне этот текст попал в конце 91го года. Он довольно >старый, и старше, чем релиз .NET. BK>в 91-м году ни Жабы, ни тем более C# не было вроде...
Вывод можно сделать только один. Плохие программисты были и будут всегда и везде. И если MS (ну и не только) берет на работу студентов, то и качеству кода удивляться не приходится. Они же только учатся, а получают копейки. И научившись чему-то, сразу уходят на нормальную зарплату в другое место. Так что это проблемы фирмы.
Так что язык программирования здесь абсолютно не причем. Чем мощнее и гибче язык, тем большая квалификация нужна для работы с ним. И наоборот. Да здравствует VB! :)
E>Так что язык программирования здесь абсолютно не причем. Чем мощнее и гибче язык, тем >большая квалификация нужна для работы с ним. И наоборот. Да здравствует VB!
Речь не об этом. А о том, что есть фичи Си++, которые не приносят никакой пользы, и приносят при этом вред. Шизанутый язык это (особенно последние новшества, которые грубо противоречат тому, что подавалось как основы языка), и восторгов совершенно не заслуживает. Вот и все.
Практическое использование Си++ нередко требует разработки внутрифирменного документа о том, какие фичи _запрещено_ использовать. Просто чтоб код нечитаемый не вышел, и чтоб не было нужды в рефакторинге
Это как известный анекдот: внедрение безбумажных систем делопроизводства привело к росту продаж принтеров и увеличению количества напечатанных за год листов.
Про ОО и рефакторинг — честно говоря, то же самое. Вот я задал вопрос, что такое "завистливые функиии". Мне ответили. Из ответа понятно, что в Си такое явление невозможно в принципе.
Похоже, что сначала придумали ОО и Си++ — то есть "как сделать то же самое, но через зад, с кучей лишнего и в шизанутом синтаксисе" — а тут же возникла нужда в рефакторинге. Энтропии в ОО языках больше, чем в Си.
Еще пример. Программа на Си читается безо всякой browse info, с использованием одного лишь grep, чтобы найти, где объявлена функция. На Си++ с этим туго. Там BSCMAKE нужен. А зачем? Плюсы-то какие?
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>----------------------------------------------------------------------------------------
[] MSS>Таким образом, скорость работы программы важна. Практика показывает, что если программа (серьезная, а не демонструшка в 1000 строк) работает слишком быстро, в нее немедленно добавляется какая-нибудь забавная функциональность, которая увеличивает объем продаж на 10% и съедает все ресурсы.
MSS>Ни программы на Java, ни на C# -- по 100 разных причин -- не работают и никогда не будут работать столь быстро, как на Си. Ну язык левой ногой задизайнен, что тут сделаешь, -- разработчики компиляторов не винованы, что создатели Жабы были в языках программирования и компиляторах ни уха ни рыла, посему там грабли разложены очень ровным слоем просто везде. Жаба, господа, это просто атас, а реализация ВМ (виртуальной машины) Саном -- это песня. Смотришь, и сразу понятно, -- ребята делают первую в их жизни ВМ. Ляп тут, ляп здесь, засада за углом, обломс там... Скажем все дружное спасибо фирме Сан, которая вбахала в пропаганду и распространие этого убожества несколько миллиардов баксов и таки добилась своего.
MSS>Кроме того, есть еще один очень существенный момент. Собственно написание кода -- это мелочи. Это 5-10% времени и стоимости разработки. Сотни миллиарды долларов и миллионы человеко-лет (без преувеличения), как в трубу, вылетают на поддержание (тестирование, правку багов и проч) софта. Вот это и есть настоящая проблема. Да еще программисты наповадились с места на место бегать каждые 2-4 года, -- только человек освоится и годик поработает продуктивно, -- глядишь, он уже опять в лес намыливается...
MSS>И вот тут возникает интересная проблема. В связи с высокой текучестью кадров и большой сложностью реальных проектов читаемость и модифицируемость кода приобретает первостепенное значение. MSS>Чтобы код был читаем и легко модифицируем, крайне желательно, чтобы он был локально понятен. Так, чтобы новый человек, посмотрев на процедуру, смог достаточно быстро понять, что она делает и как. MSS>Ну скажите мне, часто ли в Си встречаются указатели на функции? -- исключительно редко, и только по делу. Поэтому, увидев вызов функции в Си, как правило сразу понятно, какая именно функция вызвалась, можно сходить и посмотреть, что она делает.
MSS>В ОО-же языках, где народ (в особенности вчерашние студенты) любят, ой как любят переоперделять функции, хрен поймешь, какой из 15 виртуальных методов будет вызван в данном контексте, и читать текст их всех дело утомительное. В результате починка бага занимает в 3-5 раз больше времени.
Ну, это просто недисциплинированное использование возможностей ОО. Не наигрался еще народ с фичами MSS>Перейдем к деструкторам и конструкторам. Видит программист описание локальной переменной, которая нигде не используется, и, ничтоже сумняшеся, херит его. Программа перестает работать. Что за бред? -- оказывается, конструктор этой переменной устанавливает связь с Exchange'ем (реальный пример из Аутлука). Конечно, за такие фокусы (я имею в виду создание такого конструктора) нужно увольнять, но -- что написано пером, не вырубишь топором.
Да, круто! Я б точно такого уволил! MSS>Посему, как показывает мой личный опыт, надежность программ, размашисто написанных на ОО языках, оставляет желать лучшего (конечно, если менеджер следит за тем, как пишут код и за творческое использование языка программирования немедленно дает по ушам, то дело, конечно, другое. К сожалению, грязного кода на ОО языках я видел на порядок больше). MSS>К сожалению, на ОО языках наломать дров проще простого, что мы и наблюдаем изо дня в день.
Да, возможностей нагадить — значительно больше!
MSS>Как это ни удивительно, при промышленном программировании залогом хорошего здоровья является простота. Чем проще, тем лучше. Код должен быть понятен олигофрену, иначе человек, который заменит Вас через 2-4 года, не справится.
MSS>Хотите проинициализировать переменную? -- вызовите процедуру. Надо вызвать функцию? -- зовите ее напрямую. Не надо вот этого -- посылания сообщения в Жаба-скрипт, который исполнит XML (взяв его из Registry), который запустит ActiveX контрол, который и сделает, что надо, позвав вашу процедуру через COM-интерфейс (Вы смеетесь? -- зря. Я именно такой код чинил год назад. Очень надеюсь, что создатель этого маразма больше в МС не работает).
Смех сквозь слезы! MSS>Связная тема -- сложность языка программирования. Стардарт языка Си -- 200 страниц. Си++ -- почти 1000 (и достаточно много отдано на волю разработчика компилятора). Та отписка, которая должна подразумевать собой описание семантики Жабы, -- это просто смех. MSS>Очевидно, что чем проще язык программирования, тем трудней сделать на нем семантическую ошибку. Если достаточно полное и предельно краткое описание языка занимает более 1000 страниц, можно ли ожидать, что рядовой программист будет знаком хотя бы с 50% особенностей языка? -- навряд ли. Тогда откуда может быть уверенность, что достаточно навороченная конструкция представляет собой именно то, что хотел сказать программист?
Ну, я ж говорю — не наигрались! ИМХО чем "дубовей" код, тем он правильней, и зачастую — быстрее. MSS>Далее. Стандартные библиотеки. Опять же, с точки зрения промышленного программирования, — чем проще, тем лучше. Если в стандартной библиотеке (к тому же динамически подгружаемоей) есть баг, то это беда. Если программисты его не нашли -- значит, найдут пользователи. Если нашли и обошли, то проблемы начнутся после того, как пользователь обновит библиотеки и в новой версии баг будет починен (а все ведь под него проточено, не так ли?). Наконец, необходимым требованием является 100% backward compatibility библиотек. Ну скажите мне, хоть одна библиотека для Жабы удовлетворяет этому требованию? А есть ли там хоть одна процедура без какого-либо ляпа? Я уже не говорю о том, что на изучение этих библиотек может уйти полжизни.
О-о-о-о-!!!!! Кая вас понимаю!!!!! MSS>Опять же, смежная проблема. Возраст языка. Чем старше язык, тем лучше и глубже его знают программисты. Что касается Си, то всем известно, что можно делать, чего нельзя, а что можно, но лучше не нужно. С новомодными языками дело обстоит сложней, и опыт, равно как устав караульной службы, пишется кровью [программистов]. Наконец, не следует забывать, что разработчики компиляторов тоже не боги и могут ошибаться, посему вероятность обнаружить ошибку в компиляторе с Си гораздо ниже, чем в компиляторе с Си++ (чтобы найти баги в компиляторе с Жабы, в особенности Сановском, напрягаться не нужно, -- баги Вас сами найдут).
В каком-то буржуйском жкрнале была даже такая ежемесячная колонка — ошибка месяца (в компиляторах С++). MSS>Резюмирую. При создании операционных систем и большинства других серьезных проектов предъявляются очень жесткие требования к производительности и надежности.
MSS>Первое существенно зависит от языка программирования. Второе зависит от как от тестирования, так и от дисциплины программирования и читаемости/модифицируемости кода, которые также достаточно сильно связаны с языком.
MSS>Если внимательно посмотреть, то все хорошие серьезные программы на Си с примесью ассемблера. Ворд. Эксель. Ядро НТ. Ядро Линукса. Кодогенераторы (VC, GNU, etc. Гнусный кодогенератор, конечно, никуда не годится, но про удачном расположении звезд может и правильный код породить). Единственная хорошая программа, написанная на Си++, знакомая мне, -- это MS SQL сервер. MSS>Посмотрим же теперь на софт, написанный на Си++. Exchange Server. Outlook. PowerPoint. WMP. Нужны комментарии? MSS>Конечно, все вышесказанное относится к большим промышленным проектам, где объем кода измеряется миллионами и десятками миллионов строк и над которым работает хотя бы человек 50.
Ну, не вырос еще ОО-подход из коротких штанишек! Подрастем, ходить научимся, перестанем падать на каждой кочке. MSS>пи-эс. Я тут много пинал Жабу и мало -- C#. Однако, учитывая вышесказанное и тонкую связь, имеющую место быть между этими двумя языками, полагаю, что есть основания считать, что и проблемы у них будут достаточно общими. Хрен, он ведь редьки не слаще.
Все так. Именно поэтому вирт как альтернативу С++ пропагандирует оберон, описание которого на 19 (кажется страницах), а возможности — те же. Я тут постил уже ссылки на доклад Вирта.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Maxim S. Shatskih, Вы писали:
E>>Так что язык программирования здесь абсолютно не причем. Чем мощнее и гибче язык, тем >>большая квалификация нужна для работы с ним. И наоборот. Да здравствует VB! :)
MSS>Речь не об этом. А о том, что есть фичи Си++, которые не приносят никакой пользы, и приносят при этом вред. Шизанутый язык это (особенно последние новшества, которые грубо противоречат тому, что подавалось как основы языка), и восторгов совершенно не заслуживает. Вот и все.
Например? Только фичи языка, а не STL, etc.
MSS>Практическое использование Си++ нередко требует разработки внутрифирменного документа о том, какие фичи _запрещено_ использовать. Просто чтоб код нечитаемый не вышел, и чтоб не было нужды в рефакторинге :)
Ну вот я пишу под ACAD. И кое-что нельзя использовать. Например dynamic_cast. И ничего.
MSS>Про ОО и рефакторинг — честно говоря, то же самое. Вот я задал вопрос, что такое "завистливые функиии". Мне ответили. Из ответа понятно, что в Си такое явление невозможно в принципе.
Так, а что такое "завистливые функиии"?
MSS>Похоже, что сначала придумали ОО и Си++ — то есть "как сделать то же самое, но через зад, с кучей лишнего и в шизанутом синтаксисе" — а тут же возникла нужда в рефакторинге. Энтропии в ОО языках больше, чем в Си.
Читайте Буча, первое издание. Там примеры были на Smalltalk. Про энтропию — опять же квалификация программистов.
MSS>Еще пример. Программа на Си читается безо всякой browse info, с использованием одного лишь grep, чтобы найти, где объявлена функция. На Си++ с этим туго. Там BSCMAKE нужен. А зачем? Плюсы-то какие?
С C++ вообще в командной строке тяжело работать. Но в оболочке — не вызывает никаких затруднений. Особенно если VC + VisualAssist. Удобство работы на порядок улучшается.
MSS>Очень мало мест, где ОО бесспорно есть хорошо.
Ну это типичное мнение linux-оидов. Частично как следствие инертности мышления.
На 100% согласен с тем, что сказано про запутанность кодов и монструозность библиотек.
Когда читал про оптимизацию компиляторов, вспомнился один пример немножко из другой области, но весьма жизненный.
Есть две среды разработки специфических приложений — 1С и MBS Navision. Обе занимаются не компиляцией, а интерпретацией своих скриптовых языков. 1С написан, видимо, на С++ с широким использованием COM, в результате чего производительность встроенного языка при исполнении на P4 примерно равна производительности ROM-бэйсика на IBM XT. Navision пошустрее будет. Раз в 10. Тоже, конечно, безобразие, но но разница в 10 раз — это, согласитесь, аргумент.
Рассмотрим, операцию, реализованную на обеих этих продуктах: учёт отгрузки товара (в терминах 1С — "проведение расходной накладной", в терминах Navision — "учёт отгрузки"). Выполняется за одно и то же время. Функциональность примерно одна и та же. Законный вопрос: куда подевались эти 10 раз? Ввод/вывод? Поэкспериментировали с базовыми операциями работы с БД. Навижн шустрее пусть не на порядок, но в разы — это точно.
Идём смотреть скрипты, выполняющие операцию учёта. В 1С это несколько экранов текста, всё понятно и прозрачно. Ничего лишнего. Основная часть работы возложена на механизьму учётных регистров, которую надо только правильно вызвать.
Идём смотреть в навижн. Боже ж ты мой! Как в этой хреноте разобраться? Необозримой длины процедура без единого комментария (вру, один какой-то бессмысленный где-то в середине есть), IFы кустятся и ветвятся как мангровый лес. В конце концов управление передаётся в знаменитый программный модуль №12, безобразно мутный и запутанный.
Промежуточный вывод: те, кто сочинял модуль учёта в 1С думали в основном о логике предметной области (ну там проверить остатки, снять резервы, двинуть взаиморасчёты и т.д.), а навижионистам пришлось сделать всё вручную и, соответственно, до оптимальности алгоритмов дело вообще не дошло.
А если всё это реализовывать чисто на С, то результат мог бы получиться ещё более плачевным: программа, скомпилированная самым супероптимизирующим компилятором, вполне может оказаться тормознутее, чем то же самое, исполняемое интерпретатором 1С.
Вывод:важна не только и не столько оптимизация, заложенная в средство разработки, но и закладываемые в "философию" средства разработки средства обеспечения простоты и ясности реализации целевого функционала.
(что, в общем, совпадает с выводами, следующими из "текста написанного нашим соотечественником, работающим в микрософтовской команде компиляторов").
Здравствуйте, Maxim S. Shatskih, Вы писали: MSS>Практическое использование Си++ нередко требует разработки внутрифирменного документа о том, какие фичи _запрещено_ использовать. Просто чтоб код нечитаемый не вышел, и чтоб не было нужды в рефакторинге
Всегда требуется , так как сколько людей столько и мнений . коллективная разработка каждый сам по себе ??? — дерзай . С++ тут не причем .
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Про ОО и рефакторинг — честно говоря, то же самое. Вот я задал вопрос, что такое "завистливые функиии". Мне ответили. Из ответа понятно, что в Си такое явление невозможно в принципе.
угу. потому что там классов вообще нет
отличчный аргумент, не поспоришь
MSS>Перейдем к деструкторам и конструкторам. Видит программист описание локальной переменной, которая нигде не используется, и, ничтоже сумняшеся, херит его. Программа перестает работать. Что за бред? -- оказывается, конструктор этой переменной устанавливает связь с Exchange'ем (реальный пример из Аутлука). Конечно, за такие фокусы (я имею в виду создание такого конструктора) нужно увольнять, но -- что написано пером, не вырубишь топором.
А я иногда создаю переменную типа CWaitCursor и нигде ее не использую. Похоже, меня тоже скоро уволят.
Да, со студентами проблем много, чаще всего всё заканчиваеться переписыванием их кода.
Это как начинающий водитель и проффесиональный гонщик — если перед ними поставить 2 машины: болид формулы 1(18 скоростей) и чтто нибудь отечественное, то, думаю, не надо особой фантазии чтобы представить последсвия, а также переимущества и недостатки возможных комбинаций.
Получается, что вызов f(obj) может модифицировать obj, и при этом нет никакой видимой подсказки.
Если бы не было такой фичи, то параметр f имел бы тип CMyClass* — и вызов пришлось бы писать в стиле f(&obj). Это лучше, потому как явная подсказка, что obj может быть изменен в результате вызова.
Namespaces и особенно оператор using.
Почему в ядре Windows функции имеют явные лексические префиксы? IoCreateDevice, KeSetEvent... прекрасный путь. Во-первых, ищется грепом по всему проекту. Что будет в Си++? Kernel::SetEvent? Сразу лишний визуальный шум в виде ::. Но это еще полбеды. А если использовался using? Тогда одна и та же сущность может быть поименована и как set, и как CMyTooSmartNamespace::set, попробуй проищи по всему проекту.
Уже нужен BSCMAKE вместо grep, и вдобавок код лишается локальной понятности. Позвано просто — set() и все. И чтобы понять, что за set(), надо листать код на начало файла, где стоит using.
Operaror overloading. Скрытая семантика. Читаешь a+b и не знаешь, а что тут значит +. Чтобы узнать — надо лезть в башку, и хорошо, если этого класса, а не одного из предков.
Но это еще цветочки. Тут хоть лексема + есть. А если operator T()? Вот тут даже никакой видимой подсказки нет, что зовется какая-то процедура сбоку. Прям хоть венгерскую нотацию используй
RTTI. Уродство. Если язык претендует на ОО, и считает полиморфизм важной фичей языка (а против полиморфизма я ничего сказать не могу, прекрасная идея) — то на кой черт поощрять не-полиморфные стили программирования? Сам же Страуструп писал в 90ом году, что УМЫШЛЕННО не стал делать RTTI как часть языка. И приводил очевидные аргументы. Во-первых, это поощрение не-полиморфного стиля программирования (который однозначный отстой, и кандидат на рефакторинг). Во-вторых, невозможно раз и навсегда придумать правильную раскладку class object. В-третьих, если надо, то несложно сляпать самому, и к чему язык загромождать?
Теперь он что, передумал? На кой черт эта фича в языке? Если уж очень сильно надо — что бывает редко — чем плох DECLARE_DYNAMIC из MFC? Однозначно лучше, чем что бы то ни было compiler-generated (а компилятор сгенерит то же самое, это очевидно). Например, тем, что можно откастомайзить под себя class object.
Такое ощущение, что рефакторинг кода на Си++ должен состоять главным образом в выбрасывании из него этих маразмов, и приближении его к коду на Си .
E>Ну вот я пишу под ACAD. И кое-что нельзя использовать. Например dynamic_cast
dynamic_cast само собой. Но это не единственный бред в Си++.
E>Так, а что такое "завистливые функиии"?
Метод одного класса, который часто и помногу работает с содержимым другого класса. Кандидат на перенос в тот другой класс.
E>Читайте Буча, первое издание. Там примеры были на Smalltalk. Про энтропию — опять же >квалификация программистов.
Программисты (и часто даже очень толковые программисты) есть народ, очень склонный к сверхценным идеям и поиску "серебряных пуль" на все случаи жизни. Вбил он себе в башку, что ОО — это круто, и будет потом писать программу для чтения SMART данных с винчестера в ОО стиле, при этом делая идиотства типа открытия файла в конструкторе. И невдомек ему, что OO — это круто для inherently object oriented задач типа UI, а вовсе не панацея на все случаи жизни.
Почти каждая фича, каждый подход, каждый язык и каждая библиотека имеет своих маньяков. Даже такая шиза, как юниксные condvar.
И нет никакой гарантии, что программист, которого нанимаешь, не будет маньяком какой-то заумной бредятины, и не свернет весь проект на ее использование. Рынок труда и HR таких гарантий уж точно не дадут.
Заумь написать мы все можем, дурное дело нехитрое. А ты (абстрактный "ты", не Exhumer) попробуй простой код написать. Существенно сложнее.
А в силу сложности этого — лучше пользоваться инструментом, который не даст писать заумь. По крайней мере в ответственных проектах, где высока цена баги в человеко-часах, и превышает цену печати кода.
E>С C++ вообще в командной строке тяжело работать. Но в оболочке — не вызывает никаких > >атруднений. Особенно если VC + VisualAssist. Удобство работы на порядок улучшается.
О! Уже даже MSVC мало, нужен еще какой-то VisualAssist. Энтропия инструмента такова, что требует дополнительных тулов для ее обуздания
И вот только не надо мне говорить, что project workspace в MSVC лучше, чем файл SOURCES или Makefile. Потому как это не так аргументы могу привести. Project workspace — это иллюзия юзабилити для начинающих.
E>Ну это типичное мнение linux-оидов. Частично как следствие инертности мышления.
Можно заглянуть ко мне в профайл, чтобы узнать, какой я знатный линуксоид
Я работал на Си++ годы. С 93 по эдак 99. И что я могу сказать... если выкинуть оттуда половину бреда (административным путем), то хороший инструмент для своего круга задач. Для всего UI, например.
Вот только в системном программировании вряд ли он хорош. Потому как бы и не приживается он там. Инструмент старый. Давно зрелый. Уже в 93ем году был зрелый — тот же Борланд 3.1. А в системном программировании не прижился.
Как можно жить без in-place определения переменных. Как это напрягало в паскал, когда одныжды пришлось что-то на нём писать! А отсутсвие декодирования имён! Этож как можно писать проект, если не выполняется проверка корректности типов и количества аргументов? А работа с памятью? Тривиальная работа со строками превращается в геморрой. Кто где память выделяет, и кто должен её удалять? Реализация функции split на голом си занимает едва ли не страницу текста. А сколько там соатнется дырок, связанных с переполнением буфера!
А контейнеры? Вы себе представляете работу на голом С со структурой вроде map<int,list<string> >? То ли я раньше не сталкивался с этим, но сейчас мне просто страшно представить, как это можно сделать без классов. Или вот работа с 3D графикой. Без перегрузки операторов, без конструкторов копирования. Как-то в юношеские годы была безумная идея написать трассировщик лучей на делфях (ещё второй версии). Посмотрел я на, то выглядят операции с векторами и ужаснулся.
Один из преподов по программированию как-то сказал, что программы по мере роста начинают жить своей собственной жизнью. Это правда!
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Нижеследующий текст написан нашим соотечественником, работающим в микрософтовской команде компиляторов.
MSS>Ко мне этот текст попал в конце 91го года. Он довольно старый, и старше, чем релиз .NET.
MSS>Предлагаю обсудить.
MSS>----------------------------------------------------------------------------------------
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>CMyClass& как параметр вызовов.
MSS>Получается, что вызов f(obj) может модифицировать obj, и при этом нет никакой видимой подсказки.
const надо писать, вот что я могу сказать. посмотрел заголовок функции — и стало всё понятно
MSS>Если бы не было такой фичи, то параметр f имел бы тип CMyClass* — и вызов пришлось бы писать в стиле f(&obj). Это лучше, потому как явная подсказка, что obj может быть изменен в результате вызова.
а ты уверен, что CMyClass* это именно подсказка о том, что параметр изменяется внутри? Может быть, просто этот объект очень тяжеловесный и програмер написал передачу через указатель, чтобы убрать лишнее копирование данных. Потому что ссылки он ненавидит и нигде не использует
MSS>Namespaces и особенно оператор using.
MSS>Почему в ядре Windows функции имеют явные лексические префиксы? IoCreateDevice, KeSetEvent... прекрасный путь. Во-первых, ищется грепом по всему проекту. Что будет в Си++? Kernel::SetEvent? Сразу лишний визуальный шум в виде ::. Но это еще полбеды. А если использовался using? Тогда одна и та же сущность может быть поименована и как set, и как CMyTooSmartNamespace::set, попробуй проищи по всему проекту.
мне даже страшно представить себе имена в стиле SystemRuntimeRemotingChannelsTcpTcpChannel
вот за такое точно надо руки рубить, по самые уши
такие имена можно использовать только в том случае, если у тебя очень мало модулей, на которые разделены функции. Вероятно, в случае написания драйверов, когда достаточно использовать крайне маленькое подмножество функций, это прокатит. В других случаях — нет.
MSS>Operaror overloading. Скрытая семантика. Читаешь a+b и не знаешь, а что тут значит +. Чтобы узнать — надо лезть в башку, и хорошо, если этого класса, а не одного из предков.
Это значит "сложение"! (чтобы понять, совсем не нужно даже иметь высшее образование )
А уж как и где оно делается, это уже дело десятое.
MSS>RTTI. Уродство. Если язык претендует на ОО, и считает полиморфизм важной фичей языка (а против полиморфизма я ничего сказать не могу, прекрасная идея) — то на кой черт поощрять не-полиморфные стили программирования? Сам же Страуструп писал в 90ом году, что УМЫШЛЕННО не стал делать RTTI как часть языка. И приводил очевидные аргументы. Во-первых, это поощрение не-полиморфного стиля программирования (который однозначный отстой, и кандидат на рефакторинг). Во-вторых, невозможно раз и навсегда придумать правильную раскладку class object. В-третьих, если надо, то несложно сляпать самому, и к чему язык загромождать?
да, RTTI плох. Но не тем, что он есть. А тем, что он недостаточно развит и применяется не для того, чего надо бы. Я надеюсь, полезность отражения никто оспаривать не будет?
MSS>Теперь он что, передумал? На кой черт эта фича в языке? Если уж очень сильно надо — что бывает редко — чем плох DECLARE_DYNAMIC из MFC? Однозначно лучше, чем что бы то ни было compiler-generated (а компилятор сгенерит то же самое, это очевидно). Например, тем, что можно откастомайзить под себя class object.
Hello, Maxim!
You wrote on Fri, 11 Jun 2004 07:13:38 GMT:
MSS> Ко мне этот текст попал в конце 91го года. Он довольно старый, и
А разве Жаба тогда уже была?
MSS> В ответ на это Игорь Васильевич заметил, что я далеко не первый, кто MSS> задает этот вопрос, -- он его регуляно слышит начиная года так с MSS> 60-го. Ответ заключается в том, что, как бы много вычислительных MSS> ресурсов не было, программисты найдут способ занять их все, посему MSS> выжимание из машины всего, чего она может, есть хорошо и будет хорошо MSS> еще долго.
Вот тут он явно прав — быстродействия много не бывает.
MSS> Ну скажите мне, часто ли в Си встречаются указатели на функции? -- MSS> исключительно редко, и только по делу.
Ага, щаз.
MSS> Поэтому, увидев вызов функции в Си, как правило сразу понятно, какая MSS> именно функция вызвалась, можно сходить и посмотреть, что она делает.
Особенно если она использует 25-30 глобальных переменных. Чиста на 5 минут
дело
MSS> В ОО-же языках, где народ (в особенности вчерашние студенты) любят, ой MSS> как любят переоперделять функции, хрен поймешь, какой из 15 MSS> виртуальных методов будет вызван в данном контексте, и читать текст их MSS> всех дело утомительное. В результате починка бага занимает в 3-5 раз MSS> больше времени.
Эмуляция полиморфизма на С — гораздо страшнее
MSS> Перейдем к деструкторам и конструкторам. Видит программист описание MSS> локальной переменной, которая нигде не используется, и, ничтоже MSS> сумняшеся, херит его.
Значит, или идиот, или новичок. Что способны такие люди написать на С, я
видел. Автор, похоже, нет.
MSS> В результате программист (по-хорошему) вынужден прочитать описания MSS> всех конструкторов и деструкторов по всей цепочке наследования всех MSS> локальных cтруктурных переменных процедуры. Кому хочется шариться по MSS> 40 файлам, чтобы понять, что делается в процедуре? — да никому. Никто MSS> этого и не делает, в результате через 3 года в программе, лихо MSS> написанной на ОО языке, не разберется никто.
Это если ламеры писали.
MSS> Посему, как показывает мой личный опыт, надежность программ, MSS> размашисто написанных на ОО языках, оставляет желать лучшего
Надежность программ, размашисто написанных на любых языках,
оставляет желать лучшего.
MSS> Я уже не говорю про перекрытие операторов, конструкторов копирования и MSS> проч.
При правильном использовании способно избавить от разбирательства с
деталями.
MSS> Творческое пользование темплейтами также сможет доставить потомкам MSS> немало приятных минут.
Бывает. Но если нет шаблонов, то вместо них на помощь приходят макросы... А
это вообще жопа.
MSS> А чего стоят исключительные события?
Сложный вопрос. Иногда значительно меньше, чем коды ошибок.
MSS> Почему-то получается, что код, написанный на языке программирования MSS> без скрытого поведения, поддерживать и сопровождать гораздо легче.
Щаз. Достаточно пару раз глянуть на MS'овский любимый "goto cleanup" чтоб
понять, что это не так.
MSS> Вышли из блока -- значит, вышли, и нечего кроме.
И забыли закрыть половину хэндлов....
MSS> Что написано, то и происходит.
А это и в C++ так — просто читать надо уметь
MSS> Когда же программа начинает напоминать MSS> сводку новостей времен СССР и приходится докапываться до третьего слоя MSS> истины -- это бардак. К сожалению, на ОО языках наломать дров проще MSS> простого, что мы и наблюдаем изо дня в день.
Честно говоря, я в этом вопросе больше доверяю Кернигану и Пайку, которых в
предубеждении к С трудно обвинить. Цитирую: "C is a razor-sharp tool, with
which one can create an elegant and efficient program or a bloody mess". Про
С++ они куда спокойней отзывались.
MSS> Очевидно, что чем проще язык программирования, тем трудней сделать на MSS> нем семантическую ошибку.
Если б это было правдой, все бы до сих пор писали на ассемблере.
MSS> Далее. Стандартные библиотеки. Опять же, с точки зрения промышленного MSS> программирования, — чем проще, тем лучше.
И чем больше — тем лучше. Сишного рантайма категорически не хватает.
MSS> Опять же, смежная проблема. Возраст языка. Чем старше язык, тем лучше MSS> и глубже его знают программисты. Что касается Си, то всем известно, MSS> что можно делать, чего нельзя, а что можно, но лучше не нужно. С MSS> новомодными языками дело обстоит сложней, и опыт, равно как устав MSS> караульной службы, пишется кровью [программистов].
Да, в 91 году это было очень актуально. Достаточно посмотреть на
MFC... Сейчас сложнее найти грамотного программиста на С, чем на С++.
MSS> Наконец, не следует забывать, что разработчики компиляторов тоже не MSS> боги и могут ошибаться, посему вероятность обнаружить ошибку в MSS> компиляторе с Си гораздо ниже, чем в компиляторе с Си++
Да-да, давайте все в машинных кодах писать — в процессорах багов точно
меньше, чем в связке процессор-компилятор
MSS> Резюмирую. При создании операционных систем и большинства других MSS> серьезных проектов предъявляются очень жесткие требования к MSS> производительности и надежности.
Угу.
MSS> Первое существенно зависит от языка программирования.
С + asm здесь рулят.
MSS> Второе зависит от как от тестирования, так и от дисциплины MSS> программирования и читаемости/модифицируемости кода, которые также MSS> достаточно сильно связаны с языком.
Так точно. И С здесь совершенно не конкурентоспособен.
With best regards, Sergey.
Posted via RSDN NNTP Server 1.9 alpha
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Нижеследующий текст написан нашим соотечественником, работающим в микрософтовской команде компиляторов.
MSS>Ко мне этот текст попал в конце 91го года. Он довольно старый, и старше, чем релиз .NET.
MSS>Предлагаю обсудить.
MSS>----------------------------------------------------------------------------------------
......
Да чушь полная. ООП — это такой же инструмент как и любой другой. Все зависит от того кто как этим инструментом пользуется. Если руки из жопы растут, то хоть ооп, хоть процедурное программирование — один хрен будет куча ошибок и проблем. Вопрос не в инструменте а в квалификации товарищей, которые его пользуют.
MSS>>Получается, что вызов f(obj) может модифицировать obj, и при этом нет никакой >видимой подсказки. Д>const надо писать, вот что я могу сказать. посмотрел заголовок функции — и стало всё >понятно
В том-то и фишка, что надо ЗАГОЛОВОК смотреть. В случае f(&obj) — все видно в месте вызова, без заголовка.
Д>а ты уверен, что CMyClass* это именно подсказка о том, что параметр изменяется внутри?
Как говорится, лучше перебдеть, чем недобдеть.
Д>мне даже страшно представить себе имена в стиле >SystemRuntimeRemotingChannelsTcpTcpChannel
RpcChannelIsTcp — пойдет? такой функции нет, но могла бы и быть.
>модулей, на которые разделены функции. Вероятно, в случае написания драйверов, когда >достаточно использовать крайне маленькое подмножество функций, это прокатит.
Порядка 1100 функций. Это маленькое подмножество???
Д>Это значит "сложение"! (чтобы понять, совсем не нужно даже иметь высшее >образование ) Д>А уж как и где оно делается, это уже дело десятое.
Да правда что ли? То есть, что тут автор кода имел в виду под сложением (а прийти в безумную голову может все, что угодно, например, << для печати) — это неважно?
Д>тем, что он нестандартный. И тем, что он макрос
Чем плохи макросы? Всяко лучше встроенной в компилятор функции. Она не кастомизируется, а макрос — кастомизируется.
G>Да чушь полная. ООП — это такой же инструмент как и любой другой. Все зависит от того >кто как этим инструментом пользуется. Если руки из жопы растут, то хоть ооп, хоть >процедурное программирование — один хрен будет куча ошибок и проблем. Вопрос не в >инструменте а в квалификации товарищей, которые его пользуют.
Типичное возражение, и совершенно неверное.
У любого человека, независимо от квалификации, ограничен объем внимания. И если его засорять, например, визуальным шумом — то это в минус.
Необходимость много листать несколько файлов (заголовки этого класса и предков) для чтения кода — в минус.
Использование оператора сдвига для печати — в минус.