(письмо Африканцу)

Привет,

хочу ответить по поводу Джавы. :)

Замечание. Везде в этих заметках слово "жаба" означает язык Java, разработанный фирмой Sun, кажется, в 1995 году. Я его буду использовать, потому что переключать регистры мне лень.

Я буду использовать слово Джава. Регистр мне переключать тоже лень, а лишнюю буковку писать - чего уж там. Да и слово "Жаба" у меня, видимо, вызывает те же ассоциации, что и у тебя.

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

Часть 1. Жаба

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

Общее замечание - Джаву как язык программирования и как платформу (операционную среду) придумывало достаточно много людей, ни один из которых студентом-троечником не был. А многие, напротив имеют степени докторов в CS и приличный опыт разработки других операционных систем. Хороши, блин, студенты! Бад Триббл был один из ведущих разработчиков NextStep, Джеймс Гослинг написал первый Emacs - со Столманом на пару, Andrew System Toolkit (кто знает, тот поймет), NeWS и первую многопроцессорную версию Соляриса, да и Билл Джой тоже не х.. пинал - the principal designer of BSD UNIX и lead architector of UltraSparc IV:)

Версия про студентов также не объясняет то, почему Сан дал возможность этим троечникам распоряжаться ресурсами, а компании типа Оракла и ИБМ (вот кретины!) радостно подхватили эту идею, которая яйца выеденного не стоит. Непонятно как-то.

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

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

1) Основное свойство Жабы, которое, по замыслу, должно обеспечить большое преимущество перед С++ - ее простота. Посмотришь на язык в первый раз - душа радуется. Какой красивый, маленький язычок!

Отмечается, что основными достоинствами Джавы являются: объектно-ориентированность, портабильность, архитектурная нейтральность, динамичность, распределенность, безопасность, надежность, встроенная многопотоковость и простота. Желающие раскрыть эти понятия могут обратится к замечательной книге "Java in a Nutshell", 2 издание, страницы 3-8 :)

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

Примеры, примеры? Что значит "инициализации указателя на объемлющий объект"? В Джаве нет указателей, есть только имя объекта.

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

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

2) Даже лексика Жабы неочевидна - правила о том, что раньше раскрывается, \n или \u, кого угодно сведут с ума. Скажите-ка, что выведется таким вот оператором:   System.out.println ("a\u005Cnb");

А будет вот что:

a
b

потому как \u (это означает символ в Юникоде) "интерпретируется раньше других искейп-последовательностей", про это написано в доке, которую читать надо внимательно. Кроме того, использовать юникод-символы надо только тогда, когда это нужно, а еще System.out.println в основном используется для отладочной печати, а так - есть функции
форматного вывода в поток, (как в printf). Я даже удивился, как же это у тебя не было наезда на "слабые возможности консольного ввода-вывода :)"

3) Неясно, зачем у Жабы синтаксис, смахивающий на С. Единственное объяснение - желание завлечь программистов, пишущих на С или С++. То есть выбор синтаксиса по политическим, а не по техническим причинам. Синтаксис С хорош только если язык, сделанный поверх этого синтаксиса - С. Когда можно написать
while (*p++ = *q++);

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

Если же такого написать нельзя, то следует принять наиболее безопасный с точки зрения возможных ошибок синтаксис. Синтаксис С - не для чайников. Он требует внимания. Можно забыть фигурные скобки, можно поставить (случайно) точку с запятой после заголовка while. Профессионалы никогда не сделают подобных ошибок. Но ведь Жаба-то разрабатывалась для не совсем профессионалов!

Опять наезд. Джава разрабатывалась как ИНДУСТРИАЛЬНАЯ СОФТВЕРНАЯ ПЛАТФОРМА (со встроенным языком с тем же названием) для создания РАСПРЕДЕЛЕННЫХ КОМПОНЕНТНЫХ ПРИЛОЖЕНИЙ. Если эти слова непонятны, я расскажу подробнее. Но сама по себе компонентная архитектура предполагает как модульную сборку в application builders чайниками И ДРУГИМИ ПРОГРАММАМИ, так и создание компонент (маленьких и рюхливых, способных цепляться друг с другом и образовывать аппликации - как утилиты в Юниксе) - профессионалами.
Так что Джава с ее сишным (не плюсовым, а именно сишным) синтаксисом рассчитана именно на профессионалов.
А уж компоненты чайниками обычно клеются скриптовыми языками. Не Джавой.

Некоторые проблемы, связанные с синтаксисом С, в Жабе решены. Скажем, требование типа boolean в условном операторе почти что решает проблему употребления там одного равенства вместо двух. Решает, однако, не полностью, поскольку можно написать  if (a = b) где a и b - оба типа boolean. И надо заметить, что все компиляторы с С выдают предупреждение в этом случае.

Джавские тоже. К тому же "решить" проблему с помощью изменения синтаксиса - значит забить на совместимость с си, а в Джаве есть правило - то, что выглядит так как на С, работает так же. И это, на мой взгляд правильно.
Представляю, сколько воя было бы если бы if (a = b) было бы по-другому.

А вот неполный список проблем синтаксиса С, которые в Жабе не решены:
 - странные приоритеты ряда операций (у >> ниже, чем у +, и у + выше, чем у &)
 - отсутствие явной закрывающей скобки цикла и условного оператора и применение вместо этого
фигурных скобок - очень сильно чревато ошибками
 - оператор switch, где люди очень часто забывают break
 - совпадение оператора выхода из цикла (break) и из ветви switch

Это все то, что есть и работает как в С. То же самое. И, кстати, почему странные?

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

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

Джава - это язык, который помогает не ошибаться. Отсутствие поинтеров, множественного наследования, запрет на неявное преобразование типов, последовательность в объектном подходе, отсутствие переопределения операторов, отсутствие макросов, - всё это, имхо, очень и очень способствует. А какая работа с иксэпшнами! Сказка просто.
Скажи мне простую вещь, друг, в плюсах - если иксепшн возникает в конструкторе, считать объект созданным - али ишшо нет? А в Джаве это просто :)

4) Авторы Жабы выкинули несколько вещей, которые они либо боялись использовать, либо не знали, что это такое. В частности, сохранив блочную структуру языка, они выкинули перекрытие переменных в блоках. Теперь во вложенном блоке нельзя описать переменную, совпадающую с переменной в объемлющем блоке. Объясняется это "слишком сложным характером" этого дела - явно студенты просто не поняли.

Про студентов я уже сказал. А про сложный характер - это правда. Так же, как и инициализация параметров в конструкторах по умолчанию и прочие кошмарики.

5) Они выкинули goto. Знаю, знаю, что сейчас тысяча возмущенных людей напишут мне, что goto вреден, должен быть запрещен, и без него программы лучше и яснее. Отвечу - оператор присваивания не менее вреден, ведь с помощью него можно составить совершенно нечитаемые программы. Не зря его нет в LISP. Впрочем, программы на LISP ничуть не яснее, из чего следует, что и вызов процедуры должен быть запрещен тоже. Более того, все неправильные, не работающие или ненужные программы, как правило, содержат хотя бы один из указанных операторов.

