OberonCore https://forum.oberoncore.ru/ |
|
Инициализация: преимущества нормальных модулей https://forum.oberoncore.ru/viewtopic.php?f=29&t=1243 |
Страница 1 из 4 |
Автор: | Comdiv [ Пятница, 07 Ноябрь, 2008 12:04 ] |
Заголовок сообщения: | Инициализация: преимущества нормальных модулей |
ОТ МОДЕРАТОРА Выделена тема по просьбе: Info21 писал(а): Коллеги, очень интересно про инициализацию. Может быть, выделить в отдельную темку про "Чем хороши настоящие модули"? И вставить там в начале ссылочку на текст Сергея Юрьевича. Ссылка на статью С.Ю. Губанова "Секреты модульных систем": http://oberoncore.ru/index.php?option=c ... &Itemid=23 ================================================ Хочу вернуться к первоначальному вопросу об инициализации переменных по месту объявления. В Обероне инициализация переменных сделана близко к тому, что в итоге будет скомпилировано. Какая в этом польза для писателя компилятора - очевидно. Но есть ли от этого выгода для программиста? Ведь как неудобно - инициализировать не по месту объявления, а в отдельной секции в конце модуля. На мой взгляд, выгода есть. Расскажу на примере. Недавно у меня возникла проблема с портированием приложения для мобильного телефона, написанного на Яве, на несколько непривычных аппаратов: после выхода из приложения, оно уже не хотело выполняться второй раз. Оказалось, что проблема заключалась в неправильной инициализации статических переменных класса. На большинстве телефонов при завершении мидлета (аналога апплета для мобильного) все классы выгружаются, и при повторной загрузке все статические переменные инициализируются заново. Поэтому в абсолютном большинстве мидлетов допущена одна и та же ошибка: те переменные, которые должны инициализироваться при загрузке приложения, инициализируется при загрузке классов. Поскольку для большинства телефонов это всегда происходит одновременно, то проблемы не возникает, но на устройствах, выпавших мне, классы не выгружаются, и в результате у меня проблема на 40 классов с кучей неправильных значений в переменных. В Яве - это проблема, поскольку объявления статических переменных (переменных модуля) перемешаны с объявлениями нестатических (переменных объекта) и телами функций. К тому же в портируемом приложении инициализация напичкана перекрёстными ссылками, а потому зависит от порядка загрузки классов, но проследить этот порядок проблематично. Представим, что это глючное приложение было бы написано на Обероне. Моя задача была бы очень простой: достаточно было бы перенести компактные секции инициализации в процедуры, проследить порядок загрузки модулей, выведя при загрузке имена модулей в лог, и при запуске мидлета выполнить в этом порядке процедуры. Хочу отметить, что допустить такую ошибку в Обероне было бы сложней, из-за более чёткого разнесения понятий по сравнению с Явой, где инициализация переменных размазана по всему классу и всё свалено в кучу: и класс, и модуль. То есть одним лишь правильным выбором языка, как минимум на одну головную боль становится меньше. |
Автор: | Сергей Губанов [ Пятница, 07 Ноябрь, 2008 13:37 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Comdiv писал(а): К тому же в портируемом приложении инициализация напичкана перекрёстными ссылками, а потому зависит от порядка загрузки классов, но проследить этот порядок проблематично. Меня в C# "радует" вот такая возможность: Код: public static class A { public static readonly int a = B.b + 1; } public static class B { public static readonly int b = A.a + 1; } Всё компилируется и даже "работает". |
Автор: | Comdiv [ Пятница, 07 Ноябрь, 2008 15:21 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Сергей Губанов писал(а): Меня в C# "радует" вот такая возможность: Код: public static class A { public static readonly int a = B.b + 1; } public static class B { public static readonly int b = A.a + 1; } Всё компилируется и даже "работает". Попробовал в Яве. Тоже работает, причём System.out.println("A.a == " + A.a + "; B.b == " + B.b); //выдаёт A.a == 2; B.b == 1 System.out.println("B.b == " + B.b + "; A.a == " + A.a); //выдаёт B.b == 2; A.a == 1 А вот, что ещё можно: Код: public class A { public static int a; } public class B { public static final int B = A.a; } Особенно прикольно вносить изменения в программы с подобным кодом и узнавать, что из-за смещения момента загрузки класса, константа приобретает значение переменной, отличное от предыдущего, из-за чего логика программы рушится. Фактически в Ява нельзя объявить именованную константу - это лишь особые переменные, приобретающие значение один раз. В принципе, можно писать приложения - "шедевры" вообще без функций, а всю работу выполнять объявлением таких вот почти констант. |
Автор: | Alexey Veselovsky [ Пятница, 07 Ноябрь, 2008 16:16 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Comdiv писал(а): Представим, что это глючное приложение было бы написано на Обероне. Моя задача была бы очень простой: достаточно было бы перенести компактные секции инициализации в процедуры, проследить порядок загрузки модулей, выведя при загрузке имена модулей в лог, и при запуске мидлета выполнить в этом порядке процедуры. И это было бы ошибкой. Насколько я помню, описанием языка никак не гарантирована очередность инициализации модулей. Также не гарантировано сохранение оной очередности от запуска к запуску. Также нет средств для управления таковой очередностью. Т.о. выявив один раз очередность запусков и завязав на нее логику программы, вы получаете UB. В С++ эта проблема решается. В Аде она решается ещё проще и возможностей по контрою элаборации там значительно больше. Вплоть до явного указания кто и после кого. |
Автор: | Alexey Veselovsky [ Пятница, 07 Ноябрь, 2008 16:19 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Сергей Губанов писал(а): Comdiv писал(а): К тому же в портируемом приложении инициализация напичкана перекрёстными ссылками, а потому зависит от порядка загрузки классов, но проследить этот порядок проблематично. Меня в C# "радует" вот такая возможность: Код: public static class A { public static readonly int a = B.b + 1; } public static class B { public static readonly int b = A.a + 1; } Всё компилируется и даже "работает". Кстати, если мне мой склероз не изменяет, то в C# есть т.н. конструкторы статических классов. Или статические конструкторы... Как-то так. |
Автор: | Илья Ермаков [ Пятница, 07 Ноябрь, 2008 16:32 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Alexey Veselovsky писал(а): И это было бы ошибкой. Насколько я помню, описанием языка никак не гарантирована очередность инициализации модулей. Гарантирована. Семантика импорта предполагает, что к началу "жизни" модуля A (т.е. моменту его инициализации, независимо от того, есть дин. загрузка или нет) все импортированные им модули готовы к использованию. Т.е. инициализированы. Ациклический направленный граф простым и ясным образом задаёт частичный порядок инициализации. Что частичный - пугать не должно, т.к. неупорядоченными остаются только независящие друг от друга модули. Конечно, если разрешить циклическое использование модулей - вот тогда возникает букет проблем типа элабораций и проч. |
Автор: | Alexey Veselovsky [ Пятница, 07 Ноябрь, 2008 16:53 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Илья Ермаков писал(а): Alexey Veselovsky писал(а): И это было бы ошибкой. Насколько я помню, описанием языка никак не гарантирована очередность инициализации модулей. Гарантирована. Семантика импорта предполагает, что к началу "жизни" модуля A (т.е. моменту его инициализации, независимо от того, есть дин. загрузка или нет) все импортированные им модули готовы к использованию. Т.е. инициализированы. Ациклический направленный граф простым и ясным образом задаёт частичный порядок инициализации. Что частичный - пугать не должно, т.к. неупорядоченными остаются только независящие друг от друга модули. Конечно, если разрешить циклическое использование модулей - вот тогда возникает букет проблем типа элабораций и проч. Тут имеется один нюанс. Код: MODULE A; VAR a* : INTEGER; BEGIN a:=0; END A. MODULE B; IMPORT A; VAR b* : INTEGER; BEGIN b:=A.a; A.a:=a+1; END B. MODULE C; IMPORT A; VAR c* : INTEGER; BEGIN c:=A.a; A.a:=a+1; END C. Что будет в B.b и что будет в C.c ? |
Автор: | Илья Ермаков [ Пятница, 07 Ноябрь, 2008 17:02 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Да, такой момент есть. Но обсуждается проблема констант. Т.е. CONST либо VAR только для чтения, которые изменять из другого модуля нельзя. (экспорт на запись запретить бы вообще...) |
Автор: | Comdiv [ Пятница, 07 Ноябрь, 2008 17:19 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Илья Ермаков писал(а): (экспорт на запись запретить бы вообще...) В данном случае это ничего не даст. Раз переменную так объявили, значит есть необходимость менять её значение в других модулях. Если запретить экспорт на запись, то эта потребность будет удовлетворена созданием уродливой процедуры, которая делает только то, что устанавливает новое значение переменной. Это инкапсуляция, доведённая до абсурда. |
Автор: | Info21 [ Пятница, 07 Ноябрь, 2008 17:53 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Коллеги, очень интересно про инициализацию. Может быть, выделить в отдельную темку про "Чем хороши настоящие модули"? И вставить там в начале ссылочку на текст Сергея Юрьевича. |
Автор: | Alexey Veselovsky [ Пятница, 07 Ноябрь, 2008 19:08 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Comdiv писал(а): Илья Ермаков писал(а): (экспорт на запись запретить бы вообще...) В данном случае это ничего не даст. Раз переменную так объявили, значит есть необходимость менять её значение в других модулях. Если запретить экспорт на запись, то эта потребность будет удовлетворена созданием уродливой процедуры, которая делает только то, что устанавливает новое значение переменной. Это инкапсуляция, доведённая до абсурда. Запретить изменение "не своих" переменных в блоке инициализации модуля. Также ввести понятие константных функций/процедур (аля vod foo() const; в с++) которые не меняют какие-либо переменные и разрешить вызывать в блоке инициализации только их. |
Автор: | Илья Ермаков [ Пятница, 07 Ноябрь, 2008 19:16 ] |
Заголовок сообщения: | Re: Инициализация: преимущества нормальных модулей |
"Ввести... ввести... ввести..." Как же нам хочется чего-нибудь ввести, вместо того, чтобы неспеша поразмыслить... |
Автор: | Alexey Veselovsky [ Пятница, 07 Ноябрь, 2008 19:21 ] |
Заголовок сообщения: | Re: Инициализация: преимущества нормальных модулей |
Илья Ермаков писал(а): "Ввести... ввести... ввести..." Как же нам хочется чего-нибудь ввести, вместо того, чтобы неспеша поразмыслить... А что, кто-то уже бросился реализовывать новые фичи в компиляторе оберона или КП? По моему, мы тут как раз и размышляем. Неспешно. |
Автор: | Alexey Veselovsky [ Пятница, 07 Ноябрь, 2008 19:30 ] |
Заголовок сообщения: | Re: Инициализация: преимущества нормальных модулей |
Кстати, вот за C# не скажу, но вот в яве import это совсем не аналог #include, также это не аналог и IMPORT'a оберонова или же адского with. На самом деле это аналог using (С++) или use (Ada). Т.е. просто позволяет с типами/функциями/переменными обращаться фамильярно, без полного упоминания фамилии.имени.отчества. Всё что доступно, доступно сразу без import'a. Какие классы/модули будут загружены определяет класслоадер и его параметры/пути. Естественно можно написать свой класслоадер который будет грузить то что нужно тебе и так как тебе нужно. PS. Это сильно напоминает С, где #include как бы тоже не особо нужен. Т,е. без которого вполне можно обойтись. |
Автор: | Comdiv [ Пятница, 07 Ноябрь, 2008 20:00 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Alexey Veselovsky писал(а): Запретить изменение "не своих" переменных в блоке инициализации модуля. Также ввести понятие константных функций/процедур (аля vod foo() const; в с++) которые не меняют какие-либо переменные и разрешить вызывать в блоке инициализации только их. Поскольку не всегда во время компиляции можно знать какими значениями инициализировать переменные, а также поскольку блок инициализации нужен не только для задания значений переменным, то запретить вызов неконстантных процедур нельзя, а раз так , то и в запрете на присвоение не своим переменным тоже нет смысла. Тот пример, что Вы привели, в том или ином виде может иметь смысл. Для моего случая, он как ни крути не представляет проблемы. Поскольку мидлет - это одно приложение, то и В, и С будут проимпортированы другими модулями программы, а следовательно можно совершенно однозначно сказать, какой из этих модулей будет загружаться первым. |
Автор: | Сергей Оборотов [ Суббота, 08 Ноябрь, 2008 16:35 ] |
Заголовок сообщения: | Re: Инициализация: преимущества нормальных модулей |
А один мидлет может запустить другой? |
Автор: | Сергей Губанов [ Воскресенье, 09 Ноябрь, 2008 00:27 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Alexey Veselovsky писал(а): Кстати, если мне мой склероз не изменяет, то в C# есть т.н. конструкторы статических классов. Или статические конструкторы... Как-то так. Да есть. Приведённый ранее пример есть ещё один образец синтаксического сахара C#, который компилятор раскрывает в следующий код со статическими конструкторами: Код: public static class A { public static readonly int a; static A () { a = B.b + 1; } } public static class B { public static readonly int b; static B () { b = A.a + 1; } } Закавыка в разрешении циклического импорта, а не в способе это выразить. |
Автор: | Info21 [ Воскресенье, 09 Ноябрь, 2008 08:03 ] |
Заголовок сообщения: | Re: "Типизированные константы" |
Alexey Veselovsky писал(а): Тут имеется один нюанс. Это же совсем другая проблема. |
Автор: | Сергей Оборотов [ Воскресенье, 09 Ноябрь, 2008 11:56 ] |
Заголовок сообщения: | Re: "Инициализация: преимущества нормальных модулей" |
Ткачёв Ф.В. писал(а): Это же совсем другая проблема. В чем проблема? Поменять заголовки в cообщениях?
|
Автор: | Comdiv [ Понедельник, 10 Ноябрь, 2008 13:45 ] |
Заголовок сообщения: | Re: Инициализация: преимущества нормальных модулей |
GUEST писал(а): А один мидлет может запустить другой? Нет |
Страница 1 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |