Сергей Холодилов ([info]fat_crocodile) wrote,
@ 2008-05-12 04:08:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Entry tags:c++, книжки, программинг

C++

Рок-н-ролл мёртв, а я ещё нет

Борис Гребенщиков

Мавр сделал свое дело, мавр может уходить

Фридрих Шиллер
(а вовсе не Шекспир, как я думал сначала)

Но он навсегда останется в нашей памяти...


Кучу всего разного хочется сказать про С++. Забавного и серьёзного. Начнём с забавного. Все помнят хохму про зависимость популярности языка программирования от бороды? Теперь посмотрите на домашнюю страничку Бъёрна Страуструпа и его новую фотографию... Есть ещё вопросы про C++0X? Вопросов нет, переходим к следующему пункту.

Страуструп и без нас получил полно всяческих наград. Но я считаю, что всё-таки нужно всем программистам сброситься и поставить ему памятник. Выбрать какую-нибудь бородатую фотографию и отлить из бронзы в натуральную величину. Почему - поймёте по тексту. Я его всегда уважал. Был, правда, момент, когда я вдруг осознал, что С++ - не самый лучший язык на свете... Но одновременно с этим я понял, что самых лучших языков просто не бывает. Бывают задачи и языки для них.

Что было


А недавно я прочитал



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

И зауважал Страуструпа ещё больше. Потому что он это тоже понимал, причём уже тогда, когда я ещё только рождался - как раз в 1982 году. При проектировании языка он, как Фома Аквинский, идёт срединным путём: между совместимостью с С, производительностью, гибкостью, новыми возможностями, абстракциями, ООП и низкоуровневым программированием. Не ударяется в крайности, но гнёт свою линию.

Мимо непокорных и нежных
Мимо этой и той стороны стекла
Мимо митьков и друидов
Мимо тех, кто может не пить


(c) http://www.aquarium.ru/discography/kunstkamer279.html#@992

С++ - язык, разработанный не просто так, ради идеи, а для живых людей и реальных задач. Это его слабость, но это же и его сила. Можно жаловаться, что что-то недостаточно высокоуровнево или продвинуто... Но при выборе любого другого варианта он разделил бы судьбу остальных замечательных языков того времени: Eiffel, Modula-3 - его использовало бы несколько сотен разработчиков по всему миру, остальным язык бы просто не подходил.

Потому что:
  • часто элементом задачи (или элементом очевидного оптимального решения) является «используя существующий код на …» Угадайте, на каком языке? На С, конечно; количество кода на других языках тогда было пренебрежимо мало по сравнению с С (ну, Фортран ещё, но Фортран из С/C++ использовать тоже можно, я даже сам как-то пробовал).

  • а вторым элементом так же часто бывает «и чтобы работало быстро!» Причём на тех машинах, не на современных. Причём не просто «быстро», а «не медленнее, чем на С»

  • третьим – необходимость писать код сегодня, а не переучиваться.

  • четвёртым элементом... Опять же надо учесть время. Тогда писалось гораздо больше низкоуровнего системного софта.

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

С++ должен был покрывать все перечисленные "потому что". И двигаться дальше – к вершинам абстракции. Очень широкий диапазон, и нижнюю границу никак нельзя поднять, иначе всё это бесполезно – язык просто не будет использоваться. Поэтому задрать верхнюю и отказаться от опасных механизмов не получается: в прикладном коде они опасные, а в системном – необходимые.

Подборка цитат из ДиЭС++ (цитирую по русскому изданию в серии "Классика Computer Scinse", в скобках в конце номер разделов, иногда мои комментарии):

  • В цифрах:

    За двенадцать лет число пользователей С++ в среднем удваивалось каждые семь с половиной месяцев. (7.1) --- закон Мура отдыхает! - С.Х.

    Компания Rational поставляет С++-версию библиотеки The Booch Components, которую Грейди Буч (Grady Booch) первоначально реализовал на языке Ada. На С++ её переписали сам Буч и Майк Вило (Mike Vilot). Версия на Ada занимает 125 тыс. строк исходного текста без учёта комментариев, на C++ - всего 10 тыс. строк. (8.4.1) --- Оцените прорыв в выразительности языка. И это без ущерба для эффективности! Так что сравнения с "квиксорт на Хаскеле в 2 строчки" не корректно - С.Х.

  • Цели и ограничения:

    С++ это язык, а не законченная система.[...] По своему замыслу С++ - это лишь один язык среди многих. (4.2)

    Не оставлять места языкам более низкого уровня, чем С++, исключая ассемблер (4.5)

    С++ проектировался как язык для системного программирования и разработки приложений, в которых есть большой системный компонент. (7.4.2)

    Если в компиляторы С++ не будет включён необязательный сборщик мусора, то в определенных областях С++ займёт невыгодные позиции, но я уверен, что такие компиляторы скоро появятся повсеместно. (9.3.2.2)

    C++ не является идеальным инструментом для приложений, где не нужны развитые системные компоненты, а требования к быстродействию и потреблению памяти не слишком жёсткие. Однако при поддержке со стороны библиотек и, возможно, сборщика мусора, он может найти применение и здесь. (9.3.2.5)

  • Случаи из практики:

    Во время опытной эксплуатации типобезопасной компоновки я пытался отслеживать результаты её работы. С помощью данного средства выявлялись необнаруженные ошибки в каждой из больших программ на С и С++, которые мы пытались откомпилировать и связать. (11.3.3)

    В первоначальном проекте множественного наследования, который был представлен на Европейской конференции группы пользователей UNIX, состоявшейся в Хельсинки в мае 1987 г. [Stroustrup, 1987], фигурировало понятие делегирования [Agha, 1986]. [...] Реализация была тривиальной, затраты - минимальными. Поэтому данную идею испытало несколько пользователей. Много времени и сил здесь приложил Билл Хопкинс (Bill Hopkins). К сожалению, все пользователи, применявшие механизм делегирования, пострадали от серьёзных ошибок и путаницы. (12.7)

    Странный синтаксис =0 был выбран вместо очевидной альтернативы ввести ключевое слово pure или abstract только потому, что тогда я не видел возможности добавить новое ключевое слово. Если бы я предлагал pure, то версия 2.0 вышла бы без абстрактных классов. (13.2.3)

  • Философское:

    Если есть сомнения, нужно выбирать такое вариант средства, которому легче обучить. [...] Необходимо помнить, что, как уже говорилось программисты - неглупый народ; нельзя жертвовать важной функциональностью в угоду простоте. (4.4)

    Правило нулевых издержек: чем не пользуетесь, за то не платите. [...] Виртуальные функции (см. раздел 3.5), множественное наследование (см. раздел 12.4.2), идентификация типов во время выполнения (см. раздел 14.2.2.2), обработка исключений и шаблоны - в каждом случае средство принималось лишь после того, как я убеждался, что его можно реализовать с нулевыми издержками. [...] Пожалуй именно данное правило заставило отказаться от включения в язык многих возможностей. (4.5)

    По-моему, основным конкурентом С++ всегда был С. Сегодня С++ является наиболее распространённым объектно-ориентированным языком только потому, что это единственный язык, способный соперничать с С на его собственном поле и одновременно предоставлять существенные усовершенствования. (7.4.1)

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

    Хорошие программы – это продукт хорошего образования, удачного проектирования, адекватного тестирования и т.д., а не наличия в языке средств, которые предположительно должны использоваться только «правильно». Употребить во вред можно любое средство, поэтому вопрос не в том, можно ли чем-то воспользоваться неправильно (можно!) или будут ли этим неправильно пользоваться (будут!). Вопрос в том, необходимо ли данное средство при условии его правильного употребления настолько, чтобы оправдать затраты на его реализацию, удастся ли смоделировать его с помощью других средств языка и реально ли с помощью обучения обратить во благо неправильное использование. (14.2.4)

    Я подумывал о том, чтобы пойти дальше и разрешить наследование от встроенных типов и явное объявление для них встроенных операторов. Но сдержался. (15.11.3)

Главное, конечно, цели и ограничения. С++ не предназначен для того, чтобы на нём писать всё подряд, и Старуструп это понимал. Но на практике его мало кто слушал... Во всяком случае, на моей практике. Отступили от заветов :)

Чем сердце успокоилось


Мои основные претензии к С++ описаны здесь:

SH> Фокус в том, что правильно спроектировать библиотеку на C++ сложнее. ...
SH> Причина — С++ слишком заботится о байтах. О машинном представлении ...


Немного разверну.

В качестве "гарантированно переносимого" С++ предоставляет слишком низкоуровневые абстрации. Везде есть int, char, указатели. И, в общем, всё. Т.е., если библиотека хочет, чтобы её "понимали" все, она должна общаться с пользователем на языке, состоящем из int, char, указателей. Иначе это уже не просто библиотека, а, например, MFC-библиотека. Или ATL-библиотека. Или STL-библиотека. STL почти всем хороша, но её неудобно использовать из MFC-приложения..

Всё это усложняет совмещение нескольких библиотек, и/или фреймворков друг с другом. И написание "правильных" библиотек тоже усложняет.

Корни очевидны: широкий диапазон, нацеленность на системное программирование, прямую поддержку железа. Для подтверждения того, что подобные проблемы существуют и придуманы не мной - еще одна цитата из ДиЭС++:

Механизмы RTTI, которые предоставлялись разными библиотеками, были несовместимы между собой, и это стало препятствием для использования сразу нескольких библиотек. Кроме того, в каждом случае от проектировщика базовых классов требовалось многое предвидеть. Следовательно, был необходим какой-то механизм, который поддерживался бы самим языком (14.2)

Что будет


ДиЭС++ описывает период 1979 - 1994. 1998-й знаменит не только дефолтом, но и принятием стандарта С++, который, фактически, закрепил описанное в ДиЭС++ (ну и добавил кое-какие мелочи). Но на этом прогресс останавливаться не захотел, и через некоторое время комитет начал обсуждать следующую версию стандарта, названную C++0x. Подразумевалось, что стандарт выйдет где-то между 2001 и 2009 (и они ещё могут успеть! Хотя местами Страуструп шутит, что "X" не обязательно будет десятичной).

