<<<предыдущий список следующий>>>

Это - копия документа, находившегося на http://dz.ru. Авторские права, если не указано иначе, принадлежат Дмитрию Завалишину и/или Евгении Завалишиной. Все изменения, внесенные мной, находятся в этой рамочке.Пожалуйста, прочитайте disclaimer.


18 Марта 1999

День писем. :-)

Первое - про MIDI - в защиту Квикшота.

   
From: Alex Young
Subject: MIDI-keyboard

Не могу не добавить пару слов по поводу MIDI-клавиатур.

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

Теперь о Quickshot. Именно его я купил в конечном счете, разочаровавшись в крутизне, купил в качестве самой дешевой активной четырехоктавки на тот день. Дизайн, конечно у него слабоват, сильно напоминает этакие "компьютерные" аляповатые и дешевые светло серые пластмассовые мышки, колонки, микрофончики и прочие плюшки-джойстики. Но самое интересное началось потом - я обнаружил, что работает-то он практически так же (про отличия от рояля говорить не стану, самый лучший имитатор рояля - пианино, деревянное с чугунной рамой.) Непривычный уровень чувствительности дал о себе знать сразу, динамика игры была поначалу весьма посредственной, но выяснилось, что это, во-первых, дело привычки, а во-вторых легко и плавно регулируется малозаметным ползунком "data entry" после волшебной комбинации select-velocity-select. У клавиатуры Evolution тоже есть регулировка реакции на нажатие, но оно не было описано в документации, и ко всему еще ничем не индицируется - все вслепую... Ползунок этот, который все принимают за регулятор громкости (по default, он им и является), оказался третьим "колесиком" после pitch и modulation. Им можно с весьма хорошей разрешающей способностью регулировать практически все, относящееся к MIDI. Громкость, баланс, реверберацию, хорус, посленажатие, и многое другое, например квакать гитарной приставкой на моей YAMAHA SW60. Что только не придумают авторы дешевой "некрутой" клавиатуры, дабы понравиться пользователям!

Единственным серьезным из замеченых недостатков QuickShot я назову не очень плавную работу колеса Pitch вблизи среднего значения, что заставляет довольно долго тренироваться работе с ним. Ну вот, пожалуй и все.

/Alex

 

Спасибо. Я со своей стороны отмечу еще раз, что в нынешний момент на рынке есть еще и Evolution 149 по цене того же квикшота и пятиокатвный Evolution 161, которые, вероятно, стоит рассматривать как сильных конкурентов Квикшоту. А что до "ползунка" на последнем - да, мы до него при тестировании тоже добрались, но не впечатлились. Возможно, это вопрос тренировки и за короткое время его не оценить. С другой стороны, фактически, это письмо лишний раз подтверждает наш вывод - для миди-ввода QuickShot пригоден, для обучения игре - нет.

 

Интересное письмо про рейв я тоже получил. Увы, анонимное. :-( Но все равно публикую.

    ...

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

Не буду заниматься критикой данного "первого антирейверского" веб сайта, так как информация, представленная авторами, не выдерживает никакой критики. Выражения "рейв и прочая кислота" просто умиляют. Ну почему бы тогда не начать наезды на рок музыку с фразами типа "Doors и прочая кислота"? Для непосвященных рекомендую посмотреть фильм "Doors" by Oliver Stone. Мы не будем говорить уже о том, что называть наркотиком, а что нет, так как ни один человек, пробовавший психоделики, не назовет их наркотиками. Ну да не об этом мы. А о чем? Да вот не смог пройти мимо твоей, Дмитрий, личной заинтересованности этим вопросом (рейвом), и решил высказать несколько мыслей.

1) Rave'ом называют у нас стили: hardcore, jungle, breakbeat, drum'n'bass, techno, trance, house. Это очень основные направления. Существует еще множество сабстилей и других стилей, которые не являются столь популярными как вышеперечисленные.

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

Вот некоторое очень обобщенное описание этих направлений. hardcore - bpm (beat per minute) >160 Т.е. музыки нет, есть только bpm :-) Очень простой стиль, популярен среди 13-15 летних, потому что можно всю пати прыгать :-)

от jungle и breakbeat до drum'n'bass меняется bpm (точное значение не помню, по этому не буду приводить во избежание комплейнов от поклонников данных стилей) и меняется насыщенность музыки. Появляется многослойность. Бит все также определяющий элемент, но по мимо него появляется очень много других компонентов. Аудитория от такой же как у хардкора(в Москве популярны вечеринки Jungle vs. Hardcore), до 17-20 и выше. Именно эту музыку представляют многие как рейв, а про другие стили считают, что это из той же серии.

