Б. Страуструп - Дизайн и Эволюция C++. 2006 (1160775), страница 42
Текст из файла (страница 42)
При работе над расширениями основной акцент делается на интеграции в язык и на взаимодействии с другими его возможностями. Трудность такой работы и необхолимое лля нее время постоянно недооцениваются. Любое новое средство делает все существующие реализации устаревшими. Поэтому пользователям приходится обновлять версии компиляторов, обходиться некоторое время без нового средства или сопровождать две версии системы (для нового и старого компиляторов). Последний вариант обычно приходится выбирать разработчикам библиотек и инструментальных средств.
Документацию и прочую учебную литературу также приходится обновлять и иногда специального оговаривать, каким был язык до введения нового средства, чтобы помочь пользователям, еще не перешедшим на новую версию. Все это негативные последствия «идеального» расширения. А если оно и изначально противоречиво, то от членов комитета и от сообщества в целом потребуются дополнительные усилия. Если у расширения есть аспекты, которые несовместимы с прелыдущими версиями языка, при перехоле на новую версию это необходимо учесть, и не исключено, что эффект будет заметен даже тогда, когда новое средство не используется.
Классический пример — введение нового ключевого слова. Такая безобидная, на первый взгляд, функция чоЫ иэтпд(таЫе* павезрасе) ( /* ... */ ) 6.4.4. Логическая непротиворечивость На мой взгляд, основная трудность при рассмотрении расширения — обеспечить логическую непротиворечивость С++ и убедить пользователей в том, что перестала компилироваться после введения пространств имен, поскольку изхпд и патезрасе оказались ключевыми словами. Мой опыт, впрочем, показывает, что введение новых ключевых слов создает немного проблем и все они легко решаются.
С другой стороны, предложение ввести новое ключевое слово всегда вызывает взрыв негодования, хотя практические сложности можно свести к минимуму за счет выбора такого слова, которое вряд ли булет конфликтовать с именами идентификаторов. Именно по этой причине было выбрано цэ1пд, а не иве, и паыеэрасе, а не эсоре. Когда ради эксперимента мы без предварительного уведомления ввели ключевые слова иэ1пд и павеэрасе в используемый внутри фирмы компилятор, никто за два месяца их даже не заметил. Помимо вполне реальных проблем, связанных с принятием и реализацией новых возможностей, лаже сам факт их обсуждения может производить негативный эффект: пользователи начинают сомневаться в стабильности языка.
Многие неискушенные не отдают себе отчет в том, что изменения тщательно фильтруются, чтобы свести к минимуму влияние на уже написанные программы. С другой стороны, илеалистически настроенные поборники новых возможностей часто не хотят ничего предпринимать, чтобы развеять опасения на счет нестабильности. Кроме того, энтузиасты «улучшений» нередко преувеличивают слабости языка, чтобы выставить свои предложения в более выгодном свете.
ПИИИИИИВ Стандартизация данная цель достигнута. Возможности, включаемые в С++, должны работать согласованно и компенсировать серьезные недостатки программы, синтаксически и семантически укладываться в структуру языка и способствовать разумному стилю программирования. Язык программирования не может быть просто собранием интересных возможностей, поэтому при оценке и включении расширений важно привести их к такому виду, чтобы они стали естественной частью языка.
При серьезном анализе некоторых расширений, 957а времени уходит на то, чтобы найти форму оригинальной идеи, которая позволила бы гармонично интегрировать ее в С++. Обычно много сил тратится на выработку путей перехода к новой версии языка для разработчиков компиляторов и пользователей. Даже самое удачное средство приходится отклонять, если им нельзя будет воспользоваться, не удалив значительную часть прежнего кода и старых инструментальных средств. 6.5. Примеры предлагавшихся расширений Предлагаемые для включения в язык расширения рассматриваются в книге в контексте связанных с ними средств, но некоторые просто некуда отнести, поэтому я привожу их здесь в качестве примеров. Неудивительно, что средства, которым нигде не нашлось места, обычно отклоняются. Какой бы разумной ни казалась возможность сама по себе, к ней следует относиться с большим подозрением, если она не помогает развитию языка в нужном направлении.
с1азз н(пс(ои ( // рпп11 с: и(пс(ои ( и1пгуре=асапйагй, 1пг п1 согпег х=з, (пп 01 согпег у=0, ьпг хэ1ге=100, ьпп уэ(хе=100, со1пг Со1ог='п1асх, Ьпгйег Вогдег=э(пд1е, со1ог Вогйег со1пг='п1пе, 6.5Л. Именованные аргументы Предложение Роланда Хартингсра 1Я01апг( Нагг(пйег) об именованных аргументах, т.е. о возможности при вызове функции задавать аргументы по имени, с технической точки зрения было близко к совершенству. Поэтому особенно интересна причина, по которой его отклонили: группа по расширениям единодушно решила, что предложение не дает почти ничего нового, приведет к несовместимости с существующим кодом и булет способствовать распространению неудачного стиля программирования.
Ниже отражено обсуждение, состоявшееся по этому поводу в рабочей группе. Как обычно, сотни замечаний приходится опускать изза недостатка места. Рассмотрим некрасивый, но, к сожалению, вполне реалистичный пример, заимствованный из аналитической статьи Брюса Эккеля (Вгцсе Еске!): Примеры предлагавшихся расширений гглЩЯффЯЯЩ изтатв х'паох всасе=преп); Если вы хотитс определить окно по умолчанию, все иормалыю. Определить же окно «почти по умолчанию» нелегко, прп этом можно наделать ошибок. Суть предложения заключалась в том, чтобы ввести новый оператор: .— и использовать его в вызовах фупкппй для пмсповапия аргумента.
Например, пеи иггпои)Соуп :=агееп,ув1ге:=150) булет эквивалецтио предложению псх х1пдои)»Сап«)ага,0,0,100,150,0гееп); что с учетом аргументов по умолчанию эквивалентно пех х1пйои) впаянна а, О, О, 100, 150,0гееп, в1п01е х51ис, орсп); На первый взгляд, это полезное синтаксическое удобство, которое может сделать программы более иалежиыми. Предложение даже было реализовано, при этом пс возникло инкаких концептуальных проблем. Кроме того, предложеипый механизм основывался иа опыте лругих языков, в частности, Лс)а. С другой стороны, ист сомпсиий, что без именованных аргумс)иов вполне можно обойтись, что оип ис прслставляют собой фуиламеитальио нового средства, вс поддерживают прщщипиальпо новую парадигму программирования и пе закрывают никакой «лыры» в системе контроля типов.
Поэтому ответы па следующие вопросы зависят больше от личпых пристрастий и представлений о состояиии сообщества пользователей С+->: а уластся лп с помощью пмеповапиых аргументов писать более хороший код? а пс приведут ли зти аргументы к путаиипс или проблемам при обучсиии языку? рз породят ли проблемы совместимости? а должны ли именованные аргументы стать опиям из немногих расширений, которые мы одобрим? Первая сложность, с которой пришлось столкнуться, заключалась в том, что именованные аргументы вволят повий вил зависимости между иитсрфейсом вызова и реализацией: сз аргументу иеобхолимо иметь одно и то же имя в объявлении и определении фуикции; ы если именованный аргумсит использовался, то изменить его имя в определении функции уже нельзя, ие нанеся ущерб пользовательской программе.
Из-за времени перекомпиляции многие ис хотят увеличивать степень зависимости между интерфейсом и реализацией. Более того, за этой зависимостью скрыта существенная проблема совместимости. В ряле организаций рскомсидустся использовать «длинные, ииформативиые» имена аргументов в заголовочных файлах и «короткие, удобные» в опрелелеииях. Например: ПИФИИ ИИ1'.
Стандартизация чоьс) гечесве(1пс* е1евепсз, ьпс 1епчсп ог е1епепс асгау) ча1() сечесзе(ьпс* ч, (пс и) ( г/ 6.5.1.1. Альтернативы именованным аргументам Но если мы отказываемся от именованных аргументов, то как сократить длииу списка аргументов в примере с классом хупс)ои? Кажущаяся сложиость уже Как всегла, одни находят такой стиль отвратительным, другие (в том числе я) — вполне разумным. Как бы то ци было, программ в указанном стиле написано очень много.
Но, введя имецованиые аргументы, мы ис сможем изменить ии одио имя в стандартно распрострапяемом заголовочном файле без риска сделать неработоспособиым пользовательский кол. Поставщикам заголовочных файлов лля одних и тех жс библиотек, например Росйх или Х ЪЪ')пг(ожз, придется договариваться об именах аргумептов. Но можно сделать так, чтобы в языке не было требования одинаково именовать один и тот же аргумент в объявлеипях. Такой вариант казался мие приемлемым. Олиако другим ои це поправился.
Если требовать проверки того, что имена аргументов олицаковы в разных едииицах трансляции, то время компоновки может сушсствеиво увеличиться. Если же ие организовывать такой проверки, пол угрозой окажется безопасность типов, что может стать источником скрытых ошибок. И потенциальную проблему замеллеиия компоновки, и вполне реальную проблему дополиительиых зависимостей можно было бы решить, опустив имена аргументов в заголовочных файлах. Тогла осмотрительный пользователь мог бы ие задавать там имена аргументов, ио, цитируя Билла Гиббоиса, аэто может негативио сказаться иа удобочитаемости программ па С+»». Я опасался, что именованные аргументы могут замедлить постепенный переход от традиционных приемов программирования к абстракции данных и далее к объектно-ориентированному стилю. В программах, которые, ца мой взгляд, лучше всего написаны и улобиы для сопровожлеиия, длинные списки аргумептов— редкость.
Многие пользователи отмечали, что перехол к объектно-ориентированному стилю сопровожлается укорачиванием списков аргументов: то, что раньше перелавалось в виде аргументов или глобальиых переменных, теперь становится локальным состоянием объекта. Основываясь иа опыте, я ожилаю, что среднее число аргументов будет мсиьше двух, а функций, имеющих более лвух аргумеитов, почти ие остаистся. Отсюда следует, что имеиовапные аргументы окажутся наиболее полезными как раз в таких программах, которые мы считаем написанными плохо.
Так следует ли вволить новое срелство, поощряющее именно тот стиль программирования, который мы хотели бы изжить? Такая постаиовка вопроса, проблема совместимости и некоторые мелкие летали стали причиной елицолушного отказа принять прелложеиие об имеиовациых аргумеитах.
Примеры предлагавшихся расширений ЦффффЯЯЩ уменьшена за счет аргументов по умолчанию. Еще оЛин распространенный прием — дополнительные типы для представления наиболее типичных вариантов; с1аяв со1огес) х1пс)ох : рпЫ1с х1пс)ох роЫТсс со1огес) х1пс)ох(со1ох с=Ыасх) с х(пс)ох(ясапс)ахс),0,0,100,100,с) ( ) с1авя Ьогс)егес) х1пс)ох : риЫТс х1пс)ох ( риЫ1с: Ьохс)егес) хупдох(Ьогдег Ь=вупд1е, со1ог Ьс=Ыне) х1пс)ох(ясапс)агс),0,0, 100, 100,Ыаск,Ь,Ьс) ( ) с1авя х ахов хупхуре хс; 1пг и1ск, п1су, хя, уя; со1ог хс, Ьс; Ьохс)ег Ь; ХЯТйТВ хя; рпЫ1с: х агдв() // установки по умолчанию хх(всапс)агс)), п1сх(0), п1су(0), кя(100), уя(100), хс(Ыас)с), Ь(яьпд1е), Ьс(Ыие), хв(орел) ( ) // отменить умолчания: х ахова уяьяе(упс в) ( уя=в; геснгп *сын; ) х ахова Со1ог(со1ог с) ( хо=с; гегигп *Гыя; х ахова Вогс)ег(Ьогс(ег ЬЫ ( Ь = ЬЬ; хегихп *Гыя; ) х ахова Вогс)ег со1ох(со1ох с) ( Ьс=с; гегпхп *СЫя; ) // с1аяя х1пс)ох ( // х1пс(ох(х агдв ха); // ); // скопировать настройки ха Это дает иам иотациониое удобство, в некоторой степени эквивалентное тому, которое обеспечивают именованные аргументы: хупс(ох х; // окно по умолчанию хтпс)ох х( х агдя().со1ог(дгееп).увуяе(150) Этот прием ограничивает использование функции несколькими наиболее употребительными формами и потому код и поведение программы становятся более однообразными.