О будущем стандарте написана куча документов, текстов, есть мегабайты обсуждений в форумах, но я всё это не читал :) Я читал только Evolving a language in and for the real world: C++ 1991-2006 всё того же Страуструпа, ну и ещё кое что, о чём ниже. Несколько цитат:

  • Дополнительно о периоде 1991-1998:

    Reviewing this list in 2006, I’m struck by two design criteria (ideals) that are not explicitly stated:
    • There is a direct mapping of C++ language constructs to hardware
    • The standard library is specified and implemented in C++
    Coming from a C background and being deep in the development of the C++98 standard (§3.1), these points (at the time, and earlier) seemed so obvious that I often failed to emphasize them.

    The members of the J16 committee are volunteers who have to pay (about $800 a year) for the privilege of doing all the work.

    Changing the definition of a widely used language is very different from simple design from first principles.Whenever we have a "good idea", however major or minor, we must remember that
    • there are hundreds of millions of lines of code "out there" - most will not be rewritten however much gain might result from a rewrite
    • there are millions of programmers "out there" - most won’t take out time to learn something new unless they consider it essential
    • there are decade-old compilers still in use - many programmers can’t use a language feature that doesn’t compile on every platform they support
    • there are many millions of outdated textbooks out there - many will still be in use in five years’ time

    Basically, we (the members of the committee) desire change because we hold the optimistic view that better language features and better libraries lead to better code. Here, "better" means something like "more maintainable", "easier to read", "catches more errors", "faster", "smaller", "more portable", etc.

    We agreed on many principles and details, but the size of the STL emerged as the major obstacle. There was no consensus about the need for large parts of the STL, there was a (realistic) worry that the committee wouldn’t have the time to properly review and more formally specify something that large, and people were simply daunted by the sheer number of things to understand, implement, document, teach, etc. Finally, at Alex’s urging, I took a pen and literally crossed out something like two thirds of all the text. For each facility, I challenged Alex and the other library experts to explain - very briefly - why it couldn’t be cut and why it would benefit most C++ programmers. It was a horrendous exercise. Alex later claimed that it broke his heart. --- Речь про того самого Александра Степанова - С.Х.

    A common question over the years has been: Why don’t you add GC to C++? Often, the implication (or follow-up comment) is that the C++ committee must be a bunch of ignorant dinosaurs not to have done so already. --- В тексте есть довольно внятное объяснение "почему". И ещё более внятное - про отсутствие поддержки параллельности. Но они длинные, почитайте сами, раздел 5.5 - С.Х.

  • Про новенькое:

    I first used the term "C++0x" in 2000 and started a discussion of "directions for C++0x" through presentations in the committee and elsewhere from 2001 onwards. By 2003, the committee again considered language extensions. The "extensions working group" was reconstituted as the "evolution working group". --- В комитете Страуструп возглавляет именно эту группу. - С.Х.

    From many discussions and presentations, I have come with a brief summary of general aims and design rules for C++0x that appear to be widely accepted. Aims:
    • Make C++ a better language for systems programming and library building - rather than providing specialized facilities for a particular sub-community (e.g. numeric computation or Windows-style application development)
    • Make C++ easier to teach and learn - through increased uniformity, stronger guarantees, and facilities supportive of novices (there will always be more novices than experts)

    As ever, there seems to be as many people claiming that the committee is spoiling the language by gratuitous complicated features as there are people who complain that the committee is killing the language by refusing to accept essential features.

В общем, очень познавательное чтение. Но, для того, чтобы понять, что же всё-таки войдёт в новый стандарт, его нужно немного дополнить.

Небезызвестный Герб Саттер мало того что работает в адской компании Майкрософт, так ещё и председательствует в комитете стандартизации С++. Просто страшно представить, сколько людей ежедневно посылают проклятия-и-пожелания в его адрес. Впрочем, человек он вроде хороший. Вот тут (01.11.2007) и тут (29.03.2008) он пишет про состоявшиеся заседания комитета. А тут даёт ссылку на документ State of C++ Evolution (Post-Bellevue 2008 Mailing) (Bellevue это город, где происходило заседание комитета в марте 2008), содержащий все принятые/ожидающие/отложенные и т.п. новшества (на текущий момент; следующее заседание в июле 2008, потом в сентябре 2008, следите за рекламой).

Подбивая бабки, по основным пунктам (тезисно, ориентируясь на Страуструпа, Саттера и заголовки документов, запарился читать все эти пропозлы, если честно; если где-то понял не так, буду благодарен за поправки):
  • Много внимания уделено улучшениям шаблонов. Собираются (пока не приняты, но они очень стараются, правда) добавить понятие "концепции" (concept), позволяющее явно вводить ограничения на типы параметров шаблона. Уже приняты псевдонимы для шаблонов (насколько я понимаю, параметризованный typedef, но мне лень было разбираться). Шаблоны с переменным количеством аргументов (не вкурил пока, как это)... Ещё что-то куда-то туда же.

  • Лямбда-функции. Гы :) Конечно, они получились "немного кастрированные" :) Если я не ошибся, то честных замыканий не получилось и вернуть лямбду в качестве результата работы функции нельзя. Ну, а чего ещё можно сделать в языке, который хранит локальные переменные в стеке. Но всё равно это немерянно круто, это расширяет использование всяких find_if и for_each до полного беспредела. Хотя это можно было и сейчас, т.е. это просто синтаксический сахар... Но сладенький :)

  • Поддержка многопоточности делится между языком и библиотекой. Что куда я не понял :) Страуструп пишет, что язык поддержит TLS (ещё не принят) и атомарные операции (уже приняты, там вроде написано про библиотеку, не вникал). А библиотека реализует интерфейс к потокам в стиле Windows/POSIX (в каком-то виде уже принята, опять же не разбирался). Ну и ещё есть как минимум один связанный вопрос, про исключения в соединённых (joined) потоках (тоже принят).

  • Сборки мусора, скорее всего, в этом стандарте не будет (но уже есть упоминания о C++1x).

  • Куча мелких полезных улучшений. Вывод типа значения функции, например.. "Мелких" в том смысле, что они не меняют подход к программированию, но снимают некоторые мешающие ограничения или упрощают синтаксис.

Чем сердце успокоится


Стандарт C++0x неплохой. Я боялся, что ребята свихнулись, а они вполне ещё крепкие старики :) Кроме шуток, когда я услышал про многопоточность и сборку мусора, я подумал, что комитет попытается охватить в одном языке всё, что можно... И это будет абзац, потому что в результате язык нельзя будет применять нигде. Оказалось - нет. Выпрыгнуть из штанов С++ не пытается. И я этому очень рад.

Но, имхо, доля системного кода снижается, доля критичного по скорости кода снижается, доля кода, для которого надёжность и простота важнее производительности повышается... С++ не уйдёт, скорее всего, никогда (ну, никогда это в ближайшие 10 лет :)). В своей области он лучший. Но вот область эта уменьшается. И новый стандарт её не расширяет (к счастью!), он улучшает язык, но оставляет без изменения задачи, для которых он предназначен (т.е. которые разумно решать с его помошью).