Techno, trance и house. Более взрослая музыка, есть очень простые композиции, есть очень сложные... Каждый выбирает, что-то свое.

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

Транс и его наиболее популярная разновидность - psychedelic trance, включающий в себя goa trance - это очень сложная и интересная музыка. Она не поддается твоему расхожему описанию "включил компьютер, программку запустил, трек готов". Это реальная музыка, но созданная при помощи нестандартных инструментов. Многие транс музыканты в прошлом работали в других стилях, что отражается в их творчестве и приносит новые идеи. Существует много альтернативных "нетрансовых" проектов, созданных этими музыкантами. Например, владелец одного из ведущих трансовых леблов Dragonfly - Youth, бывший гитарист группы "Killing Joke" участвовал в проекте с Полом Маккартни - проект Fireman. У одной из известнейших транс команд Juno Reactor выходит новый альбом, в записи которого принимал участие Steve Stephens, гитарист Billy Idol'а играющий flamenco. Просто хочется данными примерами убедить, что транс - это прежде всего МУЗЫКА, которая может кому-то не нравиться, кто-то может ее не понимать, но это сложная, интересная музыка для your mind.

Чтоже касается популярности, то эта музыка объединяет летом тысячи людей на open air фестивалях, куда съезжаются psychedelic people со всего мира. Один из таких фестивалей пройдет в этом году в Венгрии в августе во время солнечного затмения и будет продолжаться неделю! Кстати, это неплохой шанс для отечественных поклонников данной музыки по бывать на подобном событии, т.к. для поездки в Венгрию даже виза не нужна.

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

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

Получилось сумбурно, но надеюсь, что ты, Дмитрий, изменишь свой взгляд на электронную музыку в целом. Она ОЧЕНЬ разная. На сайте http://www.aerodance.net есть несколько интервью с разными транс музыкантами, если интересно, то рекомендую прочитать интервью с Олли Ольсеном из Австралии. На него есть ссылка с новостной страницы (Центральный компьютер -> Новости).

Кстати, по поводу старых пластинок :-) Большинство транс диджеев играют с ДАТ(или сейчас еще на минидисках), так как они играют нереализованную музыку (которая еще не успела выйти на лейблах и на виниле просто не доступна), так что свежее некуда :--) И в России есть такие диджеи.

 

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

Это - пара слов о моём лично отношении к предмету. Электронной музыкой я называю то, что ИГРАЕТСЯ на электронных инструментах. Рейвом (я, увы, тоже обобщаю) я называю то, у чего барабанная партия состоит из нескольких драм-лупов, а роль "музыканта" сводится к указанию номера такта, с которого пойдет не тыц-дыц, а трррррр.

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

Что я всем этим хочу сказать.

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

Ну и придирка под конец. :-) Когда говорят "эта музыка хороша", дают ссылку не на интервью, а на mp3, не так ли. :-)

 

Последнее письмо - про Яву. Я не стану "одевать" его в стандартную табличку, так как оно очень большое. Автор его, Maxim Kizub, одновременно является и автором более сложного и полезного произведения - языка "киев", о котором я уже как-то упоминал в онлайне. Язык этот - развитие Явы, и развитие сильное. Соответственно, и реакция Максима на флейм о Яве заслуживает пристального внимания. Он знает Яву с двух сторон.

Итак, далее от имени Максима.


Посмотрел на обмен любезностями по поводу явы... Вот, не удержался, чтоб самому не ответить. Вообще, все эти holy wars вокруг языков вещь достаточно гнилая в своей основе. И главное, что я бы хотел сказать в своем письме - это сделать ударение на разнице между JVM (Java Virtual Machine) и явой как языком. мне кажется, именно тут и лежит основное недоразумение в разговорах с противниками или приверженцами явы.

Основным достоинством JVM является

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

Кроме того, в зависомости от точки зрения разработчика, полезными или вредными можно считать

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

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

Достоинствами (или недостатками) Java как языка можно считать

а) привычный синтаксис
б) разумные семантические ограничения, особенно те, которые каждый приличный современный компилятор с С/С++ должен выдавать как warning
в) объектно-ориентированный подход
г) упрощение семантики языка, по сравнению с его "предшественниками"

Я убежден, что каждый из этих пунктов является как достоинтсвом, так и недостатком одновременно. В любом случае, их обсуждение выходит за рамки темы моего письма, поскольку тема C vs Pascal уже обсосана поколениями программистов, а тема Java vs Modula ничего нового сюда не привнесет ;-)

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

На правах рекламы ;-) Кстати, желающие иметь паскале-подобный синтаксис... Ну очень желающие... Если Ваше желание лежит чуть дальше, чем флейм ради флейма, и Вам этот синтаксис действительно необходим... Вам поможет фирма Forestro и, скажем, $10.000 для этой фирмы на карманные расходы ;-) Я думаю, работа займет всего месяц-другой ;-)

