понедельник, 30 ноября 2009 г.

Неформат.

Прочитал в блоге у коллеги заметку про встроенный в IDE форматтер. Человек не пожалел времени, разложил все по полочкам с примерами. Добавить в общем-то и нечего, окромя нескольких косяков этого форматтера. Ну, кто про что, а я - про баги. =)


Наличие встроенного средства форматирования в среде разработки - это как бальзам на душу. Я уже по этому поводу высказывался. Поэтому, как только появилась такая возможность, я сразу же приступил к его использованию. Горячая клавиша (ctrl+d) расположена удобно - так и подмывает её периодически нажимать. Да и функционирует новый форматтер неплохо. Но есть несколько нюансов в его работе, из-за которых код форматируется ошибочно. Обратимся к примерам:
















Как видите, с классами TTest1, TTest2 и TTest3 все в порядке. А вот TTest4 получился кривым: отступ у класса неверен и метод съехал набекрень. Найти "десять" различий не сложно. У класса TTest1 есть завершающий End, у TTest3 - его нет. И хотя такая конструкция успешно компилируется, форматтер на ней глючит. Эффект наблюдается кумулятивный: когда идут подряд несколько классов, подобных TTest3 - отступ у расположенных ниже по коду конструкций становиться гигантским. Они съезжают к правой границе экрана и пугают разработчика своим остроконечным разнобоем, напоминая выравнивание текста по правому краю.

Другая заковыка касается использования точки с запятой. Обратите внимание на результаты форматирования, приведенные ниже:



































В методе класса TTest4 всё хорошо, а вот у класса TTest2 из-за опущенной точки с запятой наблюдаем смещение блока "finally end" в первом случае и finally во втором. Так что если после форматирования "что-то не так" - проверьте end-ы и точки с запятыми. Безусловно, жить данные баги не мешают и решаются легко.

Рад, если был кому-нибудь полезен =).

вторник, 24 ноября 2009 г.

Экспроприаторы

Прочитал в блоге Александра Божко о проекте DelphiFeeds.RU. Вещь безусловно нужная и полезная. Раньше в рунете был только один агрегатор-старичок DelphiPlus.org, который уже более десяти лет регулярно снабжает нас новостями, ну а "теперь мы вдвое больше сена для нашей коровки запасем!" На данный момент в списке присутствует 19 блогов. Не без интереса изучил каждый из них - всё-таки послушать коллег чертовски интересно. Видно, что каждый в чем-то поднаторел, каждого гложет несправедливость этого мира и он пытается воздействовать на это посильным ему образом. Некоторые блоги, надо признаться, вижу в первый раз, что говорит о том, что не всё так плохо в датском коровлевтсве - люди пишут, общаются, творят. Но больше других заинтересовал и удивил блог под номером 17. По ссылке переходим на сайт http://adwos.ru/blog и видим... мои собственные посты двухлетней давности, снабженные, правда, заботливо подобранными картинками и свежей датой публикации =).

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

пятница, 23 октября 2009 г.

Компьютеру надо верить.

Скачал как-то я 64-битную версию Windows7 c Technet, чтобы проверить работоспособность своих приложений. Признаюсь: за рутиной никак не доходили руки почитать про особенности 64-х разрядных систем, поэтому в этих вопросах я плаваю основательно, и наличие огромных граблей в работе программы меня совсем не удивило. Будь я титаном, непременно бы догадался о причинах появления этого садового инструмента. А я в начале впал в ступор, потом не верил своим глазам, и лишь потом взял чашечку кофе и начал просветлятся. Но обо всем по порядку.

Есть у меня модуль, которые проверяет цифровые подписи драйверов. Обычный такой среднестатистический модуль килобайт на 50. В общем, ничего примечательного. Тестекйз этого модуля под win64 падал в разных местах с удивительными для меня эффектами. Подробное изучение происходящего привело меня к причине ошибочного поведения - функции FileExists(). Она никак не хотела видеть модули, находящиеся в системном каталоге windows\system32\drivers. Причем, если скопировать, например, из отладчика путь к модулю C:\Windows\System32\drivers\acpi.sys и выполнить его в командной строке - все работает. Из программы - фигвам. Первое, что приходит в голову, это то, что глючит рабочая лошадка - FileExists. Тут же были испробованы альтернативные способы добраться до файлов, но результат был стабилен и одинаков - такого драйвера в каталоге нет. Да и эксперименты с параметрами функции показали, что проблема только с системными каталогами. Тут я вспомнил слова одного моего товарища: "Компьютеру надо верить!" Если он говорит, что нет файла значит его там действительно нет. А то, что FAR видит этот файл - так это проблемы FAR-а. Далее я легким движением руки программно получил список содержимого каталога C:\Windows\System32\drivers\ и пришел к выводу, что передо мной на самом деле каталог C:\Windows\SysWOW64\drivers\. Там действительно файла acpi.sys нет - налицо транспарентная подмена системных папок, что в новых поколениях Windows на каждом шагу. В качестве дальнейшего источника просветления я выбрал MSDN, где нашел статейку и нужные функции. Так родился скупой, как мужская слеза, код:

function DisableRedirection(out Value: Pointer): Boolean;
const
  DIS_ALIAS = 'Wow64DisableWow64FsRedirection';
type
  TDisableRedirectionFunc = function(OldValue: Pointer): Boolean; stdcall;
var
  DisRedir: TDisableRedirectionFunc;
begin
  @DisRedir := GetProcAddress(GetModuleHandle(kernel32), DIS_ALIAS);

  if Assigned(DisRedir) then
    Result := DisRedir(@Value)
  else
    Result := False;
end;

function EnableRedirection(Value: Pointer): Boolean;
const
  REVERT_ALIAS = 'Wow64RevertWow64FsRedirection';
type
  TRevertRedirectionFunc = function(OldValue: Pointer): Boolean; stdcall;
var
  RevRedir: TRevertRedirectionFunc;
begin
  @RevRedir := GetProcAddress(GetModuleHandle(kernel32), REVERT_ALIAS);

  if Assigned(RevRedir) then
    Result := RevRedir(@Value)
  else
    Result := False;
end;

Ну и напоследок несколько комментариев:

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

- Как видно из документации, управление редиректом осуществляется только в вызывающем потоке. Этим можно воспользоваться.

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

- В каталоге system32 лежат 64-х разрядные компоненты, в SysWOW64 - 32-х разрядные. Изрядная путаница в названиях не должна смущать настоящего windows-разработчика. Путаница - это священная традиция, без которой создание программ под windows попросту невозможно.

понедельник, 19 октября 2009 г.

Снова про диаграммы...

Повертел я редактор диаграмм в Delphi 2010. Видно, что с ним поработали: добавились разные незначительные фишки, слегка изменился внешний вид. В целом стало  существенно стабильнее и быстрее. Тем не менее, всё ещё периодически генерится некомпилируемый код, идентификаторы блуждают по исходнякам, есть много мелких замечаний по юзабилити. В частности, непонятно, зачем лицезреть в инспекторе объектов кучу всяких бесполезных свойств диаграммы класса вроде Gradient Color 1, Gradient Color 2 и т.д. Их там добрых 50%, и за ними хорошо умеют прятаться нужные свойства. Или вот: пользовательские свойства диаграммы видны в инспекторе объектов, но поменять их там нельзя - только через специальный редактор или в исходном коде.


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

Как говаривал Билл Гейтс: "Значит нам есть ещё над чем работать..."

Обидно. 5-ый релиз уже. Складывается стойкое ощущение, что направление LiveSource + Together факультативное, и работают с ним по остаточному принципу.

среда, 7 октября 2009 г.

Манифест некоммунистической партии.

Категорически приветствую вас, уважаемые коллеги!

Наконец-то(!) появилось время что-нибудь черкнуть не только на языке компьютера и не для компьютера =).
Два больших и интересных проекта поглотили меня с головой. Возможно, как-нибудь расскажу и о них. Тем более, там есть о чем поведать... Но сегодня я хотел поговорить о другом. На днях столкнулся с проблемой, которая помимо ассоциации со знаменитым трудом Карла Генриха Маркса и Фридриха непоймикого Энгельса привела меня в замешательство. Есть у меня один проект, работа которого под правильными операционными системами не возможна без запроса определенных прав.
Для получения этих прав в манифесте, находящемся в ресурсах приложения, необходимо указать начальный уровень привилегий. Подробно об этом можно прочитать на MSDN или в новом блоге Александра Божко.
Надо отметить, что ранее (в D2007) особых проблем с манифестами не было, так как они добавлялись руками трудолюбивых разработчиков. Теперь же, в эпоху тотально автоматизации создатели передовой IDE решили помочь разработчикам, избавив их от рутинной работы. Тепрь D2010 сама прикрутит за вас манифест со своими параметрами, изменить которые в проекте нет никакой возможности. Прямо как в том мультфильме:
— Так вы что, и конфеты за меня есть будете?!.. — АГА!!!

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

Что ж, мы, как говориться, не ищем легких путей, да и покой нам только снится. К сожалению, FinalBuilder выдирать манифесты ещё не научился. А готовой консольной программы, которая могла бы запускаться из пакетных файлов, вырезать ресурсы и при этом корректно отдавать ExitCode, я за приемлемое время не нашел. Пришлось достать коленку, и на ней написать патчилку косяка. Вот, может быть кому-нибудь ещё пригодиться.

MD5 архива: 3abd737e5d990240b08d856f487a4b3b
MD5 ехе: 3b18c4323ec1226bbf466515c86ce1fa

понедельник, 26 января 2009 г.

АОП и Delphi(часть 2)

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