Кстати, кто хочет посмотреть на живого Страуструпа - Лекция в CSSlub-е университета Waterloo, август 2007. Изложение избранных мест из Evolving a language in and for the real world: C++ 1991-2006 на час с небольшим, потом полчаса ответов на вопросы. Ответы интересные.



(52 comments) - (Post a new comment)


[info]_eihwaz_
2008-05-12 04:31 am UTC (link)
Сереж, убери, пожалуйста, под кат. А то отфренживать я тебя не хочу, а ленту ты мне разнес очень сильно.

(Reply to this) (Thread)


[info]julishe
2008-05-12 05:20 am UTC (link)
+1

(Reply to this) (Parent)


[info]fat_crocodile
2008-05-12 08:30 am UTC (link)
Извини, не нашёл, что тут можно было бы сократить без потери цельности.

(Reply to this) (Parent)


[info]plumqqz
2008-05-12 06:03 am UTC (link)
С++ - язык, разработанный не просто так, ради идеи, а для живых людей и реальных задач...
И мы до сих пор жили бы практически в каменном веке, с доминирующим С... И перейти с С на какую-нибудь Жабу программистам было бы на порядок труднее, это другое мышление совсем, и не родилась бы та Жаба. Но нам повезло - явился добрый гений :) И подумал наконец о людях и их потребностях, а не только о красоте идеи.


Собственно, жаба, пожалуй, уже четвертая итерация этого, по всей видимости, бесконечного кружения - PL/I -> Ada -> C++ -> Java. Я всем занудливо рекомендую тьюринговскую лекцию Хоара "Старые платья императора", но ее, как и брошюрки о вреде пьянства, читают, видимо, только трезвенники.

(Reply to this) (Thread)


[info]fat_crocodile
2008-05-12 08:48 am UTC (link)
ну, в данном случае "жаба" - эфемеризм для "современных средств разработки". Для всех. Без учёта живых людей и реальных задач (что вообще мало кому свойственно) ни один язык не достиг бы популярности, сравнимой с С. И мир программирования был бы сейчас совсем иным.

Лекцию почти прочитал, pdf никак последние страницы докачать не может :)

(Reply to this) (Parent)(Thread)


[info]plumqqz
2008-05-12 09:26 am UTC (link)
ну, в данном случае "жаба" - эфемеризм для "современных средств разработки".

Так повелось, что в ревущия девяностыя меня занесло с турбопаскаля да турбос на клиппер, где никаких сред отродясь не было. Оказалось, что не пользоваться ими - очень удобно! Может быть, я и неправ, но с тех пор воспринимаю всякие IDE исключительно как средство зарабатывания денег продавцами IDE.

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-05-12 09:27 am UTC (link)
средств, а не сред

(Reply to this) (Parent)


[info]fat_crocodile
2008-05-12 09:04 am UTC (link)
докачалось, прикольно.

Можно, конечно, жаловаться на то, что неразумные программисты не используют Паскаль.. и десяток других отличных языков. А можно понять почему они их не используют. И попытаться как-то учесть их интересы. Они же не со зла, честное слово.

(Reply to this) (Parent)(Thread)


[info]plumqqz
2008-05-12 09:21 am UTC (link)
Можно, конечно, жаловаться на то, что неразумные программисты не используют Паскаль.. и десяток других отличных языков.

Это как это не используют? PL/SQL - в полный рост, например. Отличный язык, должен сказать.

И попытаться как-то учесть их интересы. Они же не со зла, честное слово.

Конечно не со зла - а от мук творчества. У нас же все творцы, один я быдлокодер. А творцы, как мудро подметил Пелевин, нам, быдлокодерам, на хуй не нужны. Вообще, по моему твердому убеждению, единственное допустимое творчество в программировании - это искоренение творчества. И ++, и жаба прямо-таки подталкивают к творчеству, и надо обладать очень ясным сознанием, чтобы от него удержажаться. Хороший язык от творчества отваживает, и позволяет сосредоточиться на самой задаче, а не классах.

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-05-12 09:38 am UTC (link)
не используют. 3 миллиона это три миллиона. А 1000 человек это всего лишь 1000 человек. Охотно верю, что отличный. Я ещё других отличных могу десяток назвать. Они уже лет 20 существуют.. но вот как-то не получается у них широко распространиться.

Хотя тот же Страуструп искренне советует их использовать.

Consider an apparent paradox: C++ has a bias towards systems programming but “most programmers” write applications. Obviously millions of programmers are writing applications and many of those write their applications in C++. Why? Why don’t they write them in an applications programming language? For some definition of “applications programming language”, many do.

http://www.research.att.com/~bs/hopl-almost-final.pdf раздел 7.1

И я к нему присоединяюсь.

>> Конечно не со зла - а от мук творчества. У нас же все творцы, один я быдлокодер. А творцы, как мудро подметил Пелевин, нам, быдлокодерам, на хуй не нужны.

Кому вам? Тыж себя из всех выделил. Все в дерьме, а ты д'Артаньян.

А Клиппер это язык под задачу. Ничего против не имею, мой папа на нём много писал. Но чтобы сделать в программе мышку понадобилось небольшое дополнение на С, чтобы при старте выводился графический логотипчик - ещё одно... Если задача оказывается шире, чем та, на которую рассчитан язык, это абзац. С рассчитан на всё, как ассемблер. С++ тоже.

(Reply to this) (Parent)(Thread)