Я не считаю, что goto надо запрещать. Просто есть разные технологии программирования, мне больше нравится без goto. А передача управления всякими goto суть FAR джампами - это хорошо для  низкоуровневого программирования, от которого я хотел бы находиться как можно подальше.

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

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

6) Я никогда не видел языка с модульной структурой, такой же идиотской, как в Жабе. Близко к тому - видел. Скажем, у Ады модульная система достаточно убогая. Но Жаба! Ощущение такое, что люди вообще не знали ни одного языка, и никаких книжек не читали. Для сравнения.
[skipped]
В результате сказать, кого импортирует данный класс, никогда нельзя. При использовании второго механизма нельзя сказать, из какого пакета произошел класс CallEvent. При использовании первого способа список импорта имеет гигантский размер, что усложняется необходимостью для каждого класса иметь свой оператор импорта. Кто придумал такое, заслуживает очень неприятной смерти.

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

7) Вообще, система с пакетами через точку явно непродумана. Например, отсутствует относительная адресация. Нельзя написать
import com.dvsoft.cts.*;
и потом употребить event.CallEvent - только полная квалификация! И если наш класс сам принадлежит к пакету com.dvsoft.cts - к подпакету доступ тоже только с полным путем!

Да, потому что может появиться неоднозначность. Например, есть:

com.dvsoft.cts.event.CallEvent;
com.metabyte.event.CallEvent;

допустим, напишем:
import com.dvsoft.cts.*;
import com.metabyte.*;

и как тогда трактовать event.CallEvent? Именно по этой причине "звездочка" означает только
ОДИН уровень вложенности.

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

Понятнее он становится. Короче - нет, это правда. Но, как по мне, понятный длинный код куда как лучше короткого и непонятного.

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

Это опять-таки вопрос скорее стиля программирования. Согласен, на Джаве тоже можно написать непонятно, но по крайней мере написать на плюсах непонятно еще проще. ГОРАЗДО проще, не знаю уж почему, но подавляющее большинство плюслвого кода, который я сопровождал было написано людьми, для которых написать заковыристо было важнее, чем просто и понятно тому, кто придет потом. Не люблю я такие вещи.

9) Необходимость помещать каждый публичный класс в отдельный файл приводит к появлению сотен небольших файлов, и программу становится невозможно читать. Я хочу спросить у фанатов Жабы - вы свои программы хоть иногда печатаете? Не говорите мне, что это устарело и более ненужно. Просто вы не можете ее напечатать, вот и говорите так. А я свои программы изредка печатаю. Приятно почитать программу утром в кафе за чашкой двойного испрессо.

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

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

Согласен. Хотя браузеры помогают, в общем.

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

Так в этом же соль всей Джавы, весь кайф, динамичность пресловутая - ради чего она и задумывалась! Живые приложения, которые способны собираться по кусочкам в рантайме - это и есть суть компонентного софта, когда (совместно с системой именования, поиска и т.д - см. про CORBA) можно получить действительно распределенные и reusable программы, мечта всех разработчиков :)

11) процедуры и классы можно использовать до описания. Это не только усложняет компилятор, но и делает программу менее понятной, потому что труднее найти определение нужного тебе объекта. Вообще отступление о компиляторах. В свое время языки писались для людей, без учета сложности компиляторов. Это часто приводило к зауми - достаточно упомянуть передачу параметров по изображению в Алголе-60. Написание компиляторов с некоторых языков было нетривиальной задачей - например, по синтаксическому разбору Ады или Алгола-68 защищались диссертации. Примерно со времени С и Паскаля наметилась тенденция делать языки так, чтобы их проще было компилировать, и оказалось, что такие языки и для человека удобнее, ведь человек - это тоже компилятор. Человек читает программу с целью ее понять, и язык, который легче разбирается компилятором, и для человека лучше. Так вот, в Жабе явный откат назад - считается, что машина железная, пусть и трудится. В итоге
программы легче писать, но труднее читать. А читать - важнее.

В Джаве программа описывает логику работы приложения, что на мой взгляд важнее, чем "проще было компилировать" А насчет железа - я согласен с ИБМ, пусть человек думает, а машина работает. Умные компиляторы гораздо очень важны для индустриального программирования. Под "индустриальным" программированием я понимаю программирование с полным отчуждением результата труда программиста от него самого - то есть, программа написана просто, понятно, отражая то ЧТО надо  сделать, и скомпилирован хитрым компилятором в эффективный код. При всем при том, этот код как сам по себе, так и в составе приложений должен быть эффективно оттестирован, желательно не вручную. И эта программа, этот код должен быть reusable и быть к тому же куском, способным работать с другими.

12) Лично я не люблю описания переменных в произвольных местах, люблю в начале процедуры. Тогда легче по переменной определить, где она описана, и, если хочешь ввести новую переменную, виднее, есть она уже или нет - это обычно касается простых временных переменных, вроде i и j.

Для простых пременных это и так понятно, и проще их описывать на месте, а вот специальные лучше
описывать в начале, я согласен. Опять-таки, вотпрос стиля.

13) Переменную можно описать в заголовке цикла, но она не локальна в этом цикле, что похоже на маразм.

Это вытекает из неперекрытия имен в блоках. И что в этом плохого? Она локальна в блоке, и на мой взгляд это куда как более правильно.

14) Почти что во всяком серьезном языке есть возможности для метапрограммирования, то есть описания макросов. В некоторых языках они развиты очень хорошо (POP-2, PL/1, некоторый ассемблеры), в некоторых - похуже, как, скажем, в С. В некоторых языках их нет, но реализаторы добавляют их в виде расширений. В некоторых языках эти возможности присутствуют в виде средств расширения синтаксиса (Алгол-68), или написания обобщенных процедур (Ада, С++). И только в жабе их нет и не планируется. Это оправдывается тысячей аргументов - и непонятны, мол, макросы, и спомощью классов можно без них обойтись, надо только предусмотреть побольше виртуальных методов (черт с ней, с эффективностью). А в итоге писать сколько-нибудь сложную реальную программу практически полностью невозможно.

Господи, как хорошо, что макросов в Джаве нет! И комментариев у меня тоже нет :)

Рассмотрим простой пример. Мы хотим иметь хэш-таблицу, ключами в которой являются целые числа - самый простой и эффективный вид хэш-таблицы. В то же время мы не хотим дублировать код для хэш-таблицы на все возможные случаи. Так вот, в С для этого мы напишем макрос, в Аде - generic package, в С++ хорошо сгодится template. В Жабе мы применим стандартный класс Hashtable, который берет в качестве ключей произвольные объекты, завернем целые числа в эти объекты, выделив каждый из них в куче, и будем вызывать в них виртуальные метода hashCode и equals. Ну да, работать будет. А кого в наше время заботит эффективность?

А в наше время заботит не эффективность исполнения на уровне железа, а эффективность создания, поддержки софта и удобство работы с ним :) Можо сколько угодно плакать о том, что программирование как искусство ушло, что были люди в наше время, которые в 32 К такое запихивали, и что толстые неэффективные приложения всех затрахали. Всё это правда, но к Джаве отношения не имеет. Скорость исполнения кода - это единственная серьезная проблема, связанная как с технологией интерпретации байткода, так и, быть может, с кривизной начальной имплементации Джавских библиотек (вот уж что писали студенты :), а эффективность в смысле создания приложений - тут с Джавой все ОК.

