Уровни магии в программировании
Уровни магии в Java таковы:
1. Обычный Java-код по Эккелю et al., в Thinking in Java etc.
2. Жонглирование тредами, динамические листенеры, nio, setAccessible(true).
3. Творческое применение средств java.util.concurrent, ручная работа с Queues, ручная синхронизация через CountDownLatch, continuations.
4. Противоестественные reflections для generics и прочие тонкие извращения вроде template methods (включая знания, где в Java есть type inference), generic constructors.
5. Нетривиальные compile-time annotations.
6. Действия по обходу type erasure, например, typesafe heterogeneous containers (THC) и прочие извращения.
7. Собственные класслоадеры.
8. Конструирование своей водки собственного байткода ASM-ом (cglib, BCEL etc.) и модификация байткода на лету.
9. Использование sun.misc.Unsafe, прямая модификация заголовков классов и других структур JVM.
10. Расковыривание javac, обходы верификатора, замена garbage collector и прочая хирургия кувалдой.
Лично я некоторые вещи "высоких уровней" использовал ограниченно (7 уровень в проекте, 9 - сам JfF ковырялся).
Интересно бы было прочитать мнения как джаваистов - кто что из этого использовал, так и, особенно, знатоков C++, С#, не знаю, Oracle (?) -- какие там могут быть классификации такого рода "магии"?
P.S. hardcase, Green, bioflash - два шага вперед ;)
Вот с ходу прикинул для .NET, но в одну линейку не втиснуть (далеко не полная классификация):
C# (2.0, наиболее общие техники):
1) Написание простого кода, бросание компонентов на форму, привязка к данным.
2) Использование генериков, написание простых обобщенных классов, сюда же анонимные делегаты.
3) Атрибуты (сюда же CLR атрибуты вроде ThreadStatic и MethodImpl), Использование отражения в разной форме - сбор метаинформации, вызов методов, обращенией к свойствам.
4) Уверенное многопоточное программирование, ParallelExtensions.
5) Отражение + генерирование кода через CodeDOM (загрузка сборок, домены приложения etc).
6) Отражение + генерирование CIL-кода через Emit (как следствие - создание собственного .NET компилятора).
Nemerle (или Boo):
1) То же что и в C# (пп. 1 - 3), понимание основных метаатрибутов (Accessor, Factory, etc).
2) ФП во всем его многообразии.
3) Метапрограммирование: понимание отражения времени компиляции, написание простых макросов, метаатрибуты, синтаксические макросы.
4) Понимание работы ncc, создание собственного embedded DSL.
C++\clr (и все что связано с нативным кодом):
1) PInvoke, маршаллинг управляемых типов, SafeHandle
2) Смешаные сборки
... // тут я не спец, Der Meister лучше знает.
Отдельно:
- ремотинг (с проксями и прочим всяким)
- написание CER-кода
- хостинг CLR
Реально использую/исползовал почти все вышеперечилсенное кроме: C++\clr, Emit, CER-кода, хостить CLR тоже не пробовал.
Я не сомневаюсь в величии перечисленных товарищей, но мне в первую очередь хотелось бы услышать мнение от Der Meister. Ибо перечисленные уровни вводят меня в тоску. Наверное из-за недостатка знаний или от плохого чувства юмора...
Знаешь, вот про что интересно поговорить тогда:
C# (2.0, наиболее общие техники):
5) Отражение + генерирование кода через CodeDOM (загрузка сборок, домены приложения etc).
http://www.firststeps.ru/dotnet/r.php?118 - взглянул на пример - выглядит интересно, закопаюсь в этом... Заголовок кстати, напомнил классы в Java, которые создаются по XML Schemas через JAXB.
Хотя JAXB - это не то. Посмотрю, какие есть (а какие нибудь да есть, я уверен) аналоги для Java.
6) Отражение + генерирование CIL-кода через Emit (как следствие - создание собственного .NET компилятора).
Вот это по сути, генерация MSIL - это то что соответствует моему (моему -в контексте этого топика) пункту 8. Конструирование собственного байткода ASM-ом (cglib, BCEL etc.) и модификация байткода на лету?
А аналоги для 9-10 уровней какие нибудь есть? Доступ к базовым механизмам среде CLR, внутренние структуры, которые там используются?
Кстати, написано наверняка на Asm/С/С++ оно все.
Ниже пишешь про PInvoke и прочее, но это не доступ к внутренностям CLR все же.
И, про взаимодействие с GC в виде его замены, есть что-то такое?
Nemerle (или Boo):
1) То же что и в C# (пп. 1 - 3), понимание основных метаатрибутов (Accessor, Factory, etc).
2) ФП во всем его многообразии.
А вот тут несколько шокирован. В моем понимании, понимание ФП во ВСЕМ многообразии -- это гораздо более тонкие материи? :)
3) Метапрограммирование: понимание отражения времени компиляции, написание простых макросов, метаатрибуты, синтаксические макросы.
Отражение времени компиляции - это некоторый аналог Java Agent + собственный процессор аннотаций?
Сорри, знания дотнета не хватает...:(
О, да, прошу прощения у всех -- я просто назвал из тех, кто был на слуху некоторое время назад, когда я более активно тут появлялся:(.
Конечно, мнение Der Meister, как и всех кому интересны такие классификации и есть что сказать - хочется услышать.
Знаешь, вот про что интересно поговорить тогда:
http://www.firststeps.ru/dotnet/r.php?118 - взглянул на пример - выглядит интересно, закопаюсь в этом...
CodeDOM позволяет собирать AST (синтаксическое дерево) и потом из него генерировать код на языке высокого уровня: C#, VB.NET, Boo, Nemerle. Далее этот текст в виде файлов отдается целевому компилятору. Можно относительно быстро создать кодогенератор. В целом не слишком удобно, когда логика становится достаточно запутанной.
Emit позволяет создавать динамические сборки (сразу в памяти). По поводу самомодификации кода.... хмм не знаю, но чем черт не шутит...
Мне кажется, эти пункты имеет смысл рассматривать со стороны хостинга рантайма. Уж с этой стороны нехилый такой API, я правда не зарывался в это дело. Во всяком случае MS SqlServer 2005/2008 умеет CLR хостить, и использование внутри него памяти пожестче чем в обычной софтине - так что GC заменить можно (в дотнете их сейчас 2 штуки на выбор).
А вот тут несколько шокирован. В моем понимании, понимание ФП во ВСЕМ многообразии -- это гораздо более тонкие материи? :)
Не знал куда запихнуть, но дотнет без ФП как-то невкусно рассматривать. F#, Boo, Nemerle уже достаточно взрослые языки, их их нельзя не брать в рассмотрение.
Отражение времени компиляции - это некоторый аналог Java Agent + собственный процессор аннотаций?
Сорри, знания дотнета не хватает...:(
Это API компилятора (в частности Nemerle, в Boo тоже есть), метапрограммирование в чистом виде. В Nemerle язык уже сам заточен на метапрограммирование, тогда как в Boo это исключительно API.
Это то, что позволяет положить болт на отражение рантайма, CodeDOM и динамические сборки - код разворачиваем на этапе компиляции. Похожий подход сейчас используется в Sing# (компилятор Singularity).
Наоборот - радуйся, что на наш век еще столько интересных вкусностей))
Дело в другом. Возможно, я заблуждаюсь и вижу в этом списке не то, что в нем есть. Но мне видется, что все пункты, кроме первого - это опасное хакерство, которое нужно очень небольшой группе людей, типа разработчиков компиляторов, архиваторов и тому подобного софта. Однако, не совсем ясно, при чем тут Java. Нужна скорость - вызвал через JNI (или как оно зовется) платформо-зависимый метод, выполненный в C/C++ и радуйся. Естественно, вначале надо провести исследование с помощью профайлера и т.п.
Вот такие мои дилетантские размышления.
Ващето в том списке хакерство начинается с 6 пункта, когда "ломают" систему типов (хотя меня напарник уже считает очень тонким извращенцем, когда попадает оладчиком в абстрактные генерики с 3 параметрами-типами... нууу оно в рантайме связалось там как-то).
Но в целом, да, подобные тонкости нужны достаточно ограниченной группе людей, хотя знания подобного уровня могут сильно помочь при поиске нетривиальных багов.
Кстати, для достижения повышенной производительности переписывать код на C/C++ совсем уж крайний метод - лучше сперва из управляемого кода выжать все возможное.
Хотя приходилось несколько раз кроме первой тройки также вникать в детали вещей 5 и 7 уровней. Так как не все системы оправдывают себя в качестве и надежности.
ИМХО: Я бы немного 1 пункт подправил - Обычный Java-код по Эккелю et al., в Thinking in Java etc. + рекомендации от Блоха, в Effective Java 2ed.
Если не крут, то спровоцируй тех, кто крут - начни писать свой список :)
Например, для C++ я бы написал 2 списка или 3. Эти списки бы показали пути развития в программировании.
Первый, по аналогии с приведенным (в случайном порядке):
2. Отказ от статического создания объектов, переменных, массивов. Все создается динамически, с использованием указателей.
3. Использование хитрых указателей на функции (для гибкости).
4. Для повышения быстродействия применяем могучие макросы.
5. Отказ от STL. Вместо контейнеров и строк std::string используем только динамически созданные массивы.
6. Для экономии памяти везде, где возможно и где невозможно используем union.
7. Опять же для выигрыша в скорости и экономии памяти переходим к ассемблерным вставкам.
8. Отказ от new, delete. Используем только самодельные функции динамического распределения памяти. Естественно, эти функции написаны на ассемблере.
и т.д.
Например, для C++ я бы написал 2 списка или 3. Эти списки бы показали пути развития в программировании.
Первый, по аналогии с приведенным (в случайном порядке):
2. Отказ от статического создания объектов, переменных, массивов. Все создается динамически, с использованием указателей.
3. Использование хитрых указателей на функции (для гибкости).
4. Для повышения быстродействия применяем могучие макросы.
5. Отказ от STL. Вместо контейнеров и строк std::string используем только динамически созданные массивы.
6. Для экономии памяти везде, где возможно и где невозможно используем union.
7. Опять же для выигрыша в скорости и экономии памяти переходим к ассемблерным вставкам.
8. Отказ от new, delete. Используем только самодельные функции динамического распределения памяти. Естественно, эти функции написаны на ассемблере.
и т.д.
эдак до перфокарт можно опуститься...
мне так кажется, что программирование развивается в несколько противоположном направлении.
мне так кажется, что программирование развивается в несколько противоположном направлении.
Прочитайте тему сначала, а не только последнее сообщение :)
Насколько я понял, суть темы "частный хак", а не
в делфях два уровня:
1. Используешь делфи
2. Не используешь
:)
Ну, я говорил о пути развития отдельного программиста. В общем, я хотел создать список - аналог того, что увидел в первом сообщении.
Применительно к C++ гдето на последних уровнях должен фигурировать Александреску. Ну это как аналог метапрограммирования.
2 путь: использование хитрых шаблонов (template), безупречное знание STL (включая понимание того, как использовать алгоритмы, функторы и т.п.), использование Boost, и т.д.
3 путь: использование шаблонов проектирования GRASP и GoF, использование Unit-тестирования, рефакторинга и т.д. Хотя, третий путь к C++ прямо не относится. Возможно, для этого пути C++ даже вреден.
Можно пытаться одновременно идти по трём путям. Или по двум.
Как правильно сказал кто-то, смысл - частный и честный хак.
Некоторое сочетание нетривиального знания языка, платформы, сторонних средств, приемов программирования, внутреннего устройства среды исполнения, и несколько ненормального, в хорошем смысле слова решения - ДЛЯ получения интересных, поразительных для увлеченных людей и знатоков, завораживающих - но, часто сложных, малополезных в обыденности решений, опасных хаков.
Вот, ссылочка только для примера. Про высшую магию.
http://www.wasm.ru/article.php?article=unsjav1
http://www.wasm.ru/article.php?article=unsafe_ii
Перечитайте список от меня в первом посте, и список hardcase.
Еще правда не откликнулись некоторые другие люди к которым я обращался ;)
Как правильно сказал кто-то, смысл - частный и честный хак.
Некоторое сочетание нетривиального знания языка, платформы, сторонних средств, приемов программирования, внутреннего устройства среды исполнения, и несколько ненормального, в хорошем смысле слова решения ...
В общем, вроде понятно. Извините тогда за оффтоп.
Тогда для чистого C++ трудно придумать аналогию - тут наверно надо смотреть в сторону всяких фреймворков (или как оно завется, я говорю про библиотеки типа MFC, WTL, QT и т.п.), всяких классовых оберток для "классов" Win32 API и т.д.
1. Используешь делфи
2. Не используешь
:)
а фиг там... доже дофига своих прибамбасов (может и меньше чем в др. яп, но по любому есть)
1. Используешь делфи
2. Не используешь
:)
глупо
Наверно, опять все сводится к изощренному использованию Win32 API и ассемблерных вставок.
Ну и установка KOL для Лазаруса и дальнейшее программирование в этом тоже только магам по силам....
Да ну, прикольная шутка! :) Там ж смайлик не просто так.
В дельфине тоже много всякой "бадяги": класс-функции, динамические классы, длинные строки и дин. массивы, интерфейсы, стартовые процедуры модулей, лоадеры компонентов, вариантные типы, динамические и виртуальные методы, фастколл конвенция (я не про использование а про реализацию в основном - чтобы самому забацать), ну а VCL вообще отдельной статьей пойдет :) - один TObject и TDataSet несут в себе много интересного.
И все же как в случае с нативным кодом, мне кажется нельзя относить asm/MSIL/bytecode непосредственно к уровню языка, это уже другое, слишком низкое, подмножество. Хотя граница весьма расплывчата порой.
Кстати несколько тонкостей языка я подловил когда начал писать парсер Delphi-кода а потом тестировать на всем что под руку попадалось. То же самое было и с C (хотя тут есть хоть какой-то стандарт которого я правда не читал).
У меня такая "магия" когда класс в библиотеке нужно сделать доступным и в C и в C++ и в Delphi. Вот и начинаются пляски с бубном, куча экспортируемых функций с похожими именами и G/Set-ами, собственные хендлы - то номера, то указатели... :D
- Ленивые вычисления и отложенные загрузки на основе замыканий. Система делает вид, что работает быстрее. От пятисот человек.
- Генерация кода для промежуточных, связующих слоёв системы на основе метаданных XML, загрузка "на лету". Система делает то, чего она делать не может, причём правильно. Как она работает на самом деле, до конца никто не знает. От двух тысяч человек.
- Выброс кода в виде аспектов поведения. Все дублирования, устранить которые ума не хватило, но очень хотелось, теперь гордо называются сквозной функциональностью и локализуются в атрибутах, разворачиваясь где-то на этапе компиляции. От десяти тысяч человек.
- Принятие конституции супертипов и сепаратных интерфейсов, или введение аспектов сущностей. Система напоминает мексикансий сериал: все сущности в системе состоят в родственной связи, страдают амнезией и владеют страшной тайной, но зритель узнаёт обо всём этом лишь в самый последний момент. IDE подчёркивает красным факты создания абстрактных классов и абсурдные приведения типов. Тем не менее, всё работает. От ста тысяч человек.
- Метапрограммирование. Теперь система напоминает русскую народную сказку, в которой лежащий на печи тридцать лет Иван-дурак отхватывает полцарства, умную бабу и беспроцентную ипотеку. Языковые конструкци, переменные, типы данных и беспрецедентная функциональность появляются из ниоткуда по велению волшебной щуки. Вне контекста системы объяснить, как такое возможно, не реально. Теоретически, один хороший типобезопасный макрос способен спасти от миллиона человек, разрушив, при этом, левое и часть правого полушария мозга большинства разработчиков системы.
Описал то, что видел, но не ко всему из этого прибегал сам. Отметил аспекты, поскольку .NET позволяет разработчику реализовать такие вещи без систем АОП как таковых.
Аналоги 8-10 уровней, описанных в начале топика, в безопасном коде нереализуемы, но ансейф позволяет делать что-то подобное (и многое другое). Например, можно ознакомится со внутренним устройством управляемых объектов в статье мага VlaD2 и, немало подумав, решить задачу о sizeof управляемых классов. Прецедентов замены GC не имею, но думаю, что и это возможно; зато в C++ заколдованная память используется часто, и вот, скажем, пример снесения башки стандартному механизму (а уж о прикручиваниях самопальных GC и говорить, думаю, не стоит).
P.S. Простите за сумбур: у меня Христос воскресает до сих пор... :)
Я только не очень понял число человек под каждым пунктом - это необходимое количество жертв данного метода? :)
- Генерация кода для промежуточных, связующих слоёв системы на основе метаданных XML, загрузка "на лету". Система делает то, чего она делать не может, причём правильно. Как она работает на самом деле, до конца никто не знает. От двух тысяч человек.
Вот тут кстати несколько несогласен - у нас в системе на этапе компиляции несколько тысяч классов генерятся по XML-схемам через JAXB.
И, натурально, работает правильно :)
конечно глупо. Ведь вы в состоянии представить ряд задач, которые легко решается на делфи, а на прочих языках ни как. Но правда я сомневаюсь. Может разочаруете? Это вопрос ко всем деби.. прошу прощения к тем кто свято уверен что делфи - это язык програмирования
Вспомнил прикол. На одном форуме я возмутился, когда кто-то начал обращаться к участникам по именам. На следующий день все постоянные участники ввели в подпись свои имена...
По теме: я же говорил, что надо подождать Der Meister. Пришел, доступно объяснил на рабоче-крестьянском про магию - все стало понятно ))
И ко мне? Я вот тоже уверен, что Делфи - это язык программирования :) Есть и по-лучше, конечно, и по-современней, но именно этот язык, в основном, определил мой образ мышления.
Костя, ты не прав. зачем разводить хуливар с хамством, да еще основываясь на собственных предположениях об умственных способностях оппонента? не пообщавшись и толком не узнав его мнение.
и чем тебя делфи не устраивает?
Он еще не знает что на нем написан злобный зверь буилдеръ :D