(no subject) - [info]plumqqz, 2008-05-12 09:50 am UTC
(no subject) - [info]fat_crocodile, 2008-05-12 10:43 am UTC
(no subject) - [info]plumqqz, 2008-05-12 10:55 am UTC
(no subject) - [info]fat_crocodile, 2008-05-12 11:17 am UTC
(no subject) - [info]plumqqz, 2008-05-12 12:47 pm UTC
(no subject) - [info]fat_crocodile, 2008-05-12 01:36 pm UTC
(no subject) - [info]plumqqz, 2008-05-12 01:57 pm UTC
(no subject) - [info]fat_crocodile, 2008-05-12 02:27 pm UTC
(no subject) - [info]plumqqz, 2008-05-12 02:38 pm UTC
(no subject) - [info]scavenger_spb, 2008-05-12 06:31 pm UTC
(no subject) - [info]plumqqz, 2008-05-13 08:53 am UTC
(no subject) - [info]scavenger_spb, 2008-05-13 09:06 am UTC
(no subject) - [info]plumqqz, 2008-05-13 09:17 am UTC
(no subject) - [info]scavenger_spb, 2008-05-13 09:44 am UTC
(no subject) - [info]plumqqz, 2008-05-13 09:50 am UTC
(no subject) - [info]scavenger_spb, 2008-05-13 10:04 am UTC
(no subject) - [info]plumqqz, 2008-05-13 10:07 am UTC
(no subject) - [info]fat_crocodile, 2008-05-12 07:30 pm UTC
(no subject) - [info]plumqqz, 2008-05-13 09:10 am UTC
(no subject) - [info]fat_crocodile, 2008-05-13 03:15 pm UTC
(no subject) - [info]plumqqz, 2008-05-13 03:31 pm UTC
(no subject) - [info]fat_crocodile, 2008-05-13 03:38 pm UTC
(no subject) - [info]plumqqz, 2008-05-13 03:44 pm UTC
(no subject) - [info]fat_crocodile, 2008-05-13 04:00 pm UTC
(no subject) - [info]plumqqz, 2008-05-13 04:08 pm UTC

[info]jtootf
2008-05-12 07:51 am UTC (link)
хорошо написано, спасибо

(Reply to this) (Thread)


[info]fat_crocodile
2008-05-12 08:31 am UTC (link)
пожалуйста :)

(Reply to this) (Parent)


[info]scavenger_spb
2008-05-12 06:40 pm UTC (link)
Сереж, просто ода плюсам и Страуструпу получилась :)

Только есть маленькое замечание:

> STL почти всем хороша, но её неудобно использовать из MFC-приложения..

Это скорее косяк MFC, нежели STL :) Хотя, действительно, STL'ные строчки жутко неюзабельны. Да и в контейнеры иногда хочется добавить ту или иную функцию. Но в общем и целом STL очень хороша.

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

(Reply to this) (Thread)


[info]fat_crocodile
2008-05-12 07:37 pm UTC (link)
Страуструпу ода и респект и уважуха, безусловно. Плюсы на своём месте чудо как хороши, тоже спорить не буду. Вопрос что именно на своём месте.

----

Ну косяк MFC, ну а что делать. Она ведь от этого не девается. Такой же косяк есть в ATL, WTL, Qt - у всех свои строчки. stl-ные никому не подошли. Тупых функций типа trim или split STL тоже не предусматривает.. Короче, тема строчек не раскрыта. Туда COM-овские BSTR до кучи.

Тяжело, понятно что тяжело. Вопрос в том, что на С++ тяжело уже просто спроектировать библиотеку, которую будет использовать кто-то другой. Даже если специально об этом думать. Потому что как только начинаешь специально думать, получается, что ничего кроме int и char* использовать нельзя.

Но и не было у них хороших вариантов. С++ лучшее из возможного в тех условиях для тех задач. Но мои задачи немного другие да и условия уже не те.

(Reply to this) (Parent)


[info]scavenger_spb
2008-05-13 10:07 am UTC (link)
Да... и еще про сборщики мусора вспомнил. Плюсы позволяют их использовать :) Сам не видел, но читал, что есть библиотеки, которые как раз и реализуют сборку мусора. Но за это, естественно, нужно платить переопределением операторов new и delete и, наверно, какими-то другими вещами тоже (типа умных указателей) ;)

(Reply to this)

не могу молчать
[info]aa5779
2008-05-14 01:14 pm UTC (link)
Во-первых, текст прекрасный, респект.

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

Но я все-таки выскажу свое субъективное мнение. Как мне кажется, качество языка программирования определяется исключительно тем, как он влияет на продуктивность программиста (да, я полагаю, что обилие сторонних библиотек, сред разработки и т.п. может влиять на продуктивность в неменьшей степени, но к качеству языка программирования это отношения не имеет). Далее. Продуктивность программиста определяется некоторой нелинейной (но очевидно монотонной функцией), зависящей от затрат на:

  1. изучение языка
  2. собственно программирование
  3. отладку/тестирование
  4. поддержку

(Reply to this) (Thread)

Re: не могу молчать
[info]fat_crocodile
2008-05-15 06:12 am UTC (link)
спасибо :) И не надо молчать :) Тут, конечно, не узкая компания друзей, но всё-таки народу немного, как-нибудь постараемся не скатиться в холивар. Я, правда, знаю существенно меньше языков существенно хуже, так что, возможно, не всегда вижу альтернативу, но тем не менее...

1. C++ мог быть другим. Проще, логичнее.. Это был бы замечательный язык, которым пользовалось бы примерно 10000 человек в лучшем случае. А миллионы несчастных страдали бы на плантациях, где им приходилось бы использовать чистый С. В ДиЭС++ довольно подробно описаны цели и последовательность проектных решений. И я не вижу там каких-то серьёзных недочётов. Язык соответствует тому, для чего был разработан. И существенно упростить его, с сохранением тех же целей, было бы довольно сложно.