Заботить эффективность исполнения долно того, кто кладет Джава-среду на железо, и тут уж пусть все делается на си и ассемблере - и всем польза будет :)

15) То же касается условной компиляции. Любая серьезная программа всегда содержит куски, которые надо по-разному выполнять в зависимости от конкретной версии программы, конкретного применения и т.д. Обычно это делается с помощью условной компиляции, частенько в сочетании с макросами.
[skipped]
 - на орбиту придется брать с собой весь код, то есть одноступенчатая ракета должна будет иметь
столько же памяти, сколько и многоступенчатая.
Неужели это именно то, чего добивались?

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

Кроме того, условная компиляция и макросы очень удобны для отладки. Например, в текст вставляются вызовы макроса ASSERT, которые в отладочном режиме раскрываются в проверку условия, а в боевом - в ничего. На Жабе это невозможно - код будет исполняться и тратить время. Для этого

Это опять-таки просто неправда. То есть в отладочном режиме код будет исполняться, а в боевом
- его просто не будет.

16) Нормальные языки содержат конструкции для описания статических данных - инициализируемые
массивы и записи, например. На Жабе с этим грустно. Есть убогое подобие инициализации массивов.

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

public final int theArray[][] = {
  {16, 19, 0, 0, 0, 0, 0}, {-1, -1, 0, 1, 1, 0, 0}, {-1, -1, 0, 1, 1, 1, 0},
  {-1, -1, 0, 0, 1, 0, 0}, {-1, -1, 0, 0, 1, 1, 0}, {-1, -1, 0, 1, 0, 0, 0},
  {-1, -1, 0, 1, 0, 1, 0}, {-1, -1, 0, 0, 0, 0, 1}, {-1, -1, 1, 1, 1, 1, 0}
};

Инициализация записей (гордо называемых классами) делается с помощью конструкторов.

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

И то, и другое выполняется во время исполнения, то есть во время запуска такой программы куча времени будет съедена на эту инициализацию, и в программе будет, кроме самих данных, присутствовать код, исполняемый ровно один раз. Зачем это надо? Представьте себе, что вы пишете восходящий синтаксический анализатор. Такой анализатор имеет обычно большую-большую таблицу, которая на С записывается просто и естественно, и не тратит для своего создания ни такта процессорного времени. А на жабе это все - исполняемый код!

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

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

Более того - большинство реализаций даже константы (то, что описано как public static final int) - определяет во время исполнения!

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

Мне все равно, открывается окно за 1/100 или за 1/1000 секунды, если реакция юзера на это событие - 10 секунд. А риалтаймовые вещи на Джаве писать не надо, и никто не заставляет... С точки зрения логики программы - это константы, есть такое понятие - и мне этого достаточно. Я пишу программы на логическом уровне, а не на уровне железок. Для системного программирования есть прекрасное сочетание С+ассемблер, и слава Богу.

17) Одно из замечательных изобретений Вирта - перечислимый тип. Жаль, что он от него отказался в Обероне.

Наверное, старик Вирт ошибся, да? :)

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

То же самое. Мы, похоже, просто понимаем эффективность по-разному. К тому же, насчет отсутствия проверки типов - неправда, в Джаве неявное пребразование не пройдет.

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

Это я не знаю, зачем. Похоже как-то связано с security. Может, есть какие-то еще причины, врать не буду.
 

19) Система экспорта-импорта в Жабе настолько сложна, что правильная ее реализация становится почти непосильной задачей. Особенно с учетом того, что импорт классов может быть взаимным. В результате ни в одной из существующих реализаций нельзя быть уверенным, что проект пересобран полностью. Это наблюдается в J++, JDK и JBuilder.

В Symantec Cafe - все нормально, хотя иногда глюки бывают. Но очень редко.

Единственный надежный способ - стереть все class-файлы, после чего сделать полный Build. При этом надо, конечно, следить, чтобы в classpath случайно не было ссылок на так же называющиеся классы. В общем, поддержка проекта превратилась в постоянный геморрой и, похоже, так и было задумано. Более того, все стандартные компиляторы
вслед за JDK валят class-файлы туда же, где уже лежат Java-файлы, делая крайне затруднительным стирание всех class-файлов.

Ну, это не так. Можно сказать, куда валить то, куда - сё... Без проблем. Стандартнее компилятора не бывает - symanteковский, включен в jdk.

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

Как я уже говорил, Джава (как и Смоллток) ориентирована на на файлы, а на классы. Хорошо это или нет - другой вопрос, но ответ на вопрос о области видимости должен быть понятен.

21) Для "Надежного" языка разумно было бы иметь (возможно отключаемый) контроль целого переполнения. Либо язык для приложений - тогда нужен контроль. Либо для ковыряния битов (как в С) - тогда не нужен. Жаба вроде бы всегда провозглашалась языком для приложений. Так где этот контроль?

Ну как же? Контроль границ массивов... А переполнение целого - какие последствия может принести, если только по этому целому не индексировать? (а если индексировать, то сработает контроль индексов)

22) Каждый раз, когда мы описываем структуру (она же запись, она же класс), происходит выделение памяти в куче. Каждый раз, когда мы ее потом используем, происходит обращение по указателю. Зачем? Я понимаю, все это может быть полезно для "классов" - из-за возможного наследования их как раз полезно в куче размещать.
[skipped]

В Джаве все вещи - это объекты. По крайней мере, это последовательно. И "записи" - тоже. Никто не мешает эти вызовы пустых конструкторов оптимизировать в рантайме, что и делается,  впрочем.
 

23) Хотя Сотрудник MS и пытался меня как-то убедить, что в сборщике мусора нет ничего страшного, я все же отношусь к нему подозрительно. Я предпочитаю точно знать, когда и что в программе происходит, и почему. Особенно в приложениях, критичных по времени.

То же самое. Джава хороша чуть ли не в первую очередь тем, что вручную память там распределять
нельзя. 60% всех плюсовых и сишных багов связано с распределением памяти...
Для системы типа Джавы сборщик мусора должен быть очень хитрым, (представьте себе
распределенное приложение со сборкой мусора - например убирать ненужные части remote объектов)
но оно себя оправдывает. УЖЕ оправдывает, не только в теории. За три года прогресс виден
просто очень.

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

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

  int gen_next_lexem (char ** p);

  next_lexem = get_next_lexem (&p);

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

  Parser pars = new Parser (p);

  next_lexem = pars.getNextLexem ();

Вроде и красиво, но только жалко создавать класс без нужды. Класс из ничего, класс для ничего, класс
только для обхода убогого синтаксиса языка.

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

А теперь модифицируем это, чтобы возвращался не только тип лексемы, но и сама лексема.
На С это так:
  int gen_next_lexem (char ** p, char ** lexem, int * lexem_len);
  next_lexem = get_next_lexem (&p, &lextext, &lexlen);
На Жабе придется создавать еще один класс - лексема, в котором хранится и лексема, и ее длина, и ее
тип. И, конечно, придется выделять память для нового класса и для нового объекта String (хорошо еще,
если сам текст копировать не придется, но это зависит от реализации String).
Ну зачем это все? Неужели специально все сделано, чтобы эффективность поменьше была?