Так как АОП – это, по большому счету, дополнение к ООП, то и ключевых понятий в нем не так много. Нам понадобятся всего 4:
1) Аспект (Aspect) – это модуль, описывающий когда, в каком месте программы и какой код мы хотим вызывать. Говоря слово модуль, я придерживаюсь терминологии создателей АОП, хотя в нашем случае правильнее было бы сказать, что аспект – это некий класс, описывающий то, как надо модифицировать поведение другого класса. Поэтому аналогия с классом-хелпером в первой части этой статьи уместна, но не реализуема в полной мере.
2) Точка выполнения/присоединения (Joinpoint) - грубо говоря - любое место в программе, куда можно поставить breakpoint, хотя в конкретной реализации АОП и конкретном языке программирования это может быть далеко не так. Но для понимания такое определение нам хорошо подходит. В идеале получается, что мы можем сослаться на любое место в нашей программе, хотя на практике речь, конечно, идет о вызове методов, чтении свойств и т.д.
3) Срез (Pointcut) – это описание группы точек выполнения, отобранных по некоторым правилам. Например, может возникнуть задача трассировать вызовы всех публичных методов некоторого класса. Трудоемко и не эффективно описывать все эти методы в своем аспекте, а при добавлении или удалении методов снова модифицировать аспект. Поэтому, должны быть предусмотрены языковые конструкции, позволяющие описать сразу множество точек выполнения, связанных общими признаками. Можно даже реализовать некий язык запросов, упрощающий селекцию.
4) Применение (Advice) – это участок кода, которому можно передать управление до, после или быть может даже вместо выполнения некоторого кода, описанного некоторой точкой выполнения.

Таким образом, мы можем создать некий класс (аспект), который привносит дополнительную функциональность в уже работающий код. В этом классе описывается, в какое место или места (точка выполнения или срез) следует инжектировать код (применение), чтобы изменить поведение программы. И вот мы подошли к важному моменту, который многие статьи упоминают вскользь, сосредотачиваясь на практической стороне дела. А это, на мой взгляд, и является основной идеей: АОП – это, по сути дела возможность представить плоский код программы в виде нескольких функциональных блоков, выделив каждую ветвь бизнес-логики, разбросанную по плоской программе в отдельный законченный модуль. А уже модули разработчик может соединить в конкретное приложение с помощью аспектов. Иными словами, с помощью аспектов из готовых компонентов мы можем получить конкретную реализацию программы.
Теперь давайте посмотрим, какие преобразования происходят с исходным кодом при компиляции и сборке программы. К примеру, разработчик создает систему биллинга, включающую:
1) Модуль с четкой и лаконичной функцией оплаты клиентом некоторой услуги.
2) Модуль аутентификации и проверки прав доступа, описывающий, куда и как пользователю можно обращаться.
3) Модуль документирования действий, описывающий, когда и как логгировать действия пользователя.
4) Модуль, содержащий аспект, который определят, как использовать три предыдущих модуля(класса).
В данном случае основной бизнес-логикой программы является модуль номер 1. Именно он решает поставленную перед разработчиком задачу. Модули 2 и 3 – типичные примеры сквозной функциональности. Причем, если класс, отвечающий за безопасность – обязательный для работы программы, то лог может включаться только для тестовых версий. Изменить поведение программы не сложно - достаточно при компиляции использовать два разных аспекта – один с включенным логом, другой без. Прожженным программистам может показаться, что проще использовать директивы условной компиляции, плотно прописавшиеся в арсенале Delphi разработчика, но вот сторонники АОП пытаются доказать, что с приходом аспектов востребованность условной компиляции будет сведена к минимуму. Но об этом мы ещё поговорим чуть позже.
Важным игроком во всей этой истории является некий АОП-шный блендер, который перемешивает по описанным в аспекте правилам содержимое трех первых модулей, получая готовое к исполнению приложение. По сути дела, эта самая интересная техническая часть системы. Подходы к её реализации условно можно разделить на три группы:
1) Поддержка на уровне языка.
2) Препроцессорная обработка.
3) Использование внутренних механизмов компилятора и языка.
Понятно, что первый случай – идеальный вариант, который в данном конкретном случае пока мерещится в призрачном будущем. И хотя Ник Хождес в своем эссе прозрачно намекает на то, что формат DCU скоро канет в лету, а к нам придет новый супермодный компилятор, наивно полагать, что это творение сразу же можно будет использовать в реальных проектах. Пока оно созреет, пока обрастет кучей тредов в профильных конференция, покроется заплатами и сервис-паками, будет готова следующая версия Delphi, а может и не одна.
Вариант номер два. Используя препроцессор, мы получаем некий готовый исходный код, который потом отдается на откуп компилятору. В этом есть большой плюс, так как всегда можно посмотреть, что же там за лажа такая получилась на выходе. В случае с Delphi препроцессоров АОП мне найти не удалось, зато есть несколько решений по третьему пункту. В основном разработчики используют RTTI, хотя в сети есть и экзотические хакерские способы братьев-китайцев, смысл использования которых в собственных приложениях, мягко говоря, туманен.
Чтобы излишне не обнадеживать страждущих, сразу скажу, что готовые программы изменить под использование некоторых возможностей АОП вряд ли удастся, так как библиотеки используют свою иерархию классов, а справедливость и обоснованность предложенных решений не всегда очевидна. Тем не менее, библиотеки существуют, их можно тестировать и пробовать. А насколько они стабильны и удобны – может показать только ежедневное пристрастное использование.
Итак, MeAOP и Infra.

(продолжение следует)