2. Ну, потоки в STL, конечно, паршивые, но не настолько :) Я как раз недавно делал аналог для архива, архивируя/разархивируя через zlib. С сокетом, по идее, тоже получится. Я даже статью думал про это хотел написать, т.к. дело это весьма нетривиальное, может ещё напишу. Делается всё через std::streambuf. Или это почему-то непортабельно? Почему?

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

Поддержка шаблонов есть почти полная: всё, кроме export-а. Ну и зачем мне этот export?

Цена исключений достаточно скромная. Может быть, правда, они будут мешать встраиванию.. Но, в том и дело, их можно не использовать там, где не надо. В каких-то критичных вычислительных кусках, например. RTTI не знаю, сам практически не пользовался, он редко нужен.

3. Когда небезопасные преобразования делаются явно это нормально. С граблями согласен. То, что функция базового класса перекрывается молча и незаметно - баг.

4. Библиотеку на С++ можно вызвать из С++ :) Если тем же компилятором пользоваться. Отстуствие бинарного стандарта это существенный минус, согласен. Что-то Страуструп про это писал.. Не помню что, наверное, там где про линкеры.

Разные языки. Ну, во-первых, их всего три (процедуры, объекты, шаблоны). Во вторых, они совместимы - один из другого вызывается и некоторые общие правила сохраняются. Не вижу тут ничего критичного. Лучше было бы если бы всех заставили писать на шаблонах? Или только на объектах?

Да и потом, если вернуться к качество языка программирования определяется исключительно тем, как он влияет на продуктивность программиста, то распространённое неправильное использование языка не является его недостатком :)

(Reply to this) (Parent)(Thread)

Re: не могу молчать
[info]aa5779
2008-05-17 06:33 pm UTC (link)
1. C++ мог быть другим. Проще, логичнее.. Это был бы замечательный язык, которым пользовалось бы примерно 10000 человек в лучшем случае. А миллионы несчастных страдали бы на плантациях, где им приходилось бы использовать чистый С.

Простите, коллега, но ваша логика мне непонятна. В C++ (в отличие от, допустим, Ады или даже C) практически нет фич, ориентированных на конкретную область применения. Ты всерьез думаешь, что если бы в С++ не было бы виртуальных базовых классов, спецификатора mutable, невиртуальных деструкторов, reinterpret_cast и так далее -- этим языком пользовалось бы сильно меньше народу? Я не очень люблю Java, но если рассматривать только сам язык, безотносительно к окружающей его идеологии -- Java на порядок проще и логичнее. Далее, люди как-то умудряются писать на С++, не только не используя виртуальные базовые классы, но даже и не используя шаблоны, у меня даже есть страшное подозрение, что большая часть кода на С++ -- это, так сказать, классический С++, образца если не 1986, то 1990 г. -- ну может быть, разбавленный некоторыми простыми вещами из STL



В ДиЭС++ довольно подробно описаны цели и последовательность проектных решений. И я не вижу там каких-то серьёзных недочётов. Язык соответствует тому, для чего был разработан. И существенно упростить его, с сохранением тех же целей, было бы довольно сложно.

...а еще в ДиЭС++ подробно описано как большая умница Страуструп (которого я искренне уважаю) регулярно не мог убедить в своей правоте окружающих его меньших умниц, и что из этого получилось. Кроме того, многие решения в C++ (независимо от того, хорошие они или плохие) -- решения вынужденные (модификатор const -> const методы -> модификатор mutable, перегрузка операторов -> ccылки, множественное наследование -> виртуальные базовые классы).



2. Ну, потоки в STL, конечно, паршивые, но не настолько :) Я как раз недавно делал аналог для архива, архивируя/разархивируя через zlib. С сокетом, по идее, тоже получится. Я даже статью думал про это хотел написать, т.к. дело это весьма нетривиальное, может ещё напишу. Делается всё через std::streambuf. Или это почему-то непортабельно? Почему?

Ну, я твоей реализации не видел, поэтому не могу сказать, портабельная она или нет. :) Я не спорю -- сделать это можно (сам делал и вполне портабельно), но получается достаточно коряво и, так сказать, для этого требуется некоторый интеллект. И я искренне не понимаю, как можно было спроектировать объектно-ориентированную библиотеку таким образом, чтобы ее расширение под нужды пользователя не было штатной операцией.



Поддержка шаблонов есть почти полная: всё, кроме export-а. Ну и зачем мне этот export?
Так без экспорта шаблонов шаблоны можно держать только в хидерах, что:

  1. отрицательно сказывается на времени компиляции
  2. нарушает абстракцию данных
  3. плохо сказывается на размере приложений

Т.е. ни одна из этих проблем -- не фатальная. Но тот факт, что ключевой компонент языка во-первых за 10 лет не был полностью реализован, а во-вторых имеет системные проблемы -- это не очень хороший признак.

(Reply to this) (Parent)(Thread)

Re: не могу молчать
[info]fat_crocodile
2008-05-17 11:35 pm UTC (link)
Я имел ввиду, что, имхо, большинство сложностей вызвано обратной совместимостью. Может это и не так.

В С++ практически нет фич, ориентированных на конкретную область применения.

Ага, это концепция. А все те фичи, которые ты перечислил - их не обязательно применять и не обязательно понимать. Но есть некоторые ситуации, в которых без них плохо. Их не много, редко, виртуальные базовые классы я вообще ни разу не использовал в сознательном возрасте.

Ну, невиртуальные деструкторы нужны, конечно, иначе представление объекта в памяти слишком негибкое получается, иногда без этого никак.

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