Нет, конечно. Но разве не логично предположить, что лексема - это отдельная сущность? И потом, в этой записи то, что явно не указано, что lextext изменился - явно не облегчает понимание. Кто его знает, что там с ним происходит
внутри функции. Конечно, амперсенд вроде говорит о том, что его собираютмя изменять, но ведь не факт...
 

25) Одно из замечательных изобретений Вирта, реализованное в Модуле-2, а также в каком-то виде в С - это разделение текста на definition и implementation. Хорошо, когда отдельно описан интерфейс, отдельно - реализация. Соответственно, один файл содержит комментарии о том, что делается, а другой - как делается. И, чтобы понять, что делает данная процедура, не надо лопатить кучу текста. А файл с реализацией, в свою очередь, не содержит гигантских пользовательских комментариев, и потому более обозрим. Так вот, в жабе этого нет. Всегда советуют моделировать это с помощью интерфейсов либо абстрактных классов. То есть применять виртуальные методы. С какой, спрашивается, стати, я должен применять косвенный вызов процедуры, а не прямой, только из-за того, что язык сочиняли идиоты?

В Джаве все вызовы - виртуальные, да будет известно. А интерфейсы и абстрактные классы действительно полезны, и не только как маркерные. Для того, чтобы понять, что делает система, надо смотреть иерархию классов, а не файлов, поэтому держать в разных файлах definition и implementation смысла нет, если ты об этом. Использование интерфейсов (которое пошло из Objective C) позволяет делать все то, что позволяет делать множественное наследование, но гораздо понятнее и логичнее. Что, примеры приводить?

26) Теперь немножко о библиотеке. Это не недостаток языка, а мое личное неудовлетворение. Бывают языки, содержащие библиотеку (или большую ее часть) в себе, например, PL/1 с его оператором PUT EDIT, или BASIC. Бывают языки, от библиотеки почти независимые, как С. Мне всегда больше нравились последние, потому что позволяли обходиться без библиотеки. Обычно, если ее не использовать, то в С можно обойтись небольшим рантаймом, что особенно здорово для встроенных приложений.

А оконную систему на С в ДОСе каждый писал себе сам, и даже после появления кривой win32 в которую всех загнали, некоторое время - тоже. И file chooser, и т.д. И только лет через 6-7 стали использовать общие компонеты типа спеллчекера. Это я про системные библиотеки :)

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

В Жабе же реализован самый извращенный, третий вариант. А именно язык вроде бы и отделен от библиотеки, а вроде она и вылазит в самых неожиданных местах. Ну например, то, что строка в кавычках - значение класса String, а исключительная ситуация "указатель равен null" - класса NullPointerException. И таких случаев много - когда что-то является объектом какого-то левого класса. В результате никогда неясно, что используется в программе, а что нет.

Нет-нет, все правильно. Джава - это не язык, это куда как большая штука. Это и среда исполнения,
и виртуальный компутер. Так что библиотеки с языком связаны очень сильно. Никто никогда не говорил
(кроме микрософта), что Джава - это "только язык". Глупо как-то. На сайте Джавасофта так и пишут - Java Platform.
 

27) Сама библиотека оставляет желать лучшего. Почему, например, для узнавания текущей даты я должен выделять в памяти объект?

(терпеливо) Потому что куда-то ты эту самую дату засунуть должен, а в Джаве все - объекты :).

К тому же дата в Джаве, это не просто long а сложная штука. Джава, как и всякая порядочная система,
работает с локалями, форматами даты, времени, таймзонами и так далее. Это что, плохо? Это не часть
_языка_, конечно, но часть Джава-платформы. Как и поддержка юникода, которая, впрочем, и часть языка тоже.

А вот еще задачка, достойная пера. Напечатать текущую дату в формате
 дд.мм.гггг чч:мм:чч.МММ (МММ - миллисекунды).
Ну все сделано, чтобы только сделать это невозможным! Вообще, опыт практического использования
библиотеки заставляет подумать, что она была сделана левой ногой пьяного матроса.

Ну кто же говорит, что это сложно :)

SimpleDateFormat f = new SimpleDateFormat("dd.MM.yyyy hh:mm:hh.SSS");
Date d = new Date(); // get current date and time
System.out.println(f.format(d));

наезд про левую ногу я опускаю.

28) В Жабе появилось слово "deprecated". Это то есть когда в новой версии старый метод еще поддерживается, но не поощряется. Хорошая, на первый взгляд, возможность. Но вот почему выходит версия жабы (JDK 1.0), а через полгода другая (1.1), и в ней половина библиотечных функций уже "deprecated"? А о чем думали полгода назад? А еще "отдепрекатили" целую графическую библиотеку (AWT), сделав новую версию (Swing), причем специально сделали это, дождавшись, пока все выпустятинструменты для поддержки AWT.

Спешили. Мне это тоже не нравится. Единственное, что понятно - шумихой и ранней имплементацией
(хоть какой) к идее привлекли достаточное количество денег и независимых разработчиков. Иначе Джаве
пришла бы тихая смерть, хоть идея и прекрасная (посмотрите, где ныне NextStep). Конечно, нехорошо.
Конечно, корыстные Сановские интересы. Это правда. Но сработало...

AWT между тем, никто не отменял, и Swing на нем базируется.

29) При написании на С много внимания уделяется всяким случаям вроде "А что если функция malloc вернула NULL?" Так вот, в Жабе считается, что память всегда есть. В общем-то никаких оснований для этого нет. А когда память кончится, будет брошена эксепция вроде OutOfMemoryException, которая есть объект и должна быть выделена в куче...

Там еще под это остается место, не боись. Специально рассчитано :)

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

И на второй, и на третий. Только важно не увлекаться...

Как только применяется какой-нибудь метод разработки программ, при котором управление не передается непосредственно, а "ныряет" в переходник, то все это летит к черту. Например, если мы написали процедуру обхода дерева, которая в каждом узле вызывает пользовательскую процедуру, то вполне естественно, что в этой пользовательской процедуре что-то может пойти не так. Мало ли что - файл не пишется, ресурс не выделяется, ошибка в исходных данных. Тут бы и бросить ексепуию, прекратив обход, а фигу. Эксепция должна быть заранее предусмотрена еще при написании общей процедуры обхода дерева.

Зачем? Что-то я не понимаю, право. Иксепшн должна генерить имено пользовательская процедура. Тебя же никто не заставляет ее форвардить вверх?

31) Меня очень раздражает оператор "+" для строк. Не люблю исключений. Вообще, значит, операторы не переопределяются, а вот для строк пожалуйста. При этом, если объект не строка, вызывается специальный метод со специальным именем toString... Ну зачем превращать язык в BASIC? Ясно же, что все так и будут применять этот оператор для складывания строк, плюя на эффективность. Есть класс StringBuffer, а кто им пользуется?

Да, это непоследовательное место. Но как по мне, то очень удобное... мне нравится. Опять-таки,
какая эффективность имеется в виду?

А класс StringBuffer используется именно при работе со строками - в основном, неявно, в том числе при работе переопределенного плюса.

