В последнее время я все чаще задумываюсь о смысле апдейта текущей версии Delphi на более новую. Есть ли в этом необходимость?
С учетом, что я разрабатываю 32 битные приложения только под Win - вся эта петрушка в виде возможности разработки под Андроид или iOS прямо на Delphi, ну... скажем так — не сильно востребована.
А вот что более востребовано — так это стабильная работа среды, отсутствие ошибок при работе с дженериками/лямдами и всем тем "синтаксическим сахаром", который внедряется уже какой год.
Вы будете смеяться, но я однажды вообще от инлайнов отказался по многим причинам, в частности одна из них была в том, что кодогенератор выдавал абсолютно невалидный асм код в определенных ситуациях, абсолютно переиначивая всю логику работы inline функции (банально не тот результат возвращала). Кажется это было на 2010 или ХЕ первой.
Впрочем посмотрим что мы имеем сейчас.
Краткий перечень нововведений:
GetIt - забавная такая приблуда, позволяющая оперативно ставить сторонние пакеты. Но вот вопрос:
А как часто вы ставите сторонние пакеты компонентов?
Лично я, только при переустановке дельфи ставлю VirtualStringTree, плюс раз в полгода обновляю DevExpress (зависит от того, как часто они сами родят новую версию).
Ничего против, конечно, не имею - но GetIt это просто фишка, не имеющая к процессу разработки никакого отношения.
DUnitX - ну, допустим, юниттестирование должно прививаться разработчикам.
Интеграция различных систем контроля версий (SVN/Git/HG - Mercurial).
Этот момент спорный - люди годами ими пользуются, в том числе и экспертами, которые уже умеют это все делать. Не факт что удачный ход.
Тоже относится и к Castalia - первый вопрос будет, для непривычного пользователя: как это отключить? (например вот так).
А что еще осталось?
С учетом, что я разрабатываю 32 битные приложения только под Win - вся эта петрушка в виде возможности разработки под Андроид или iOS прямо на Delphi, ну... скажем так — не сильно востребована.
А вот что более востребовано — так это стабильная работа среды, отсутствие ошибок при работе с дженериками/лямдами и всем тем "синтаксическим сахаром", который внедряется уже какой год.
Вы будете смеяться, но я однажды вообще от инлайнов отказался по многим причинам, в частности одна из них была в том, что кодогенератор выдавал абсолютно невалидный асм код в определенных ситуациях, абсолютно переиначивая всю логику работы inline функции (банально не тот результат возвращала). Кажется это было на 2010 или ХЕ первой.
Впрочем посмотрим что мы имеем сейчас.
Краткий перечень нововведений:
- GetIt package manager for seamless installation of components
- DUnitX support
- Version Insight support for Mercurial, and improved support for Git and Subversion
- IDE configuration migration tool
- Faster CHM help
- Start here page redesign
- Project statistics information
- Clipboard history
- Multi-paste support
- Stack bookmarks
- Smart keys
- Parenthesis matching
- Code structural highlight
- Castalia refactorings
- Editor selection expansion
- Flow controls highlighting
- Code navigation toolbar
- Smart symbol search
- Code analysis to track quality
GetIt - забавная такая приблуда, позволяющая оперативно ставить сторонние пакеты. Но вот вопрос:
А как часто вы ставите сторонние пакеты компонентов?
Лично я, только при переустановке дельфи ставлю VirtualStringTree, плюс раз в полгода обновляю DevExpress (зависит от того, как часто они сами родят новую версию).
Ничего против, конечно, не имею - но GetIt это просто фишка, не имеющая к процессу разработки никакого отношения.
DUnitX - ну, допустим, юниттестирование должно прививаться разработчикам.
Интеграция различных систем контроля версий (SVN/Git/HG - Mercurial).
Этот момент спорный - люди годами ими пользуются, в том числе и экспертами, которые уже умеют это все делать. Не факт что удачный ход.
Тоже относится и к Castalia - первый вопрос будет, для непривычного пользователя: как это отключить? (например вот так).
А что еще осталось?
Ну, хелп да редизайн стартовой страницы (зачем вообще об этом упоминать?).
История буфера - такое уже видели в виде экпертов.
Остальные фишки - да, интересны, но может взглянем на решарпер (продвинутое расширение IDE для C#) и его возможности? :)
Ну и какой сделаем вывод - все плохо?
А вот с этим будет нюанс и для раскрытия оного я процитирую своего коллегу: Алексея Казанцева.
Банально сравниваем две строки.
Но давайте посмотрим на кодогенерацию в продуктах до ХЕ включительно:
Абсолютно логичный код - никаких претензий, но посмотрим что будет под XE2:
Страшно, но сейчас посмотрим что выдается под ХЕ4/ХЕ5:
Впечатлились?
Вот и я тоже, впрочем я не оставлял надежды что когда-то все придет в норму.
И вот вышла ХЕ8 и я сразу попросил проверить данный код, и что вы думаете?
Бинго.
Кодогенератор отдали в правильные руки и он снова стал работать как нужно.
А еще поправили несколько ошибок в дженериках, критичных лично для меня, но это уже не суть.
Так вот вопрос, а почему ломали кодогенерацию столько версий подряд?
Через тернии к звездам? :)
Впрочем, теперь я уверен - на ХЕ8 переходить с ХЕ2 и выше стоит.
UPDATE:
Ан нет - поторопился.
В процессе тестов нашел интересный глюк, который не позволяет мне собрать проект. Причем билдится нормально, а на этапе компиляции происходит вот такое:
Впрочем, глюк не то чтобы интересный - глюк критический.
UPDATE2:
Накидаю несколько своих мыслей по поводу данной ошибки.
Завтра, конечно попробую выдать на гора что-то воспроизводящееся, но пока что просто суть.
Сейчас мы сидим на XE4, и на нем наблюдается следующие типы ошибок (на самом главном и достаточно большом проекте под полтора лямов строчек).
Если нажать F9 (просто компиляция) то может произойти:
Обходится это все обычным ребилдом проекта, после чего компиляция начинает работать нормально.
Началось это с перехода на ХЕ.
Подозреваю, что проблема из-за того что у нас очень большое количество модулей, ссылающихся друг на друга достаточно капитальное кол-во раз и где-то именно на анализе этих перекрестных ссылок линкер и начинает дурить.
В данном случае, билд проходит успешно, но при компиляции (жмаем F9) происходит вот такая вот рекурсивная беда.
Причем в данном случае это просто юнит-тест, который используется только один модуль (связку остальных он сам подтягивает).
Хорошо что хоть с юнитом определился и завтра попробую это дело развязать и понять - что за оно такое.
UPDATE3:
На 24 миллионах строчек скомпилированного кода оно успокоилось :)
Выдав ошибку:
Однако ж - час компилилось.
Сурово.
UPDATE4:
Становится все интересней.
В рамках тестирования создал новый VCL проект и подключил к нему один из тестируемых модулей.
Результат компиляции:
Остальные фишки - да, интересны, но может взглянем на решарпер (продвинутое расширение IDE для C#) и его возможности? :)
Ну и какой сделаем вывод - все плохо?
А вот с этим будет нюанс и для раскрытия оного я процитирую своего коллегу: Алексея Казанцева.
program inline_bug; {$APPTYPE CONSOLE} {$OPTIMIZATION ON} {$INLINE ON} {$R *.res} uses SysUtils; type Utils = class type Namespace = class class function Comparestring(const ALeft, ARight: string) : Integer; static; inline; class function CompareText(const ALeft, ARight: string) : Integer; static; inline; class function Samestring(const ALeft, ARight: string; ACaseSensitive : Boolean = True) : Boolean; static; inline; end; end; { Utils.NameSpace } class function Utils.Namespace.Comparestring(const ALeft, ARight : System.string) : Integer; begin Result := SysUtils.CompareStr(ALeft, ARight); end; class function Utils.Namespace.CompareText(const ALeft, ARight : string) : Integer; begin Result := SysUtils.CompareText(ALeft, ARight); end; class function Utils.Namespace.Samestring(const ALeft, ARight : string; ACaseSensitive : Boolean) : Boolean; begin if ACaseSensitive then Result := Utils.Namespace.Comparestring(ALeft, ARight) = 0 else Result := Utils.Namespace.CompareText(ALeft, Aright) = 0; end; var S1, S2: string; begin Utils.Namespace.Comparestring(S1, S2); Utils.Namespace.Samestring(S1, S2); S1 := ''; end.
Банально сравниваем две строки.
Но давайте посмотрим на кодогенерацию в продуктах до ХЕ включительно:
inline_bug.dpr.68: Utils.Namespace.CompareString(S1, S2); 0040915A 8B1524E24000 mov edx,[$0040e224] 00409160 A120E24000 mov eax,[$0040e220] 00409165 E8F2C7FFFF call CompareStr inline_bug.dpr.69: Utils.Namespace.SameString(S1, S2); 0040916A 8B1524E24000 mov edx,[$0040e224] 00409170 A120E24000 mov eax,[$0040e220] 00409175 E8E2C7FFFF call CompareStr 0040917A 85C0 test eax,eax 0040917C 0F94C0 setz al
Абсолютно логичный код - никаких претензий, но посмотрим что будет под XE2:
inline_bug.dpr.68: Utils.Namespace.CompareString(S1, S2); 0041B3AB 8D45EC lea eax,[ebp-$14] 0041B3AE 8B15D82E4200 mov edx,[$00422ed8] 0041B3B4 E84BA4FEFF call @UStrLAsg 0041B3B9 8D45E8 lea eax,[ebp-$18] 0041B3BC 8B15DC2E4200 mov edx,[$00422edc] 0041B3C2 E83DA4FEFF call @UStrLAsg 0041B3C7 8B55E8 mov edx,[ebp-$18] 0041B3CA 8B45EC mov eax,[ebp-$14] 0041B3CD E8F28FFFFF call CompareStr inline_bug.dpr.69: Utils.Namespace.SameString(S1, S2); 0041B3D2 8D45E4 lea eax,[ebp-$1c] 0041B3D5 8B15D82E4200 mov edx,[$00422ed8] 0041B3DB E824A4FEFF call @UStrLAsg 0041B3E0 8D45E0 lea eax,[ebp-$20] 0041B3E3 8B15DC2E4200 mov edx,[$00422edc] 0041B3E9 E816A4FEFF call @UStrLAsg 0041B3EE 8D45DC lea eax,[ebp-$24] 0041B3F1 8B55E4 mov edx,[ebp-$1c] 0041B3F4 E80BA4FEFF call @UStrLAsg 0041B3F9 8D45D8 lea eax,[ebp-$28] 0041B3FC 8B55E0 mov edx,[ebp-$20] 0041B3FF E800A4FEFF call @UStrLAsg 0041B404 8B55D8 mov edx,[ebp-$28] 0041B407 8B45DC mov eax,[ebp-$24] 0041B40A E8B58FFFFF call CompareStr 0041B40F 85C0 test eax,eax 0041B411 0F94C0 setz al
Страшно, но сейчас посмотрим что выдается под ХЕ4/ХЕ5:
inline_bug.dpr.45: Utils.Namespace.Comparestring(S1, S2); 0041A3E4 8D45EC lea eax,[ebp-$14] 0041A3E7 8B15D81E4200 mov edx,[$00421ed8] 0041A3ED E8F2B6FEFF call @UStrLAsg 0041A3F2 8D45E8 lea eax,[ebp-$18] 0041A3F5 8B15DC1E4200 mov edx,[$00421edc] 0041A3FB E8E4B6FEFF call @UStrLAsg 0041A400 33C0 xor eax,eax 0041A402 55 push ebp 0041A403 683AA44100 push $0041a43a 0041A408 64FF30 push dword ptr fs:[eax] 0041A40B 648920 mov fs:[eax],esp 0041A40E 8B55E8 mov edx,[ebp-$18] 0041A411 8B45EC mov eax,[ebp-$14] 0041A414 E8F782FFFF call CompareStr 0041A419 8945CC mov [ebp-$34],eax 0041A41C 33C0 xor eax,eax 0041A41E 5A pop edx 0041A41F 59 pop ecx 0041A420 59 pop ecx 0041A421 648910 mov fs:[eax],edx 0041A424 6841A44100 push $0041a441 0041A429 8D45EC lea eax,[ebp-$14] 0041A42C E897B3FEFF call @UStrClr 0041A431 8D45E8 lea eax,[ebp-$18] 0041A434 E88FB3FEFF call @UStrClr 0041A439 C3 ret 0041A43A E9ADAAFEFF jmp @HandleFinally 0041A43F EBE8 jmp $0041a429 inline_bug.dpr.46: Utils.Namespace.Samestring(S1, S2); 0041A441 8D45E4 lea eax,[ebp-$1c] 0041A444 8B15D81E4200 mov edx,[$00421ed8] 0041A44A E895B6FEFF call @UStrLAsg 0041A44F 8D45E0 lea eax,[ebp-$20] 0041A452 8B15DC1E4200 mov edx,[$00421edc] 0041A458 E887B6FEFF call @UStrLAsg 0041A45D 8D45DC lea eax,[ebp-$24] 0041A460 E863B3FEFF call @UStrClr 0041A465 8D45D8 lea eax,[ebp-$28] 0041A468 E85BB3FEFF call @UStrClr 0041A46D 8D45D4 lea eax,[ebp-$2c] 0041A470 E853B3FEFF call @UStrClr 0041A475 8D45D0 lea eax,[ebp-$30] 0041A478 E84BB3FEFF call @UStrClr 0041A47D 33C0 xor eax,eax 0041A47F 55 push ebp 0041A480 6828A54100 push $0041a528 0041A485 64FF30 push dword ptr fs:[eax] 0041A488 648920 mov fs:[eax],esp 0041A48B 8D45DC lea eax,[ebp-$24] 0041A48E 8B55E4 mov edx,[ebp-$1c] 0041A491 E84EB6FEFF call @UStrLAsg 0041A496 8D45D8 lea eax,[ebp-$28] 0041A499 8B55E0 mov edx,[ebp-$20] 0041A49C E843B6FEFF call @UStrLAsg 0041A4A1 33C0 xor eax,eax 0041A4A3 55 push ebp 0041A4A4 68DBA44100 push $0041a4db 0041A4A9 64FF30 push dword ptr fs:[eax] 0041A4AC 648920 mov fs:[eax],esp 0041A4AF 8B55D8 mov edx,[ebp-$28] 0041A4B2 8B45DC mov eax,[ebp-$24] 0041A4B5 E85682FFFF call CompareStr 0041A4BA 8945C4 mov [ebp-$3c],eax 0041A4BD 33C0 xor eax,eax 0041A4BF 5A pop edx 0041A4C0 59 pop ecx 0041A4C1 59 pop ecx 0041A4C2 648910 mov fs:[eax],edx 0041A4C5 68E2A44100 push $0041a4e2 0041A4CA 8D45DC lea eax,[ebp-$24] 0041A4CD E8F6B2FEFF call @UStrClr 0041A4D2 8D45D8 lea eax,[ebp-$28] 0041A4D5 E8EEB2FEFF call @UStrClr 0041A4DA C3 ret 0041A4DB E90CAAFEFF jmp @HandleFinally 0041A4E0 EBE8 jmp $0041a4ca 0041A4E2 837DC400 cmp dword ptr [ebp-$3c],$00 0041A4E6 0F9445CB setz byte ptr [ebp-$35] 0041A4EA 33C0 xor eax,eax 0041A4EC 5A pop edx 0041A4ED 59 pop ecx 0041A4EE 59 pop ecx 0041A4EF 648910 mov fs:[eax],edx 0041A4F2 682FA54100 push $0041a52f 0041A4F7 8D45E4 lea eax,[ebp-$1c] 0041A4FA E8C9B2FEFF call @UStrClr 0041A4FF 8D45E0 lea eax,[ebp-$20] 0041A502 E8C1B2FEFF call @UStrClr 0041A507 8D45DC lea eax,[ebp-$24] 0041A50A E8B9B2FEFF call @UStrClr 0041A50F 8D45D8 lea eax,[ebp-$28] 0041A512 E8B1B2FEFF call @UStrClr 0041A517 8D45D4 lea eax,[ebp-$2c] 0041A51A E8A9B2FEFF call @UStrClr 0041A51F 8D45D0 lea eax,[ebp-$30] 0041A522 E8A1B2FEFF call @UStrClr 0041A527 C3 ret 0041A528 E9BFA9FEFF jmp @HandleFinally 0041A52D EBC8 jmp $0041a4f7 redsfds.dpr.47: S1 := ''; 0041A52F B8D81E4200 mov eax,$00421ed8 0041A534 E88FB2FEFF call @UStrClr
Впечатлились?
Вот и я тоже, впрочем я не оставлял надежды что когда-то все придет в норму.
И вот вышла ХЕ8 и я сразу попросил проверить данный код, и что вы думаете?
contest.dpr.68: Utils.Namespace.CompareString(S1, S2); 0041B49A 8B15C02E4200 mov edx,[$00422ec0] 0041B4A0 A1BC2E4200 mov eax,[$00422ebc] 0041B4A5 E8827CFFFF call CompareStr contest.dpr.69: Utils.Namespace.SameString(S1, S2); 0041B4AA 8B15C02E4200 mov edx,[$00422ec0] 0041B4B0 A1BC2E4200 mov eax,[$00422ebc] 0041B4B5 E8727CFFFF call CompareStr 0041B4BA 85C0 test eax,eax 0041B4BC 0F94C0 setz al contest.dpr.70: s1 := ''; 0041B4BF B8BC2E4200 mov eax,$00422ebc 0041B4C4 E8A7A9FEFF call @UStrClr
Бинго.
Кодогенератор отдали в правильные руки и он снова стал работать как нужно.
А еще поправили несколько ошибок в дженериках, критичных лично для меня, но это уже не суть.
Так вот вопрос, а почему ломали кодогенерацию столько версий подряд?
Через тернии к звездам? :)
Впрочем, теперь я уверен - на ХЕ8 переходить с ХЕ2 и выше стоит.
UPDATE:
Ан нет - поторопился.
В процессе тестов нашел интересный глюк, который не позволяет мне собрать проект. Причем билдится нормально, а на этапе компиляции происходит вот такое:
Впрочем, глюк не то чтобы интересный - глюк критический.
UPDATE2:
Накидаю несколько своих мыслей по поводу данной ошибки.
Завтра, конечно попробую выдать на гора что-то воспроизводящееся, но пока что просто суть.
Сейчас мы сидим на XE4, и на нем наблюдается следующие типы ошибок (на самом главном и достаточно большом проекте под полтора лямов строчек).
Если нажать F9 (просто компиляция) то может произойти:
- либо Internal Error
- либо откроется какой либо модуль, к нему добавится пустая строчка в самом конце модуля и выведется сообщение что не могу данный модуль сохранить (как правило для модулей которые сидят в Programm Files).
- либо - все будет хорошо (редкий случай).
Обходится это все обычным ребилдом проекта, после чего компиляция начинает работать нормально.
Началось это с перехода на ХЕ.
Подозреваю, что проблема из-за того что у нас очень большое количество модулей, ссылающихся друг на друга достаточно капитальное кол-во раз и где-то именно на анализе этих перекрестных ссылок линкер и начинает дурить.
В данном случае, билд проходит успешно, но при компиляции (жмаем F9) происходит вот такая вот рекурсивная беда.
Причем в данном случае это просто юнит-тест, который используется только один модуль (связку остальных он сам подтягивает).
Хорошо что хоть с юнитом определился и завтра попробую это дело развязать и понять - что за оно такое.
UPDATE3:
На 24 миллионах строчек скомпилированного кода оно успокоилось :)
Выдав ошибку:
Однако ж - час компилилось.
Сурово.
UPDATE4:
Становится все интересней.
В рамках тестирования создал новый VCL проект и подключил к нему один из тестируемых модулей.
Результат компиляции:
Копаю дальше.
UPDATE5:
А еще установщик утверждает что 13 свободных гигабайт ему мало :))
И все же, можно поподробнее об ошибках в дженериках? Раз уж вы их упомянули, раскройте тему до конца, плиз :)
ОтветитьУдалитьРано еще, еще не все ошибки выявлены. Обновил пост, добавил видео "вечной компиляции проекта" :)
УдалитьОй, красота :)
УдалитьЭто надо срочно в qc(qp), авось к первому апдейту пофиксят
УдалитьЭто если повезет и они смогут это воспроизвести...
УдалитьВ качестве ответа, обновил текст статьи.
УдалитьЖдем новых отчетов о расследовании!!!
УдалитьУ меня XE8 по сравнению с XE7 фиксит первые два пункта, упомянутые в Update2 статьи. Но добавляет зависание самой среды в режиме отладки. Не могу определить точных шагов для воспроизведения, но есть предположение, что глючит внутренний evaluator при отладке дженериков. Правда в XE7 у меня стоит IDE Fix Pack от Хаусладена...
ОтветитьУдалитьА восьмерка триал или уже боевая?
УдалитьОхохо, похоже в процессе тестирования я умудрился убить не только ХЕ8, но и до кучи основную ХЕ4.
ОтветитьУдалитьСам не понял, как так получилось, но - факт.
Можно сказать - рабочий день начался удачно :)))
Обновления для Windows не ставили?
УдалитьУ людей тоже проблемы (читать отсюда и ниже):
Удалитьhttp://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=190407&msg=17516531
Ничего не ставил, машина вообще у меня не перезагружается месяцами, но факт есть факт. Что XE8 и самое интересное XE4 тоже падает при старте с ошибкой: "The program can't start because rtl220.bpl is missing from your computer. Try reinstalling the program to fix this problem. "
УдалитьВообще ничего понять не могу.
Оставлю в качестве напоминалки для самого себя. Чтобы починить ХЕ4 после такого вот "убития", нужно найти в "Моих документах" все упоминания о ХЕ8 (к примеру C:\Users\Public\Documents\Embarcadero\Studio\16.0) и переименовать папку 16.0 в любую другую. Инсталятору от ХЕ8 это не поможет, но хотя бы ХЕ4 будет запускаться правильно.
УдалитьК слову, попробовал код в XE6 - там уже так же, как в 2010, то есть - нормально собирается.
ОтветитьУдалитьАга, я уже позже тоже проверил. Пофиксили кодогенерацию чуть раньше, но мы шестерку как-то мимо ушей пропустили, ибо там для нас не было ничего интересного :)
УдалитьЗдравствуйте Александр, у меня такой вопрос по XE8 стоит ли сейчас переходить(вроде там апдейты есть)? почему меня предыдущие XE не радуют - это большой скомпилированный код EXEшник, изменилась ли ситуация?
УдалитьЯ не проверял, поэтому сказать ничего не могу. Сейчас очень сильная нагрузка на работе, поэтому еще не скоро за это возьмусь.
Удалить