Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Динамический код:
модифицируем таблицу символов во время
выполнения
• Какие-то проблемы?
• Методы runtime-
кодогенерации
• Таблица символов:
матчасть
• От теории к практике
• Как не выстрели...
• Конструкторы
• Методы-аксессоры
• Идентичная предварительная обработка
данных
• Похожие по функционалу функции с
небольш...
package Foo;
sub new {
return bless {}, shift;
}
package Bar;
sub new {
return bless {}, shift;
}
www.mail.ru 4
Конструкто...
sub field1 {
my $self = shift;
$self->{field1} = $_[0] if @_;
return $self->{field1};
}
sub field2 {
my $self = shift;
$se...
sub do_something {
my $self = shift;
$self->check_cookies;
return $self->redirect('/login') unless $self->check_auth;
my $...
sub error {
my $message = shift;
my ($package, $line, $sub) = (caller(0))[0, 2, 3];
print $log scalar localtime, "ERROR: $...
• Потеря времени на
перепечатывание/копирование
• Ошибки из-за невнимательности
• Трудоемкость сопровождения
corp.mail.ru
...
• Ошибки в реализации
• Отсутствие поддержки кириллицы
• Недостаточный функционал
corp.mail.ru
Сторонние модули
print Dumper {test => 'Тестовая строка'};
www.mail.ru 10
Data::Dumper и
кириллица в utf8
$VAR1 = {
"test" =>
"x{422}x{435}...
package Foo;
use Moose;
has field1 => (is => 'rw');
has field2 => (is => 'rw');
has field3 => (is => 'rw');
around [qw(do_...
• Необходимость доказательства
целесообразности
• Замусоривание системы
• Замусоривание блоков use в коде
• Снижение произ...
• Какие-то проблемы?
• Методы runtime-
кодогенерации
• Таблица символов:
матчасть
• От теории к практике
• Как не выстрели...
• Переопределение подпрограмм
• eval
• Изменение таблицы символов
www.mail.ru 14
Модификация кода
use Data::Dumper;
$Data::Dumper::Useqq = 1;
{
no warnings 'redefine';
package Data::Dumper;
sub Data::Dumper::qquote {
my ...
package Wrapper;
sub make_accessors {
my $package = caller(0);
for (@_) {
eval qq{
package $package;
sub $_ {
my $self = s...
package Test;
use Wrapper;
sub new { return bless {}, shift; }
Wrapper::make_accessors( qw(name age) );
package main;
use ...
• Какие-то проблемы?
• Методы runtime-
кодогенерации
• Таблица символов:
матчасть
• От теории к практике
• Как не выстрели...
• Таблица символов – это хэш
www.mail.ru 19
Таблица символов
• Ключи – глобальные переменные и
подпрограммы
• Значения - т...
www.mail.ru 20
Таблица символов
package Test;
our $data = 'test';
our @data = qw(1 2 3);
our %data = (key1 => 'value1', ke...
*glob{PACKAGE} имя пакета
*glob{NAME} имя элемента (переменной или функции)
*glob{SCALAR} ссылка на значение-скаляр
*glob{...
Получение данных
my $scalar = ${ *Test::data };
my %hash = %{ *Test::data };
my @array = @{ *Test::data };
&{ *Test::data ...
• Какие-то проблемы?
• Методы runtime-
кодогенерации
• Таблица символов:
матчасть
• От теории к практике
• Как не выстрели...
package MakeAccessor;
sub import {
my $package = caller(0);
no strict 'refs';
*{"$package::has"} = &has;
}
sub has ($) {
m...
package MakeAccessor;
sub import {
my $package = caller(0);
no strict 'refs';
*{"$package::has"} = &has;
}
sub has ($) {
m...
www.mail.ru 26
Боремся с __ANON__
package MakeAccessor;
sub import {
my $package = caller(0);
no strict 'refs';
*{"$packag...
• Генераторы классов: десериализация, ORM
• Реализация паттерна «прокси»
• Тестирование: mock, stub, fake object
• Хуки дл...
package Response;
use CGI;
sub new {
return bless { cgi => CGI->new }, shift;
}
our $AUTOLOAD;
sub AUTOLOAD {
my ($method)...
package Wrapper;
sub make_deprecated {
my $deprecated = shift;
{
no strict 'refs';
return if *{$deprecated}{CODE};
};
my $...
use Test::More;
my $user_data = { ... };
{
no strict 'refs';
*{'Cache::Memcached::set'} = sub {
return 1;
};
*{'Cache::Mem...
package Wrapper;
sub before(@&) {
my ($methods, $wrapper) = @_;
my $package = caller(0);
for my $method (@$methods) {
my $...
• Какие-то проблемы?
• Методы runtime-
кодогенерации
• Таблица символов:
матчасть
• От теории к практике
• Как не выстрели...
• Прагмы strict и warnings
• __ANON__ в трассировке стэка
• Ссылки на переопределяемые функции
• Снижение читабельности ко...
use Data::Dumper;
*{Data::Dumper::Dumper} = sub {
return 'Hacked!';
};
say Dumper({key1 => 1, key2 => 2});
say Data::Dumpe...
package Wrapper;
our $name = 'Ann';
*{Test::test} = sub {
say $name;
say $Test::name;
};
package Test;
our $name = 'Bob';
...
eval
• Компиляция во время
выполнения
• Ускоренная
загрузка, возможность
компиляции по запросу
• Создание символов в
прост...
• perlmod: Symbol tables
• perlref
• perldata: Typeglobs and
Filehandlers
• Sriram Srinivasan.Advanced
Perl Programming
• ...
Шишкина Елена Владимировна
e.shishkina@corp.mail.ru
Upcoming SlideShare
Loading in …5
×

of

Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 1 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 2 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 3 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 4 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 5 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 6 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 7 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 8 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 9 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 10 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 11 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 12 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 13 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 14 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 15 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 16 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 17 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 18 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 19 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 20 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 21 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 22 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 23 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 24 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 25 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 26 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 27 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 28 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 29 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 30 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 31 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 32 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 33 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 34 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 35 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 36 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 37 Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля Slide 38
Upcoming SlideShare
Play Perl — распределенная социальная игра для Perl-разработчиков. Вячеслав Матюхин. Moscow.pm 4 апреля
Next
Download to read offline and view in fullscreen.

6 Likes

Share

Download to read offline

Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля

Download to read offline

Видео: http://video.mail.ru/corp/p.scherbinin/6/7.html

Tаблица символов — это только небольшой шаг в мир внутреннего устройства Perl, но и он открывает программисту огромные возможности:

— Runtime-кодогенерация.

— Генерация по запросу.

— Изменение кода сторонних модулей на лету и многое другое.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Динамический код: модифицируем таблицу символов во время выполнения. Елена Шишкина. Moscow.pm 4 апреля

  1. 1. Динамический код: модифицируем таблицу символов во время выполнения
  2. 2. • Какие-то проблемы? • Методы runtime- кодогенерации • Таблица символов: матчасть • От теории к практике • Как не выстрелить себе в ногу • RTFM 2
  3. 3. • Конструкторы • Методы-аксессоры • Идентичная предварительная обработка данных • Похожие по функционалу функции с небольшими отличиями corp.mail.ru Повторяющийся код
  4. 4. package Foo; sub new { return bless {}, shift; } package Bar; sub new { return bless {}, shift; } www.mail.ru 4 Конструкторы
  5. 5. sub field1 { my $self = shift; $self->{field1} = $_[0] if @_; return $self->{field1}; } sub field2 { my $self = shift; $self->{field2} = $_[0] if @_; return $self->{field2}; } sub field3 { my $self = shift; $self->{field3} = $_[0] if @_; return $self->{field3}; } www.mail.ru 5 Аксессоры
  6. 6. sub do_something { my $self = shift; $self->check_cookies; return $self->redirect('/login') unless $self->check_auth; my $form = $self->load_form('do_something'); $form->fetch; return $self->render_error() unless $form->validate; my $some_user_data = $self->load_user_data; ... } sub do_another_thing { my $self = shift; $self->check_cookies; ... } www.mail.ru 6 Предварительная обработка
  7. 7. sub error { my $message = shift; my ($package, $line, $sub) = (caller(0))[0, 2, 3]; print $log scalar localtime, "ERROR: ${package}::$sub ($line): $messagen"; print $log Carp::longmess if $Trace_Errors; } sub debug { my $message = shift; my ($package, $line, $sub) = (caller(0))[0, 2, 3]; print $log scalar localtime, "DEBUG: ${package}::$sub ($line): $messagen"; } sub info { ... } sub warning { ... } www.mail.ru 7 Похожие функции
  8. 8. • Потеря времени на перепечатывание/копирование • Ошибки из-за невнимательности • Трудоемкость сопровождения corp.mail.ru Проблемы повторяющегося кода
  9. 9. • Ошибки в реализации • Отсутствие поддержки кириллицы • Недостаточный функционал corp.mail.ru Сторонние модули
  10. 10. print Dumper {test => 'Тестовая строка'}; www.mail.ru 10 Data::Dumper и кириллица в utf8 $VAR1 = { "test" => "x{422}x{435}x{441}x{442}x{43e}x{432}x{430}x {44f} x{441}x{442}x{440}x{43e}x{43a}x{430}" };
  11. 11. package Foo; use Moose; has field1 => (is => 'rw'); has field2 => (is => 'rw'); has field3 => (is => 'rw'); around [qw(do_something do_another_thing)] => sub { my ($orig, $self) = @_; ... $self->$orig(form => $form, user_data => $some_user_data); }; www.mail.ru 11 Решение: CPAN
  12. 12. • Необходимость доказательства целесообразности • Замусоривание системы • Замусоривание блоков use в коде • Снижение производительности • Увеличение времени компиляции • Расход памяти • Уменьшение контроля над кодом («чужой код») www.mail.ru 12 Проблемы использования сторонних модулей
  13. 13. • Какие-то проблемы? • Методы runtime- кодогенерации • Таблица символов: матчасть • От теории к практике • Как не выстрелить себе в ногу • RTFM 13
  14. 14. • Переопределение подпрограмм • eval • Изменение таблицы символов www.mail.ru 14 Модификация кода
  15. 15. use Data::Dumper; $Data::Dumper::Useqq = 1; { no warnings 'redefine'; package Data::Dumper; sub Data::Dumper::qquote { my $s = shift; return "'$s'"; } } www.mail.ru 15 Переопределение
  16. 16. package Wrapper; sub make_accessors { my $package = caller(0); for (@_) { eval qq{ package $package; sub $_ { my $self = shift; $self->{$_} = $_[0] if @_; return $self->{$_}; } }; } } www.mail.ru 16 eval
  17. 17. package Test; use Wrapper; sub new { return bless {}, shift; } Wrapper::make_accessors( qw(name age) ); package main; use Test; my $obj = Test->new; $obj->name('Ann'); say $obj->name; www.mail.ru 17 eval
  18. 18. • Какие-то проблемы? • Методы runtime- кодогенерации • Таблица символов: матчасть • От теории к практике • Как не выстрелить себе в ногу • RTFM 18
  19. 19. • Таблица символов – это хэш www.mail.ru 19 Таблица символов • Ключи – глобальные переменные и подпрограммы • Значения - тайпглобы %PackageName:: %main::
  20. 20. www.mail.ru 20 Таблица символов package Test; our $data = 'test'; our @data = qw(1 2 3); our %data = (key1 => 'value1', key2 => 'value2'); sub data { return 0; } package main; say $Test::{$_} for keys %Test::; *Test::data my $fh = *FH;
  21. 21. *glob{PACKAGE} имя пакета *glob{NAME} имя элемента (переменной или функции) *glob{SCALAR} ссылка на значение-скаляр *glob{ARRAY} ссылка на значение-массив *glob{HASH} ссылка на значение-хэш *glob{CODE} ссылка на подпрограмму corp.mail.ru Структура тайпглоба
  22. 22. Получение данных my $scalar = ${ *Test::data }; my %hash = %{ *Test::data }; my @array = @{ *Test::data }; &{ *Test::data }(); Запись данных *Test::data = 'new value'; *Test::data = [4, 5, 6]; *Test::data = { key3 => 'value3', key4 => 'value4‘ }; *Test::data = sub { return 1; }; www.mail.ru 22 Работа с тайпглобом
  23. 23. • Какие-то проблемы? • Методы runtime- кодогенерации • Таблица символов: матчасть • От теории к практике • Как не выстрелить себе в ногу • RTFM 23
  24. 24. package MakeAccessor; sub import { my $package = caller(0); no strict 'refs'; *{"$package::has"} = &has; } sub has ($) { my $name = shift; my $package = caller(0); no strict 'refs'; *{"$package::$name"} = sub { my $self = shift; $self->{$name} = $_[0] if @_; return $self->{$name}; }; } www.mail.ru 24 Генерация аксессоров package Test; use MakeAccessor; has 'name'; has 'age'; sub new { return bless {}, shift; } package main; my $o = Test->new; $o->name('Ann'); say $o->name;
  25. 25. package MakeAccessor; sub import { my $package = caller(0); no strict 'refs'; *{"$package::has"} = &has; } sub has ($) { my $name = shift; my $package = caller(0); no strict 'refs'; *{"$package::$name"} = sub { my $self = shift; say ((caller(0))[3]); $self->{$name} = $_[0] if @_; return $self->{$name}; }; } www.mail.ru 25 Боремся с __ANON__ MakeAccessor::__ANON__
  26. 26. www.mail.ru 26 Боремся с __ANON__ package MakeAccessor; sub import { my $package = caller(0); no strict 'refs'; *{"$package::has"} = &has; } sub has ($) { my $name = shift; my $package = caller(0); my $method = sub { local *__ANON__ = "$package::$name"; my $self = shift; $self->{$name} = $_[0] if @_; return $self->{$name}; }; no strict 'refs'; *{"$package::$name"} = $method; } Test::name
  27. 27. • Генераторы классов: десериализация, ORM • Реализация паттерна «прокси» • Тестирование: mock, stub, fake object • Хуки для подпрограмм: before, after, around • Патчи во время выполнения • Расширение функционала сторонних модулей • Синонимы для устаревших функций при рефакторинге www.mail.ru 27 От теории к практике
  28. 28. package Response; use CGI; sub new { return bless { cgi => CGI->new }, shift; } our $AUTOLOAD; sub AUTOLOAD { my ($method) = $AUTOLOAD =~ /([^:]+)$/; return if $method eq 'DESTROY'; return unless CGI->can($method); my $sub = sub { local *__ANON__ = $AUTOLOAD; my $self = shift; return $self->{cgi}->$method(@_); }; { no strict 'refs'; *{$AUTOLOAD} = $sub; }; return $sub->(@_); } www.mail.ru 28 Прокси package main; my $obj = Response->new; print $obj->header('text/html'); Content-Type:text/html; charset=ISO-8859-1
  29. 29. package Wrapper; sub make_deprecated { my $deprecated = shift; { no strict 'refs'; return if *{$deprecated}{CODE}; }; my $package = scalar caller(0); my $method = (caller(1))[3]; my $func = sub { local *__ANON__ = $deprecated; warn "$deprecated called at " . sprintf("%s (%s)", (caller)[1, 2]) . " is deprecated. Use $package::$methodn"; eval "use $package;" unless $package->can('can'); my $sub = $package->can($method); $sub->(@_); }; no strict 'refs'; *{$deprecated} = $func; } package Test1; package Test2; sub new_func { Wrapper::make_deprecated( 'Test1::old_func'); return 'test'; } package main; say Test2::new_func(); say Test1::old_func(); www.mail.ru 29 Синонимы test Test1::old_func called at test12.pl (40) is deprecated. Use Test2::Test2::new_func test
  30. 30. use Test::More; my $user_data = { ... }; { no strict 'refs'; *{'Cache::Memcached::set'} = sub { return 1; }; *{'Cache::Memcached::get'} = sub { return to_json($user_data); }; }; is_deeply($user->get_info($session_id), $user_data, 'Some test...'); www.mail.ru 30 Stub
  31. 31. package Wrapper; sub before(@&) { my ($methods, $wrapper) = @_; my $package = caller(0); for my $method (@$methods) { my $orig = $package->can($method); my $sub = sub { local *__ANON__ = "$package::$method"; $wrapper->(@_); $orig->(@_); }; no strict 'refs'; *{"$package::$method"} = $sub; } } package Test; sub test { say 'test'; } Wrapper::before [ 'test' ], sub { say 'wrapper'; }; package main; Test::test(); www.mail.ru 31 Хуки wrapper test
  32. 32. • Какие-то проблемы? • Методы runtime- кодогенерации • Таблица символов: матчасть • От теории к практике • Как не выстрелить себе в ногу • RTFM 32
  33. 33. • Прагмы strict и warnings • __ANON__ в трассировке стэка • Ссылки на переопределяемые функции • Снижение читабельности кода и повышение требований к профессиональному уровню программистов • Рост стэка при использовании хуков • Пространство имен модуля www.mail.ru 33 Проблемы кодогенерации
  34. 34. use Data::Dumper; *{Data::Dumper::Dumper} = sub { return 'Hacked!'; }; say Dumper({key1 => 1, key2 => 2}); say Data::Dumper::Dumper({key1 => 1, key2 => 2}); www.mail.ru 34 Ссылки
  35. 35. package Wrapper; our $name = 'Ann'; *{Test::test} = sub { say $name; say $Test::name; }; package Test; our $name = 'Bob'; package main; Test::test(); www.mail.ru 35 Пространство имен
  36. 36. eval • Компиляция во время выполнения • Ускоренная загрузка, возможность компиляции по запросу • Создание символов в пространстве имен нужного модуля • Неэффективная генерация большого количества похожих функций Таблица символов • Компиляция при загрузке • Проверка синтаксиса компилятором при запуске • Высокая эффективность повторного использования генераторов • Невозможность создания символов в пространстве имен нужного модуля, если имя последнего не известно во время компиляции www.mail.ru 36
  37. 37. • perlmod: Symbol tables • perlref • perldata: Typeglobs and Filehandlers • Sriram Srinivasan.Advanced Perl Programming • Modern Perl (http://modernperlbooks.com) www.mail.ru 37 Что почитать
  38. 38. Шишкина Елена Владимировна e.shishkina@corp.mail.ru
  • DmitriyStolyarov

    Jul. 4, 2015
  • ssuser129a4e

    Jul. 4, 2015
  • bessarabov

    Sep. 6, 2013
  • _bor_

    Jul. 24, 2013
  • deniszh

    Jun. 8, 2013
  • lattenwald

    Jun. 6, 2013

Видео: http://video.mail.ru/corp/p.scherbinin/6/7.html Tаблица символов — это только небольшой шаг в мир внутреннего устройства Perl, но и он открывает программисту огромные возможности: — Runtime-кодогенерация. — Генерация по запросу. — Изменение кода сторонних модулей на лету и многое другое.

Views

Total views

6,933

On Slideshare

0

From embeds

0

Number of embeds

5,597

Actions

Downloads

8

Shares

0

Comments

0

Likes

6

×