32) С определяет int как "наиболее эффективное целое число, не короче, чем 16 бит". То есть если на машине длина слова 18 бит, то и целое будет 18 бит. Жаба же определяет int как ровно 32 бита, а long как ровно 64. И если на машине нет 32-битных чисел (например, есть только 64-битные), придется моделировать. Мне это не нравится. Отсутствие беззнаковых чисел мне тоже не нравится.

А вот мне как раз нравится то, что я твердо знаю, какой у меня int и какой char. Мне вообще нравится идея виртуального, по-человечески спроектированного окружения, под которое можно писать нормальные приложения. И пусть о эффективности исполнения заботится сама система. А я буду заботится о логике работы программы.

33) Жаба предоставляет некоторые особо высокоуровневые возможности, такие, как клонирование (глубокое копирование) объектов и сериализация. Обе опасны в неумелых руках. Чайник, не задумываясь, склонирует (или сериализует) громадный граф, лишь бы добиться какой-то сиюминутной цели. Сериализация уже привела к тому, что программмы хранят свои настройки не в приятных для глаза ini-файлах, и не в Registry, а в многочисленных файлах, полученных путем сериализации объектов.

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

И потом, какое Registry не на win32? Или давайте все бросим, будем писать только под мастдайку?
 

Часть 2. Околожабство.
2.1. Техническое околожабство.

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

1) Самое очевидное техническое околожабство в том, что жаба компилятор, и с самыми лучшими виртуальными машинами все же существенно отстает от С++ (при этом речь идет о ОО-программе на С++, то есть программе со всеми этими красотами вроде динамической памяти и виртуальных методов). От нормальной программы на С жаба отстанет еще больше.

Сколько лет шлифовались компиляторы с плюсов? И среда исполнения (win32, к примеру?) Джаве - три года, причем она претендует на программную платформу, то есть на язык, компилятор(ы), рантайм(ы) и библиотеки. Подожди еще года три, посмотрим. К тому же hotspot компилятор под Win32, к примеру, отстает от компилированной С программы
всего на 10-15 процентов.
 

2) Далее, из-за переносимости жаба не позволяет нормально использовать возможности машины и ОС. Кто видел интерфейсы, писанные на жабе, даже с новомодным Swing, тот согласится, что по сравнению с виндами (а также по сравнению с Х-виндами) это просто убожество.

Я видел, и я не соглашусь. Swing выглядит просто замечательно. Медленный, это да. Пока.

Аналогично, Win32 имеет богатый набор примитивов синхронизации. Юникс тоже имеет (хотя и не столь богатый). На жабе все это недоступно по определению (если только не использовать native методы, интерфейс для которых
разработан так, чтобы никто их не использовал).

Джава имеет примитивы синхронизации в языке и в архитектуре компонент. (Например, в EJB.)
А вообще, никто не мешает эти примитивы и возможности Джава-платформы маппить на нативные.

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

Это слова человека, который не использовал JDK 1.1 и выше. Class-файлы пакуются в .jar с подписью, компрессией и тому подобное. И CLASSPATH в общем-то уже не нужен.

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

Ну, это уже извращения, согласен.

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

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

5) Жаба также вводит идиотские правила именования - классы с большой буквы с промежуточными большими буквами (ИмяКакогоТоКласса), методы - тоже с маленькой (вотКакПоДурацкиСмотрится), поля (данные) - тоже. Константы - целиком большими буквами через подчерк (ПОЛУЧАЕТСЯ_ВОТ_ТАК). Да, кстати, имена методов должны быть глаголами (getNextElement () вместо nextElement ()).

Как по мне, все очень здорово. С венгерской записью и не сравнить!

(Ну, вот, к примеру, из пережитого недавно. Понадобилось мне вставить JavaBean в MFC программу. Передача параметров - тихий атас просто. Вот почему ЭТО выглядит так:

typedef struct tagVARIANT  {    VARTYPE vt;    unsigned short wReserved1;
    unsigned short wReserved2;    unsigned short wReserved3;    union {
        unsigned char        bVal;                        // VT_UI1.
        short                    iVal;                        // VT_I2    .
        long                    lVal;                        // VT_I4    .
        float                    fltVal;                    // VT_R4    .
        double                dblVal;                    // VT_R8    .
        VARIANT_BOOL        boolVal;                        // VT_BOOL.
        SCODE                    scode;                    // VT_ERROR.
        CY                        cyVal;                    // VT_CY    .
        DATE                    date;                        // VT_DATE.
        BSTR                    bstrVal;                    // VT_BSTR.
        IUnknown                FAR* punkVal;            // VT_UNKNOWN.
        IDispatch             FAR* pdispVal;            // VT_DISPATCH.
        SAFEARRAY            FAR* parray;            // VT_ARRAY|*.
        unsigned char        FAR* pbVal;                // VT_BYREF|VT_UI1.
        short                    FAR* piVal;                // VT_BYREF|VT_I2.
        long                    FAR* plVal;                // VT_BYREF|VT_I4.
        float                    FAR* pfltVal;            // VT_BYREF|VT_R4.
        double                FAR* pdblVal;            // VT_BYREF|VT_R8.
        VARIANT_BOOL        FAR* pboolVal;                // VT_BYREF|VT_BOOL.
        SCODE                    FAR* pscode;            // VT_BYREF|VT_ERROR.
        CY                        FAR* pcyVal;            // VT_BYREF|VT_CY.
        DATE                    FAR* pdate;                // VT_BYREF|VT_DATE.
        BSTR                    FAR* pbstrVal;            // VT_BYREF|VT_BSTR.
        IUnknown FAR*        FAR* ppunkVal;            // VT_BYREF|VT_UNKNOWN.
        IDispatch FAR*        FAR* ppdispVal;        // VT_BYREF|VT_DISPATCH.
        SAFEARRAY FAR*        FAR* pparray;            // VT_ARRAY|*.
        VARIANT                FAR* pvarVal;            // VT_BYREF|VT_VARIANT.
        void                    FAR* byref;                // Generic ByRef.
    };

Почему что-то начинается с большой буквы, что-то с маленькой, а что-то и все - большими буквами,
хотя и не константа? :) Откуда что берется? В документации - не слова, в MSDN - ни слова, кроме как
эта структура, и как мне ее понимать теперь? И это - типичный пример. Почему сгенеренный код на VC++
выглядит так:
------
// itvtest.h : main header file for the ITVTEST application
//

#if !defined(AFX_ITVTEST_H__5D5B8C78_49D7_11D2_BE48_00A024D8474C__INCLUDED_)
#define AFX_ITVTEST_H__5D5B8C78_49D7_11D2_BE48_00A024D8474C__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#ifndef __AFXWIN_H__
 #error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h"  // main symbols

/////////////////////////////////////////////////////////////////////////////
// CItvtestApp:
// See itvtest.cpp for the implementation of this class
------
Как по мне, это все выглядит просто тошнотворно и отвратительно. И слэшей понавставлено зачем?
Ну да ладно, это к вопросу нравится - не нравится.

И конечно, сам Sun это не соблюдает - у него методы называются как что попало.

Примеры, пожалуйста? Я такого не разу не видел.
 

В общем, все эти схемы раскладки и именования отвлекают внимание от собственно программирования и приводят к плохо читаемым программам.

А по-моему, строго наоборот. Может, это дело привычки, конечно.

6) Способ именования пакетов в жабе - отдельная песня. Они называются по адресу компании в обратном порядке. Скажем, мы зарегистрировали домен dvsoft.com - вот наши классы и называются com.dvsoft.... Это все хорошо, когда апплеты по сети приезжают, и совершенно бессмысленно при написании нормальных программ.