Во всех этих новых языках нет деструкторов :( И разделения между заголовками и реализацией, что меня каждый раз смущает.

у меня даже есть страшное подозрение, что большая часть кода на С++ -- это, так сказать, классический С++, образца если не 1986, то 1990 г. -- ну может быть, разбавленный некоторыми простыми вещами из STL

Да, именно по этому я сомневался в нужности нового стандарта. Дайте уже ему умереть спокойно. Но, на тех кто пишет в стиле 1990 новый стандарт и не повлияет. А остальным поможет писать немного лучше, если им действительно надо писать на этом языке.

...а еще в ДиЭС++ подробно описано как большая умница Страуструп (которого я искренне уважаю) регулярно не мог убедить в своей правоте окружающих его меньших умниц, и что из этого получилось.

Не помню такого, например?

Кроме того, многие решения в C++ (независимо от того, хорошие они или плохие) -- решения вынужденные

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

но получается достаточно коряво и, так сказать, для этого требуется некоторый интеллект.

Да, конечно, с этим согласен, потоки паршивые.

1. отрицательно сказывается на времени компиляции

Да

2. нарушает абстракцию данных

С точки зрения компилятора объявление и так в хедере, а там есть все приватные поля... Ничего нового от содержимого функций он не получает. С точки зрения программиста, раздутый хедер, конечно, мешает.

3. плохо сказывается на размере приложений

Количество инстанцирований же не изменяется? А дубли линкер убирает.

В общем, экспорт шаблонов не кажется мне ключевым.

(Reply to this) (Parent)

Re: не могу молчать
[info]aa5779
2008-05-17 06:38 pm UTC (link)

3. Когда небезопасные преобразования делаются явно это нормально. С граблями согласен. То, что функция базового класса перекрывается молча и незаметно - баг.
Небезопастные преобразования, даже явные, это не нормально, если язык заявляет о себе как о сильно типизованном. Проблема-то еще в том, что хотели как лучше, а получилось как всегда. Сколько программистов понимают разницу между function-like cast, static_cast, reinterpret_cast и C-style cast, а? А она очень существенна, и использование не того каста запросто может привести к трудноуловимым ошибкам.

По поводу перекрытия имен -- да, это баг. Но это ведь не баг сам по себе, это следствие определенной концепции. Другой пример на ту же тему:

// file1
class A {
   // protected:
   //   void method() {}
};

// file2
class B : public A
{
};

void method()
{
}

class C : public A {
   public:
      C() { method(); }
};
Понятно, что программист, ответственный за file2 имел в виду вызвать глобальную функцию. После этого программист, ответственный за file1, добавил две строчки в класс А -- те которые у меня закомментированы. И вдруг совершенно неожиданно стала вызываться не глобальная функция, а метод A::method(). Опять таки, это не очень фатальная проблема, понятно, что программисту 2 следовало бы о таком подумать и писать ::method(), и все-таки...

Разные языки. Ну, во-первых, их всего три (процедуры, объекты, шаблоны). Во вторых, они совместимы - один из другого вызывается и некоторые общие правила сохраняются. Не вижу тут ничего критичного. Угу. До тех пор, пока не нужно три куска кода, написанные с использованием трех разных парадигм, соединить в один код.

Да и потом, если вернуться к качество языка программирования определяется исключительно тем, как он влияет на продуктивность программиста, то распространённое неправильное использование языка не является его недостатком :)
Да, но тот факт, что этим языком практически никто не умеет правильно пользоваться, для меня выглядит как симптом каких-то внутренних проблем.

(Reply to this) (Parent)(Thread)

Re: не могу молчать
[info]fat_crocodile
2008-05-18 12:13 am UTC (link)
Небезопастные преобразования, даже явные, это не нормально, если язык заявляет о себе как о сильно типизованном

Это не единственное, что он заявляет. Концепция "доверять программисту" тоже в нём есть. У программиста есть "капитанский доступ" (если ты читал "Геном" Лукьяненко :) ну, короче, можно зайти под рутом). И типизация настолько строгая, насколько программист её _явно_ не попросит. Строгая, но добрая и отходчивая :) C++ - язык с доброй типизацией... Это надо запомнить :)

Приведения типов в стиле C и function-like это как раз остатки обратной совместимости. Ну и иногда без приведений никак (вы верите в приведения? нет, ответил программист и превратился в void* - а что делать, нужен void*).

Другой пример на ту же тему: ...

А этот пример кажется мне надуманным. Чтобы функция совпадала с глобальной по имени (это несложно - read, например) и по списку параметров - маловероятно. В предыдущем случае программист мог ошибиться и перепутать параметры или ещё что-то в том же духе. А тут - вряд ли это часто случается. Хотя, конечно, например в Питоне такого не случится никогда.

Угу. До тех пор, пока не нужно три куска кода, написанные с использованием трех разных парадигм, соединить в один код.

А в чём проблема? Один из другого вызывается без вопросов. Если же надо сделать копипаст в одну большую функцию, то, во-первых, скорее всего этого делать не надо. Во-вторых, это и с однородным кодом сложно.

Да, но тот факт, что этим языком практически никто не умеет правильно пользоваться, для меня выглядит как симптом каких-то внутренних проблем.

Ну, почему никто. Вон, Страуструп, например :) Про нас с тобой и не говорю. Уже трое. Сколько там человек умеет пользоваться Хаскелем? :)

Возможно внутренние проблемы есть. Но большая их часть от непонимания, такие проблемы решаются молитвой, постом, чтением священных книг и практикой. Ну есть не очень прямая работа с потоками в STL. К счастью, никто не заставляет её использовать. Есть проблема с молчаливым сокрытием одноимённых методов базового класса. Я бы добавил ключевое слово, которое нужно было бы применять, когда отличаются прототипы, т.е. когда это именно сокрытие. Есть, наверное, ещё пяток проблем, которые понятно, как исправить.

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

В конце концов, есть другие языки. Замечательные высокоуровневые языки, которые нужно применять всегда, когда это можно делать. Один из вариантов будущего - более лёгкое взаимодействие между разными языками, возможно, какой-то специальный язык, используемый для "склейки".