А теперь, я бы хотел хотел поучаствовать во флейме про Яву, но с конструктивной точки зрения. Конструктивность будет двух типов

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

Источник - http://members.xoom.com/vmpage/zhaba/java-a.htm

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

Чистый флейм, совершенно бездоказательный и абсурдный. Я привел его лишь в качестве классического примера holy wars аргументов. Тягостное впечатление :-(

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

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

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

а) вложенные классы вещь достаточно простая, но несколько сложных (и неофишируемых) моментов есть. На практике встречаются редко (но метко :-) ).

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

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

Добавление closures в яву как язык просто невозможно, в силу того, что JVM этого авангарда не поддерживает. И фирма Sun этой поддержки не сделает - это потребует действительно больших изменений не только в самой виртуальной машине, но и в байткоде и структуре бинарных файлов и пр. Реализованные в полной мере closures способны просто сокрушить достаточно хрупкий механизм верификации и исполнения untrusted кода... И тем не менее, лично я бы пошел на внесение closures в JVM. Но разработчики явы выбрали более легкий путь, и внесли в яву анонимные классы. Они те потребовали модификации JVM и, в целом, они обладают большей мощностью, по сравнению с closures. Но их применение чревато большими накладными расходами, а синтаксис крайне неудобен для большинства случаев.

Как альтернативный вариант - возмите pizza или kiev расширения явы и не имейте проблем с этим ограничением. В своих проектах. Потому как новая графическая среда для явы - Swing - сделана именно на основе применения анонимных классов :-(

Кстати, я, в виде эксперимента, сделал встроенную поддержку для closures и first-order functions в JVM на основе GNU-licensed JVM - kaffe. Скорость создания и вызова для них выросла в десятки раз. Плюс - возможная экономия памяти, в случае сложных приложений определяющих десятки анонимных классов.

2) Даже лексика Жабы неочевидна - правила о том, что раньше раскрывается, \n или \u, кого угодно сведут с ума. Скажите-ка, что выведется таким вот операторомж

System.out.println ("a\u005Cnb");

Ну, не стоит из-за частной проблемы огульно обвинять всю лексику вообще. Да, уникодные escape-последовательности имеют проблемы. Я их насчитал, как-то, штук пять. Долгое время, может даже и сейчас, в исходных текстах JDK гуляла ошибка, что-то типа case '\u000A': - перевод строки внутри строковой или char константы.

Самое смешное, что все эти проблемы можно было-бы решить одним небольшим изменением JLS (Java Language Specification)... Однако не изменили... Эта ошибка - как неуловимый Джо (все помнят почему он неуловимый?) :-)

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

Ну, это дело поправимое. Смотри рекламную вставку в начале документа ;-)

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

Возьмите kiev compiler.

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

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

Возьмите kiev compiler.

Впрочем, надо сделать одно уточнение. При употреблении goto иногда очень сложно, если не невозможно, провести полную проверку на инициализированность переменных перед их применением, плюс сложности со стеком при выходе из try/catch/finally. Я рекомендую код, использующий goto, обязательно проверять ява верификатором - во избежание, так сказать.

Единственным безопасным (и очень широко применяемым) вариантом в kiev являются goto case ... и goto default внутри switch. Вообще говоря - они просто неоценимы в случае написания конечных автоматов, каковым, в частности, является код генерируемый для prolog rules в kiev.

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

А мне так нравится. Единственное, что мне захотелось добавить - это импорт статических полей и методов класса. Это позовляет иметь "глобальные" (с точки зреня синтаксиса) переменные и методы.

7) Вообще, система с пакетами через точку явно непродумана. Например, отсутствует относительная адресация. Нельзя написать

import com.dvsoft.cts.*;

и потом употребить event.CallEvent - только полная квалификация! И если наш класс сам принадлежит к пакету com.dvsoft.cts - к подпакету доступ тоже только с полным путем!

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

Возьмите kiev compiler. Там еще и typedef есть - очень помогает в подобных случаях. ;-)

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

Это проблемы проектирования программы, а не языка. Ну не умеет ява за вас еще и проектировать!

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

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

Возьмите kiev или pizza.

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

Как видите - проблема есть, и решать ее надо... Вот три варианта решения, все имеют преимущества и недостатки. Выбирайте ;-)

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

Это не проблема языка. Это проблема тестирования.

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

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

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

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

Однако, если вспомнить зачем это сделали... Взгляните на #include в С++ программах - и вам сразу полегчает ;-)

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

Вот этого я не понял. А что, ява запрещает так писать?

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