А что значит "нормальных программ"? Программы для одного компутера, которую ты будешь сопровождать, и которую твой преемник перепишет заново, отчаявшись понять и вытащить из нее куски, полезные для понимания и использования в дальнейшем? ;)

Ведь кроме всего прочего единство имени не означает единства версии. Подход Микрософта с его COM мне нравится больше - не имя определяет интерфейс, а Глобальный Идентификатор.

Мне кажется, тебе вообще просто близок подход Микрософта. В том-то и дело.

Впрочем, в именовании объектов можно использовать любой подход, но, как мне кажется, доменный проще для понимания и использования.

7) Обзор технического околожабства будет явно неполон без такого чуда, как javadoc. Это, кто не знает,
когда перед процедурами, переменными и классами делаются офигенного размера вставки,
написанные на диковинной смеси HTML и специальных тегов. Потом программа подается на вход
специальной утилите, которая делает по этому делу красивый HTML с описанием интерфейса. Как
правило, выглядит он по идиотски, например:

 int getNextNumber ()
 - returns the nest number.
 Parameters: none
 Result: next number

В доке же ясно написано, что глупо писать в описании то, что уже сказано в имени функции (переменной,
класса...) Зачем же утрировать? А Javadoc дает прекрасный и очень полезный инструмент создания
документации, унифицированный, совместимый с системами контроля версий и т.д.
Ну, не умеешь пользоваться - или нравится - не пользуйся, зачем же сразу "по идиотски"? :)
 

Читать это - одно удовольствие. Читать исходный текст - одно мучение, Вы хотели бы иметь HTML-теги у
себя в программе?

А ты пишешь документацию в процессе разработки (ехидно?) К тому же здесь документация и играет
роль definition, в котором можно очень просто понять как устроена программа, какая связь между классами
и т.д - не залезая в исходники. Действительно ОЧЕНЬ полезно. Документированных программ на Джаве я видел куда как больше чем на плюсах, кстати.

Мое мнение однозначно - комментарии это для человека. Или должен быть definition-модуль, в котором в красивом и понятном виде написано, что делает процедура. Если уж такого модуля нет, можно, конечно, и в основном тексте написать. Но - красиво и понятно, для человека, а не для машины. Хотите отдельный документ - пишите свои комментарии хотите в HTML, хотите в ворде - но отдельно. Не в исходном тексте. Этот текст еще людям читать.

Честно говоря, мне эти комментарии не мешают, тем более можно их и цветом притушить, и вообще
визуально с экрана убрать. Хотя, может, это и не так удобно.

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

 class Point {
   private int x, y;

   public Point (int x, int y) {
     this.x = x;
     this.y = y;
   }

   public int getX () {
     return x;
   }

   public int getY () {
     return y;
   }

   public void setX (int x) {
     this.x = x;
   }

   public void setY (int y) {
     this.y = y;
   }
 }

Я спрашиваю - ЗАЧЕМ?
Я бы еще понял, если бы эти переменные хранились в какой-то извращенной
форме. А они хранятся как есть, и с большой вероятностью никогда не будут храниться по другому. Так
зачем обращаться к ним через функции? Ну что этим достигается? Это явный идеологический бзик.

И я спрашиваю - зачем? Что за глупые примеры ты приводишь, и выдаешь их за свойства Джавы? :)
И передергивать не надо. Я в такой ситуации бы сделал эти поля public - и всё.

Кроме одного случая. Дело в том, что в Джаве, когда ты пишешь компонент, - то есть кубик, который
будет использоваться в визуальном построителе приложений, - то такие методы (set/get) нужны
для того, чтобы построитель произведя интроспекцию (посмотрев внимательным взором)
кода, понял, что есть параметр, который юзер в процессе компоновки приложения может изменить.
Тогда он берет это property и помещает его в табличку свойств этого компонента. В данном приведенном
примере у тебя будет в табличке два поля: X и Y и их значения можно будет назначить визуально.
А методы доступа в данном случае нужны, потому как это соглашения по синтаксису. Ты можешь
указать их и в явном виде в специальном описании, если не хочешь, чтобы они начинались с set и
get.

Подробнее - JavaBeans specification.

Я убежден - методы, высовываемые из класса, должны делать какое-то сложное действие. Иногда, для
data consistency, поля полезно скрыть. Скажем, если бы мы разрешали менять x и y только оба вместе,
я был бы обеими руками за то, чтобы делать это через методы. Был бы метод

 void setXY (int x, int y)

и все отлично. Хотя лично я в этом случае ввел бы в язык поля, доступные снаружи только на чтение, и
избежал бы вызовов процедур для чтения переменных, оставив только для записи. А скрывать поля и
тут же давать методы для доступа к этим полям ПООДИНОЧКЕ - это явный маразм.

Да, конечно. Если это не компонент, которому нужно эти свойства редактировать в дизайн-тайм.

Апологеты этого способа дошли до того, что класс не только наружу не должен высовывать поля -
внутри их не должен использовать! То есть должен сам пользоваться этими функциями доступа. Для
этого рекомендуется начинать имена полей с подчерка, чтобы их противный внешний вид отвращал от
их использования.

Это явный маразм. Апологетов таких надо отсылать.

9) Некоторым развитием этого служат так называемые "свойства" (properties). Это когда, считается,
что у класса как бы есть поле (на самом деле нету), а мы как будто присваиваем этому полю, а при этом
происходит какое-то действие. Например, есть свойство "FontSize", и мы пишем
  setFontSize (10);
И при этом все перерисовывается и размер фонта меняется. В Дельфях так вообще синтаксис
присваивания для этого используется. Так вот, мне это очень не нравится. Название должно отражать
суть процесса. Если метод только выставляет переменную, пусть называется set-что-нибудь. А если
делает что-то - то do-что-нибудь. Какой-нибудь осмысленный глагол. В нашем случае - какое-нибудь
changeFontSize или enlargeFont, а еще лучше вообще такого не иметь, а иметь что-нибудь вроде
  changeTextFont (String type_face, int font_size);
или
  changeTextFont (Font font);
А то некрасиво - одним вызовом мы меняем фонт, другим - его размер, а в итоге все жутко моргает.
Это, конечно, никого не волнует - когда что-то моргает.

Эх, слышал звон...

Все правильно, что говоришь, если речь идет о рантайме. Но компонентам-то эти свойства назначаются
в design time - когда ты собираешь апликацию, и назначаешь все эти цвета, размеры и процее.
А в рантайме у тебя быть может даже и методов этих в коде не быть!

10) Жабцы очень любят "шаблоны разработки" (design pattern). Иногда дело доходит до смешного -
например, они хотят запретить оператор switch, а всюду, где он нужен, использовать классы. Делается
это так.
[skipped]

Это имеет отношение к объектно-ориентированному дизайну приложений, и похоже, что ты не очень понимаешь зачем, и к чему это все.