(Reply to this) (Parent)

не могу молчать (2)
[info]aa5779
2008-05-14 01:15 pm UTC (link)

Итак:

  1. Изучение языка. Здесь C++, пожалуй что, вне конкуренции с другого конца. Во-всяком случае, на мой субъективный взгляд C++ сейчас существенно сложнее Ады, которую за чрезмерную сложность не ругал в свое время разве что ленивый.Количественной метрикой здесь может служит сравнение размеров текстов стандартов, но это не очень надежно, потому что стандарты С++ и Ады, допустим, очень по-разному устроены Более того, к сожалению, чтобы писать на С++ качественно его нужно действительно (в большинстве случаев) знать целиком. Более более того, после того, как я прочитал DEC++, я понял, что почти никто не использует C++ таким образом, каким он был задуман -- в DEC++ действительно куча очень элегантных решений, которых я никогда в реальной жизни не видел.
  2. Собственно программирование. Спору нет, в STL действительно много полезных вещей. Однако. Вы когда-нибуль пробовали сделать аналог fstream, но для сокетов? Не пробовали? И не пробуйте, не получится. Стандартная библиотека ввода/вывода спроектирована так, что расширить ее портабельным (относительно реализации C++) способом нельзя. Далее. Принцип "если вы этим не пользуетесь, вы за это не платите" на мой вкус и сам по себе гниловат -- если в языке есть фичи, которыми можно не пользоваться, то этих фичей в общем в языке быть не должно (но это мое личное мнение). Проблема в том, что на практике это зачастую переходит в принцип "если вы этим пользуетесь, то платите вдвойне". Полноценной поддержки шаблонов (действительно полноценной) нет, по-моему, ни в одном распространенном компиляторе (DigitalMars C++ не в счет -- вы его видели? я нет) -- и это через 10 лет после выхода стандарта и через чуть ли не 15 лет после появления самих шаблонов. Накладные расходы на RTTI и обработку исключений таковы, что практически никто ими не пользуется (особенно RTTI). Функциональный стиль программирования в STL'е -- это конечно очень здорово, но боже мой, как это выглядит! И так далее.
  3. Отладка. О да, С++, конечно, строго типизованный язык. К сожалению, программ без небезопастных приведений типов я лично не видел... Но у С++ есть и свои специфические грабли:
    class A {
      public:
        virtual int method() const;
    }
    
    class B : public A {
       public:
        virtual int method();
    }
    

    Итак, для тех, кто не в танке: в классе В два метода: константный, унаследованный от А, и неконстантный свой собственный. В результате:

    B obj;
    A *pobj1 = &obj;
    B *pobj2 = &obj;
    const A *cpobj1 = &obj;
    const B *cpobj2 = &obj;
    obj.method(); // вызывается B::method
    pobj1->method(); // вызывается (внимание!) A::method
    pobj2->method(); // вызывается B::method
    cpobj1->method(); // вызывается A::method
    cpobj2->method(); // вызывается A::method
    
    Понятно, что const в сигнатуре B::method было, скорее всего, опущено непреднамеренно... Компилятор, естественно, ругаться не будет. Особенно неприятно все это получается при сопровождении чужого кода.
  4. Сопровождение. С++ прекрасно совместим с существующим С кодом. Замечательно! Только во-первых, С++ все-таки не является надмножеством С, так что просто скомпилировать С код С++ компилятором в значительном числе случаев не получится. Вызывать С функции из С++, конечно, очень просто, только это не имеет отношения к сопровождению С++ кода. А вот вызвать произвольный метод С++ из программы на С не выйдет. Никак не выйдет. Это означает по факту что С++ библиотеку нельзя использовать ни из какого другого языка... Главная проблема однако в другом. С++ пережил период инфлянции (в космологическом смысле), так что программисты в общем не успевали за развитием языка. Более того, не успевали и реализации, соответственно какими-то вещами какое-то время просто нельзя было пользоваться, хотя они в языке уже были. На это накладывается парадигма "пользуйтесь произвольным подмножеством языка, если хотите", и в результате мы имеем ситуацию, когда разные куски кода написаны по сути на разных языках :(

(Reply to this)

не могу молчать (3)
[info]aa5779
2008-05-14 01:17 pm UTC (link)

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

Однако что я хочу сказать. Проблема С++ не в том (IMHO) что у него есть проблемы. Проблема С++ в том что оно все время заявляет о чем-то, реально этого не обеспечивая.

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

(Reply to this) (Thread)

оффтоп
[info]fat_crocodile
2008-05-19 08:00 pm UTC (link)
хотел было тебе в журнал написать оффтопом, но решил, что там это будет уж слишком не к месту :) посему здесь.

Во-первых, заранее хочу сказать, никакого конспекта не будет - пусть мне что-то местами и понятно, но целостной картины у меня нет, так что ничего объяснить я никому не смогу. Так уж получилось.

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

(Reply to this) (Parent)(Thread)

Re: оффтоп
[info]affidavid_donda
2008-05-20 12:08 pm UTC (link)
Потому что все типизованные лямбда-исчисления -- это исчисления тотальных функций (собственно, это необходимо для того, чтобы соответствующая система типов была логически состоятельной). Более того, в общем, мы ограничены примитивной рекурсией, а не общей (так что, например, в исчислении конструкций (вероятно) нельзя записать функцию Аккермана, которая хотя и тотальная, но не примитивно-рекурсивная).

(Reply to this) (Parent)(Thread)

Re: оффтоп - [info]fat_crocodile, 2008-05-20 06:26 pm UTC
Re: оффтоп - [info]aa5779, 2008-05-22 02:30 pm UTC

(52 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…