Возьмите kiev compiler. А вообще - причины этого достаточно понятны - это приблизительно то же самое, что и требование boolean выражения в if/while операторах - во избежание.

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

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

Не стоит смешивать в одну кучу макросы и параметризацию типов.

Насчет макросов... Ну есть расширения явы имеющие препроцессоры. Рано или поздно - макросы в kiev появятся...

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

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

Возьмите kiev compiler. Там это есть.

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

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

Это плата за динамическую загрузку и байт-код совместимость. Безусловно, тут есть что улучшать. Но это потребует серьезных изменений в структуре байткода. И именно поэтому на реализацию Sun-ом расчитывать не приходится. В общем, рано или поздно я засяду за работу над Sun's JVM - добавить параметризацию типов, closures и много чего еще - в частности и этого.

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

Возьмите kiev. Там это есть.

Одно замечание... Дело в том, что enum очень плохо стыкуется с объектно-ориентированным подходом, в частность - с наследованием. Возможно - это одна из причин отсутствия enum в Java.

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

Возьмите kiev compiler. Еще не хватало такой маразм тащить из javac.

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

Есть проблема - но я не вижу конструктивного решения в Вашей тираде ;-)

На счет разделения .class и .java - используйте ключ -d у javac

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

Пути решения проблемы с нахождением классов в исходных текстах я уже описывал. Но это для компилятора. А для человека - Вы какое решение имеете предложить? Впрочем, я не совсем въежжаю - вы критикуете множество классов в файле, или необходимость иметь по файлу на класс? ;-)

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

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

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

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

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

Единственная проблема - я не знаю как это можно реализовать достаточно просто и эффективно, и не потерять возможности исполнять untrusted программы.

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

Зачастую вопрос даже не стоит - кто что предпочитает. Очень часто отлов memory leaks становится просто кошмаром, и для подавляющего большинства больших С++ программ он (IMHO) вообще не решен.

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

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

Ну зачем это все? Неужели специально все сделано, чтобы эффективность поменьше была?

Ну зачем же так. Не из вредности же они это сделали.

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

А жаль.

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

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

Совершенно согласен.

Впрочем, в виде оправдания можно привести наличие javadoc.

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

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

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

В языке используется только java.lang package. По моему, это не очень запутывает. Впрочем, подход K&R в языке С мне тоже больше нравится. Хотя, он тоже предполагает наличие run-time поддержки. Хотя-бы для определения main функции и некоторых других, типа exit/abort.

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

дд.мм.гггг чч:мм:чч.МММ (МММ - миллисекунды).

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

Стандартная библиотека действительно оставляет желать лучшего.

Что-то в ней сделано хорошо, что-то удовлетворительно, что-то - откровенно халявно.

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

Кроме того, в этом желании захапать и застандартизировать пообольше - Sun распыляется и теряет возможность довести до ума java core library. А также - довести до ума и Java как язык - например, параметризация типов и assert+work-by-contract уже пару лет как находятся в top 25 bug/wish list of JDC.

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

Это не в Java - это опять в Sun. У меня по этому поводу просто нет слов. Выражения есть, а слов нет :-(

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

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

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

Да, иногда это раздражает.

Из полезных советов - когда вас достанет необходимость описывать какой-то exception - сделайте его наследником java.lang.RuntimeException. И не забудьте поймать ;-)

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

Иногда, эффективности ради, люди и используют StringBuffer напрямую.

Кроме того, использование + для конкатенации строк сильно упрощает вывод в Java.

Кроме того - а что плохого в перегрузке операторов? Конечно - в полноценной - с возможностью определить новый оператор, определить его приоритет, количество операндов и пр.?

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

Дело вкуса.

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

Это старое как мир обвинение.

Типа - нож это плохо, им можно зарезать. Мой брат занимался подводным плаванием. У него был нож. Этот нож был для спасения жизни людей. А однажды нож отобрали в аэропорту и чуть не повесили на него уголовное дело.

Все понятно?

На сем я и закончу про жабу. Достаточно этого или надо еще?

Хватит. ;-)

Все это не аргументы против или в защиту явы. Я мог бы предоставить на порядок больше претензий, и к JVM и к Java как языку и к библиотекам. И все равно она мне нравиться. Наверное, в консерватории надо что-то поправить... :-)

(C) Maxim Kizub, 1999


Вот такое вот письмо.

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

Я бы, прочтя пункт, где автор обижается, что его заставили ввести класс "лексема" ответил на все 33 наезда одной фразой: "Мужик, тебе противно само ОО, тебе не надо писать на Яве. На яве надо писать тем, кто не представляет себе, как это - лексема есть, а класса такого нету". Это - единственное, что в консерватории не так.

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

dz, тогда же.