Паттерны нужны для унификации представлений о типичных объектных структурах и методиках, а вовсе не для того, чтобы свитчи изживать :) Есть хорошая книжка на эту тему - Design Patterns : Elements of Reusable Object-Oriented Software (Addison-Wesley Professional Computing) by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
Grady Booch (Designer). В целом, это целая наука - в двух словах не рассказать. И не буду :)

2.2. Политическое околожабство

Здесь тоже надо рассматривать несколько аспектов - политический, технологический, системный,
личный. Попробуем.

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

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

Так вот, зрелая софтверная платфома есть только у МС. Ну, и вот сейчас - Джава, которая пытается ей быть конкурентом (и с моей точки зрения, она ГОРАЗДО) лучше Win32. По дизайну, по крайней мере. И по тому, как она открыта. По реализации она сыровата, - но это ведь вопрос времени. Если не придушат, конечно.

И еще: Джава-платформа, как и Win32 отчетливо идут к сетевой распределенности, к компонентному софту. Это когда у тебя аппликация строится из кусков, которые работают на разных железках (необязательно даже на универсальных компьютерах) одновременно. Это, похоже, будущее программирования, индустриального программирования. Технологии масштаба предприятий - все эти middleware и three-tier systems прекрасно ложатся на такую схему. Стандартизация и распределенность, вот что становится важным. Да и технологии распостранения и продажи софта - тоже. Например, вполне перспективным считается повременной лизинг компонент - это когда ты работаешь с апликухой, которая части свои динамически собирает со всего мира, а потом ты смотришь сколько тебе накапало :)

И Микромягкие это прекрасно понимают, всю эту историю, потому как натягивают свою изначально одномашинную OLE на сеть - получая довольно-таки кривую компонентную ахитектуру ActiveX. Java-объекты используют CORBA как стандарт общения, что на мой взгляд куда как совершенней с точки зрения и технологии, и открытости.

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

Все соревнуются - не только и не столько в том, кто сделает интерпретатор или компилятор с жабы получше, сколько в том, кто поизощреннее эту жабу применит. Скажем, наша фирма решила написать на жабе телефонный софт не в последнюю очередь из-за того, чтобы не оказаться в последних рядах - среди тех, кто еще ничего на жабе не написал. И, конечно, хвастаться можно заказчику - вот мы какие! На жабе написали! И он, которому по идее не должно быть дела, клюет и радуется. Вот странно - на Фортране написано было, на Сноболе 4 или на Симуле-67 - это всегда было всем пофиг. Лишь бы работало. А на жабе - всем интересно. Как будто оно лучше от того, что на жабе.

Нет, не лучше. Вообще, как по мне, так каждую задачу надо делать на том, что позволит ее решить
максимально эффективно и малозатратно. Может, у твоих шефов есть какие-то соображения,
кроме моды?

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

Тут я с ними согласен. Разработка на Джаве действительно быстрее. НО! Человек для этого должен понимать,
что он пишет не на плюсах, и не на С, и не тянуться к пистолету при слове "объект". И должен обладать навыками ОО дизайна, потому как Джава - очень эффективное средство и хорошая платформа,  но только если играть по ее правилам. Например, в Джавасофте все рванули писать многопоточные  программы, благо язык Джава это позволяет. А учиться-то кто этому будет? И дебаггеров многопоточных не было. Ну и наполучали кучу софта, в котором сполшные дедлоки, все виснет, работает медленно... С умом же делать нало! Спустя год, научились слава Богу. Или, RMI - хорошая штука, но сериализовавать все подряд в поток бездумно - ресурсов не хватит... и RMI тут не причем - дизайнить системы надо лучше.

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

Времени нет. Сан сотоварищи надеются создать критическую массу апликух для Джава-платформы, а то действительно от нее только язык останется. Джавасофт вынуждень рвать со страшной скоростью вперед, потому как не все спецификации Джава-окружения еще вообще имплементированы, куда там про эффективность думать. Ты видел сколько их там? Только не надо говорить, что твою свободу ограничивают этими спецификациями. Просто стараются сделать хорошие библиотеки, чтобы ты, когда писал приложение, не изобретал велосипед заново. Микрософту проще - он за 8-10 лет существования виндов свои библиотеки отшлифовал более или менее. А спецификации - открытые, хочешь - обсуждай  их, хочешь - имплементируй. По большому счету, свободы творчества не меньше чем у линуксоидов. Вот только мало кто писать умеет, особенно рантайм - хороший сборщик мусора - это технология, которая не один миллион долларов стоит... Энтузиазмом тут не пробъешься.

А в университетах Джаву же уже давно и прочно преподают, классика уже. Книжек по ней вышло в
три раза больше, чем по С и плюсам, вместе взятых...
 

Давайте зададим самый главный вопрос. Зачем жаба? Вообще, первый вопрос, который должен
задать себе разработчик нового языка - зачем этот язык. Что с помощью него можно сделать, чего
раньше было нельзя, и чего легко сделать, чего раньше было сложно. В случае жабы ответов три.
1) Для писания апплетов, которые ездят по сети и работают на машине клиента. Я полностью согласен,
что для этого необходим абсолютно надежный интерпретируемый язык. Возможно, жаба для этого и
годится, хотя она для этой цели слишком велика. Для нормальных целей достаточно какого-нибудь
скриптового языка (вроде того же жабаскрипта, имеющего к жабе отношения не больше, чем c-shell к С).

Джаву прикрутили к Интернету для возбуждения к ней интереса и демонстрации ее динамических свойств. Может, по другому и нельзя было, но многие скорее воспринимают динамическую подгрузку классов по HTTP как издевательство. И всем ведь не объяснишь, что задумывалось это все не для анимации веб-страничек....

Так вот, жаба нужна для апплетов. А для чего нужны апплеты? Где они, апплеты?
90% апплетов, которые я до сих пор видел - это были красивые счетчики. Или иной оживляж - всякие
мигалки, скроллящиеся строки и прочий маразм. Единственный раз, когда апплет был по делу - это во
время матча Deep Blue с Каспаровым. Я помню, в первом матче после каждого хода закачивалась
доска в виде GIF, а во втором - только ходы, а показывались они на клиенте с помощью апплета.
Все! Больше путевых апплетов я не видел. Да что там - самый лучшей и полезный в мире сайт (угадайте
какой) сделан с помощью чистого CGI. Так же устроены Amazon, сайты авиакомпаний, выдающие
рекомендации по составлению маршрутов, сайты новостей - словом, все, что применяется по делу.
Итак, апплеты - это большой мыльный пузырь, никому это не надо.

Во-первых, большинство апликух - это интранет-системы, которых ты не видишь и не увидишь никогда.
Много ты видел приложений на dBase? Писали их много, но под заказ или для себя, это не был коробочный софт. Он появится только после того, как разработчики накопят опыт и свои библиотеки. А компонентный софт пока только зарождается, и многие вещи - только в теории. Ну, представь себе, что ты пишешь компоненты, которые хочешь продать. Как ты это будешь делать сейчас?

2) Для писания переносимых программ. Мэнеджеры придумади термин - WORA, write once, run anywhere.
Я бы лучше назвал это WOABNR - write once and better never run. Так вот, налицо технология, созданная
для удобства програмимистов, а вернее, их мэнеджеров, а не пользователей. Представьте себе
автомобиль, который умеет ездить по рельсам и дороге, на бензине и ацетоне, с левым рулем, который
легко переставляется направо, но ездит только со скоростью до 5 км/ч. Купите вы такой? Так и с
программами. Пользователю до большой балды, на чем написана программа и работает ли она на
какой-либо еще платформе, кроме его собственной. Пользователю надо, чтобы программа хорошо
работала на одной-единственной платформе - на его. Хорошо работала - это понятие многогранное.
Оно включает в себя:
 - быстро работала на ней
 - имела бы внешний вид, принятый на этой платформе (например, Motif, Macintosh, Windows 95)
 - имела бы управляющие сигналы, принятые на данной платформе (например, на виндах - закрывалась
бы по Alt-F4 и показывала бы хелп по F1)
 - сопрягалась бы с другими программами на данной платформе (скажем, понимала бы clipboard и drag
& drop в виндах)
 - использовала бы на полную катушку возможности ОС в области многопоточности, многопроцессности,
межпроцессного взаимодействия, файлового обмена и т.д. и с помощью этого добивалась
максимальной эффективности и надежности. Например, не мещало бы, чтобы БД сбрасывала дисковый
кэш по закрытию транзакции - как этого добиться на жабе?
 - использовала бы и юзерские возможности ОС тоже. Например, в виндах чтобы писала свои настройки
в Registry, а не в странные файлы двоичного вида, получаемые при использовании жабовского
механизма Serializable.
Так вот, написание программы на жабе, по крайней мере в наше время, не отвечает поставленной
задаче. На жабе можно слепить глюкалу, но не серьезную программу.

Правильно. Но почитай спецификации, там ВСЕ это есть. И про нативный вид, и поведение, и про
транзакции. А раз есть в спецификациях, и раз этим не одна компания занимается, то это все
точно будет сделано, поверь. IBM, Sun и Oracle землю роют, и это свои плоды принесет.

Косвенное доказательство этому - ГДЕ ЭТИ ПРОГРАММЫ? Ну где эти продукты, написанные на жабе? Единственное, что мы имеем - это сановские инструменты из JDK. Скорость их работы позволяет подозревать, что они написаны на жабе. Также легко видно, что микрософтный компилятор написан не на жабе - работает со свистом.

На JavaOne в Сан-Франциско в этом году было много всего. Сходи на javasoft.com, там тебе список
выкатят. И посмотри, кто требуется для работ на East Coast в банковских и телко сферах - поищи по
ключевым словам Java и CORBA, все увидишь.

Corel предпринял попытку переписать свой офис на жабу. Я имел счастье лицезреть первую версию этого. WordPerfect и Quattro Pro, работающие в броузере! Со скоростью раз в пять меньше той, с которой аналогичные программы работали на Apple ][. Интересная была игрушка, но не более того. И известно, что Corel прикрыл эту работу, признав ее бесперспективнойю.

Я читал письмо на эту тему к сотрудникам Corel. Там было сказано: "Мы готовы к тому, чтобы переписать офис на Джаву, но Джава пока не готова к этому". Это была правда. В частности, Corel подтвердил, что они продолжат работу после выхода jdk 1.2 в котором будет встроенная поддержка true type и Postscript фонтов, что было важно. Да и производительность выросла на порядок с тех дней.

Еще одна причина - Corel делал это все для Javastation, а этот проект загнулся. Грубо говоря, Sun Microelectronics слабо оказалось сделать MicroJava. Они его и до сих пор не сделали, это неожиданно оказалось сделать сложно, как и Бабаяну с его влив-процессором. Это, кстати, был большой удар, правда.

Нечто подобное случилось в Микрософте. Микрософт с самого начала считал идею с апплетами неинтересной - вместо них они проталкивали свои ActiveX. Но они рассматривали вариант писания на жабе своих собственных программ - мол, хороший, красиыйя язычок, что ж не пописать? Я боюсь ошибиться, но, мне кажется, они очень скоро осознали, что идея бредовая, и пишут в основном, как и раньше - на С и С++. А Жабу только продают лохам, вроде нас, сами же не используют.

Они вроде свернули все свои работы в основном по политическим соображениям. А J++ кстати,
процветает вполне, хотя без подержки jdk1.1 это все смахивает на маразм.

Между прочим, количество переносимых программ, написанных на С, поражает воображение.

Ну и что? Речь идет о том, чтобы добиться не того, чтобы принес програмку, перекомпилил и
запустил, а о том, чтобы код без перекомпиляции работал на разных платформах.

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

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

Наконец, хотелось бы заметить, что Жаба - отнюдь не первый объектно-ориентированный язык. До нее было немало симпатичных объектно-ориентированных языков, которые, однако, такого шухера не вызвали - взять ту же Симулу 67. Из современных можно посмотреть на Оберон, Актор и Модулу-3. Мне особенно понравилась Модула-3 - объектно-ориентированный язык на базе синтаксиса Модулы, с сохранением концепции definition-implementation, не претворяющийся проще, чем он есть, но и без лишней придури. Был разработан без участия Вирта фирмой DEC лет десять назад, но распространения не получил - видимо, у людей из фирмы DEC есть совесть.

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

2.3. Личное околожабство.

Каждый язык вызывает кучу ощущений и ассоциаций у пишущего на нем. Он как будто имеет психо-моторные и органо-лептические свойства. Писание на одном языке может отличаться от писание на другом, как поедание мяса от рыбы, или питье молока от вина, или езда на разных видах велосипедов. Некоторые языки вызывают приятное ощущение, некоторые - неприятное. Некоторые языки по ощущениям близки, некоторые - далеки. Скажем, для меня Модула далека от С, но не настолько, как Жаба. А наиболее близкий к жабе язык (для меня) - это Visual Basic. Почему-то ощущения почти один к одному совпадают. А Visual Basic мне глубоко противен. В первую очередь своим высоченным уровнем, из-за которого простые вещи приходится моделировать с помощью сложных.

Мне VB тоже безумно противен, и, честно говоря я как раз считаю Джаву полной ему противоположностью. Так что не знаю, не знаю.
 

3. Прогноз.

Мой личный прогноз - максимум через пять лет Жаба тихо помрет, или вернее сойдет с переднего плана,
заняв подобающее ей место где-то возле Лого, Лиспа, Схемы, Снобола 4, Смолтока и Форта.

Если из нее сделают "только язык" - да, безусловно. Потому как суть идеи пропадет...
Почитай мою давнюю статью на тему того, как Микрософт успешно пытается это сделать:
http://www.sun.ru/win/news/events/1997/October/sue.html
 

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

4. Выводы.

1) Когда вокруг шухер - сохраняйте ясную голову
2) Не будьте тем, кто расшибает голову, когда молится
3) Применяйте игрушки для игры, а серьезные вещи - для работы. Например, не пытайтесь делать себе
серьезную аппаратуру из радиоконструктора.
4) Не торопитесь запрыгивать в поезд - убедитесь, не отцепленный ли это вагон.
 

Выводы универсальны, и, потому, справедливы :)

-Саша