SlideShare a Scribd company logo
1 of 81
About the dangers of refactoring




        Andrei Pratasavitski
           May Perl + Perl Mova
               2012-05-12
Refactoring
Code refactoring is a "disciplined technique
for restructuring an existing body of code,
altering its internal structure without changing
its external behavior" [Martin Fowler in
http://refactoring.com/], undertaken in order to
improve some of the nonfunctional attributes
of the software.

                                         Wikipedia
Рефакторинг
Рефакторинг или рефакторирование (англ.
refactoring) — процесс изменения
внутренней структуры программы, не
затрагивающий её внешнего поведения и
имеющий целью облегчить понимание её
работы.


                                RU.Wikipedia
Рефакторинг
Рефакторинг (англ. refactoring) —
перетворення програмного коду, зміна
внутрішньої структури програмного
забезпечення для полегшення розуміння
коду і легшого внесення подальших змін
без зміни зовнішньої поведінки самої
системи.

                                 UA.Wikipedia
Refactoring
●   Restructuring an
    existing body of
    code
●   Non-functional
●   Without changing
    its external
    behavior
THE AXIOM




Developers DO love refactoring
Refactoring
●   Makes developers'
    lives easy and
    happy
●   Brighter
●   Creates an illusion
    of hardworking
    brains
●   And...
And refactoring...
●   ...does

    NOTHING

    for users
Refactoring




What they want to do...           What they do...
Why is Refactoring a dirty word?
●   Writing code is easier than reading it.
●   So, “refactoring” often means “rewriting”.
●   Understanding code requires reading it.
●   How can you rewrite code that you don't
    understand?
●   Probably not very well...
You can't refactor the world...
●   The world is often a
    messy place.
●   If code deals with the real
    word it probably will be
    messy too.
●   Refactoring can't make
    the world less complex or
    messy.
Refactoring gone wrong
●   People tend to delete what
    they don't understand in the
    misguided hope that “it was
    not used”.
●   They do it too early, and too
    often. Its not like voting!
●   They tend to over
    generalize and violate
    YAGNI.
Refactoring has risks...
●   You might... break something
●   ... refactor the code in such a way that the
    maintainer doesn't understand.
●   ... annoy your colleagues
●   … refactor something for the wrong priority
●   … make the code harder to maintain
●   … waste time by treading water
(Thanks to Yves Orton)
Developer Craft
(December 2011)
This is what business says
This is what business says
Because          ...and

business         developers

wants            want

results...       beauty!
This is what business says
               ...and

               developers

               want

               beauty!
This is what business says
Code WTF
Code WTF
Code WTF
Code WTF
WTF
Code WTF
WTF       ●   Watch
Code WTF
WTF       ●   Watch
          ●   Think
Code WTF
WTF       ●   Watch
          ●   Think
          ●   Figure out
Code WTF
WTF       ●   Watch
          ●   Think
          ●   Figure out



               Philippe (BooK) Bruhat
Code evil is...
Code evil is...
●   ...map in void context
●   ...goto
●   ...repeating code
●   ...using properties instead of accessors
●   ...to not use foreign keys
●   ...to do on Perl side what DB can do
Code evil is...
●   ...map in void context
●   ...goto
●   ...repeating code
●   ...using properties instead of accessors
●   ...to not use foreign keys
●   ...to do on Perl side what DB can do
                       Why?
Because...
●   ...it looks ugly!
●   ...it is hard to read!
●   ...it is a bad practice!
●   ...it will bring benefits in the future!
●   ...there is another way to do it!
●   ...it sucks!
●   ...I don't like it!
But how about...




  ...performance?
map in void context
map in void context
use Benchmark qw(cmpthese);
my @arr;

my $times = 1_000_000;

sub ss { $_[0] =~ s/1/a/; }

cmpthese(
    $times,
    {
        map1   =>   sub   {   @arr   =   1..100;   map s/1/a/, @arr; },
        map2   =>   sub   {   @arr   =   1..100;   map { s/1/a/ } @arr; },
        map3   =>   sub   {   @arr   =   1..100;   map &ss($_), @arr; },
        map4   =>   sub   {   @arr   =   1..100;   map { &ss($_) } @arr; },
        for1   =>   sub   {   @arr   =   1..100;   for (@arr) { s/1/a/ }; },
        for2   =>   sub   {   @arr   =   1..100;   s/1/a/ for @arr; },
        for3   =>   sub   {   @arr   =   1..100;   do { s/1/a/ } for @arr; },
        for4   =>   sub   {   @arr   =   1..100;   for (@arr) { &ss($_) }; },
        for5   =>   sub   {   @arr   =   1..100;   &ss($_) for @arr; },
        for6   =>   sub   {   @arr   =   1..100;   do { &ss($_) } for @arr; },
        for7   =>   sub   {   @arr   =   1..100;   do &ss($_) for @arr; },
    }
);
map in void context
use Benchmark qw(cmpthese);
my @arr;

my $times = 1_000_000;

sub ss { $_[0] =~ s/1/a/; }

cmpthese(
    $times,
    {
        map1   =>   sub   {   @arr   =   1..100;   map s/1/a/, @arr; },
        map2   =>   sub   {   @arr   =   1..100;   map { s/1/a/ } @arr; },
        map3   =>   sub   {   @arr   =   1..100;   map &ss($_), @arr; },
        map4   =>   sub   {   @arr   =   1..100;   map { &ss($_) } @arr; },
        for1   =>   sub   {   @arr   =   1..100;   for (@arr) { s/1/a/ }; },
        for2   =>   sub   {   @arr   =   1..100;   s/1/a/ for @arr; },
        for3   =>   sub   {   @arr   =   1..100;   do { s/1/a/ } for @arr; },
        for4   =>   sub   {   @arr   =   1..100;   for (@arr) { &ss($_) }; },
        for5   =>   sub   {   @arr   =   1..100;   &ss($_) for @arr; },
        for6   =>   sub   {   @arr   =   1..100;   do { &ss($_) } for @arr; },
        for7   =>   sub   {   @arr   =   1..100;   do &ss($_) for @arr; },
    }
);
map in void context
use Benchmark qw(cmpthese);
my @arr;

my $times = 1_000_000;

sub ss { $_[0] =~ s/1/a/; }

cmpthese(
    $times,
    {
        map1   =>   sub   {   @arr   =   1..100;   map s/1/a/, @arr; },
        map2   =>   sub   {   @arr   =   1..100;   map { s/1/a/ } @arr; },
        map3   =>   sub   {   @arr   =   1..100;   map &ss($_), @arr; },
        map4   =>   sub   {   @arr   =   1..100;   map { &ss($_) } @arr; },
        for1   =>   sub   {   @arr   =   1..100;   for (@arr) { s/1/a/ }; },
        for2   =>   sub   {   @arr   =   1..100;   s/1/a/ for @arr; },
        for3   =>   sub   {   @arr   =   1..100;   do { s/1/a/ } for @arr; },
        for4   =>   sub   {   @arr   =   1..100;   for (@arr) { &ss($_) }; },
        for5   =>   sub   {   @arr   =   1..100;   &ss($_) for @arr; },
        for6   =>   sub   {   @arr   =   1..100;   do { &ss($_) } for @arr; },
        for7   =>   sub   {   @arr   =   1..100;   do &ss($_) for @arr; },
    }
);
map in void context
use Benchmark qw(cmpthese);
my @arr;

my $times = 1_000_000;

sub ss { $_[0] =~ s/1/a/; }

cmpthese(
    $times,
    {
        map1   =>   sub   {   @arr   =   1..100;   map s/1/a/, @arr; },
        map2   =>   sub   {   @arr   =   1..100;   map { s/1/a/ } @arr; },
        map3   =>   sub   {   @arr   =   1..100;   map &ss($_), @arr; },
        map4   =>   sub   {   @arr   =   1..100;   map { &ss($_) } @arr; },
        for1   =>   sub   {   @arr   =   1..100;   for (@arr) { s/1/a/ }; },
        for2   =>   sub   {   @arr   =   1..100;   s/1/a/ for @arr; },
        for3   =>   sub   {   @arr   =   1..100;   do { s/1/a/ } for @arr; },
        for4   =>   sub   {   @arr   =   1..100;   for (@arr) { &ss($_) }; },
        for5   =>   sub   {   @arr   =   1..100;   &ss($_) for @arr; },
        for6   =>   sub   {   @arr   =   1..100;   do { &ss($_) } for @arr; },
        for7   =>   sub   {   @arr   =   1..100;   do &ss($_) for @arr; },
    }
);
Results

        for7   map4   map3   for6   map2   for4   for5   for3   for1   for2   map1
for7      --   -91%   -91%   -93%   -93%   -94%   -94%   -95%   -95%   -96%   -96%
map4    963%     --    -5%   -26%   -29%   -32%   -33%   -45%   -52%   -52%   -53%
map3   1022%     6%     --   -22%   -25%   -28%   -29%   -42%   -49%   -50%   -51%
for6   1338%    35%    28%     --    -4%    -8%    -9%   -26%   -35%   -36%   -37%
map2   1396%    41%    33%     4%     --    -4%    -5%   -23%   -32%   -33%   -34%
for4   1461%    47%    39%     9%     4%     --    -1%   -20%   -29%   -30%   -32%
for5   1476%    48%    40%    10%     5%     1%     --   -19%   -29%   -30%   -31%
for3   1844%    83%    73%    35%    30%    25%    23%     --   -12%   -13%   -15%
for1   2110%   108%    97%    54%    48%    42%    40%    14%     --    -1%    -3%
for2   2137%   110%    99%    56%    49%    43%    42%    15%     1%     --    -2%
map1   2181%   115%   103%    59%    52%    46%    45%    17%     3%     2%     --
Results

        for7   map4   map3   for6   map2   for4   for5   for3   for1   for2   map1
for7      --   -91%   -91%   -93%   -93%   -94%   -94%   -95%   -95%   -96%   -96%
map4    963%     --    -5%   -26%   -29%   -32%   -33%   -45%   -52%   -52%   -53%
map3   1022%     6%     --   -22%   -25%   -28%   -29%   -42%   -49%   -50%   -51%
for6   1338%    35%    28%     --    -4%    -8%    -9%   -26%   -35%   -36%   -37%
map2   1396%    41%    33%     4%     --    -4%    -5%   -23%   -32%   -33%   -34%
for4   1461%    47%    39%     9%     4%     --    -1%   -20%   -29%   -30%   -32%
for5   1476%    48%    40%    10%     5%     1%     --   -19%   -29%   -30%   -31%
for3   1844%    83%    73%    35%    30%    25%    23%     --   -12%   -13%   -15%
for1   2110%   108%    97%    54%    48%    42%    40%    14%     --    -1%    -3%
for2   2137%   110%    99%    56%    49%    43%    42%    15%     1%     --    -2%
map1   2181%   115%   103%    59%    52%    46%    45%    17%     3%     2%     --
Results

cmpthese(
    $times,
    {
        for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; },
        for2 => sub { @arr = 1..100; s/1/a/ for @arr; },
        map1 => sub { @arr = 1..100; map s/1/a/, @arr; },
    }
);

       for1 for2 map1
for1     -- -1% -4%
for2     1%   -- -3%
map1     4%   3%   --
Results

cmpthese(
    $times,
    {
        for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; },
        for2 => sub { @arr = 1..100; s/1/a/ for @arr; },
        map1 => sub { @arr = 1..100; map s/1/a/, @arr; },
    }
);

       for1 for2 map1
for1     -- -1% -4%
for2     1%   -- -3%
map1     4%   3%   --
map in void context


      ...is faster
map in void context


      ...is faster

        ...a bit
map in void context


      ...is faster

        ...a bit

     ...sometimes
map in void context

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Have a look at...

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Repeating code
Repeating code
my ($row, @rows)
my $tmp = $sth->fetchrow_hashref();
while ( $row = $sth->fetchrow_hashref() ) {
    if ( $row->{field} eq $tmp->{field} ) {
        push @rows, $row;
    }
    else {
        # do something with $tmp and @rows
        $tmp = $row;
    }
}
Repeating code
my ($row, @rows)
my $tmp = $sth->fetchrow_hashref();
while ( $row = $sth->fetchrow_hashref() ) {
    if ( $row->{field} eq $tmp->{field} ) {
        push @rows, $row;
    }
    else {
        # do something with $tmp and @rows
        $tmp = $row;
    }
}

# do something with $tmp and @rows
Repeating code
my ($row, @rows)
my $tmp = $sth->fetchrow_hashref();
while ( $row = $sth->fetchrow_hashref() ) {
    if ( $row->{field} eq $tmp->{field} ) {
        push @rows, $row;
    }
    else {
        &do_something($tmp, @rows);
        $tmp = $row;
    }
}

&do_something($tmp, @rows);
Repeating code

 1.   map1   |   2181%   |   map s/1/a/, @arr;
 2.   for2   |   2137%   |   s/1/a/ for @arr;
 3.   for1   |   2110%   |   for (@arr) { s/1/a/ };
 4.   for3   |   1844%   |   do { s/1/a/ } for @arr;
 5.   for5   |   1476%   |   &ss($_) for @arr;
 6.   for4   |   1461%   |   for (@arr) { &ss($_) };
 7.   map2   |   1396%   |   map { s/1/a/ } @arr;
 8.   for6   |   1338%   |   do { &ss($_) } for @arr;
 9.   map3   |   1022%   |   map &ss($_), @arr;
10.   map4   |    963%   |   map { &ss($_) } @arr;
11.   for7   |      0%   |   do &ss($_) for @arr;
Repeating code


  ...can be useful
Repeating code


              ...can be useful


...if you remember that method/function call
               is expensive
Properties instead of accessors
Properties instead of accessors




$request->stash(key => 'value');
Properties instead of accessors



my $stash = $request->stash();

$stash->{key} = 'value';
Properties instead of accessors



my $stash = $request->{stash};

$stash->{key} = 'value';
goto is evil?
goto is evil?




   Really?
goto is evil?

$ ack-grep -a '^s*gotos+' 
/usr/lib/perl/5.14/*.pm | wc -l
10
$ ack-grep -a '^s*gotos+' 
/usr/share/perl/5.14/*.pm | wc -l
29
goto is evil?


All those cases have

goto &somewhere;

   in AUTOLOAD
goto is evil?
goto is evil?




Yes, it's evil!
Do on Perl side what DB can do
Do on Perl side what DB can do
my @days = &days_from_period('2010-08-01', '2010-08-31');
# here @days = ('2010-08-01', '2010-08-01', '2010-08-01', ... '2010-08-31')

my %result = ();

my $sth = $dbh->prepare(<<'SQL');
SELECT SUM(amount) AS result
FROM Table t
    LEFT JOIN AnotherTable at USING(field)
    LEFT JOIN YetAnotherTable yat ON (...)
WHERE
    payday = ?
    AND (long_long_list_of_conditions)
SQL

for my $day (@days) {
    $sth->execute($day);
    $result{day} = $stf->fetchrow_arrayref()->[0] || 0;
}
# my @days = &days_from_period('2010-08-01', '2010-08-31');
# here @days = ('2010-08-01', '2010-08-01', '2010-08-01', ... '2010-08-31')

my %result = ();

# my $sth = $dbh->prepare(<<'SQL');
my $sql = <<'SQL';
SELECT
    payday,
    SUM(amount) AS result
FROM Table t
    LEFT JOIN AnotherTable at USING(field)
    LEFT JOIN YetAnotherTable yat ON (...)
WHERE
    payday BETWEEN ? AND ?
    AND (long_long_list_of_conditions)
GROUP BY payday
SQL

# for my $day (@days) {
#    $sth->execute($day);
#    $result{day} = $stf->fetchrow_arrayref()->[0] || 0;
    %result = $sth->selectall_hashref($sql, 'payday', undef,
                                      '2010-08-01', '2010-08-31');
# }
my %result = ();

my $sql = <<'SQL';
SELECT
    payday,
    SUM(amount) AS result
FROM Table t
    LEFT JOIN AnotherTable at USING(field)
    LEFT JOIN YetAnotherTable yat ON (...)
WHERE
    payday BETWEEN ? AND ?
    AND (long_long_list_of_conditions)
GROUP BY payday
SQL

%result = $sth->selectall_hashref($sql, 'payday', undef,
                                  '2010-08-01', '2010-08-31');
Do on Perl side what DB can do
Do on Perl side what DB can do

                                     SELECT
SELECT SUM(amount) AS result             payday,
FROM Table t                             SUM(amount) AS result
    LEFT JOIN AnotherTable at        FROM Table t
        USING(field)                     LEFT JOIN AnotherTable at
    LEFT JOIN YetAnotherTable yat            USING(field)
        ON (...)                         LEFT JOIN YetAnotherTable yat
WHERE                                        ON (...)
    payday = ?                       WHERE
    AND                                  payday BETWEEN ? AND ?
    (long_long_list_of_conditions)       AND
                                         (long_long_list_of_conditions)
                                     GROUP BY payday
Do on Perl side what DB can do
                                          X10 slower!
                                     SELECT
SELECT SUM(amount) AS result             payday,
FROM Table t                             SUM(amount) AS result
    LEFT JOIN AnotherTable at        FROM Table t
        USING(field)                     LEFT JOIN AnotherTable at
    LEFT JOIN YetAnotherTable yat            USING(field)
        ON (...)                         LEFT JOIN YetAnotherTable yat
WHERE                                        ON (...)
    payday = ?                       WHERE
    AND                                  payday BETWEEN ? AND ?
    (long_long_list_of_conditions)       AND
                                         (long_long_list_of_conditions)
                                     GROUP BY payday
I don't tell you
I don't tell you




“ Do NOT refactor! ”
I tell you




“ Do NOT refactor just because you can! ”
Think you!
Thank you!

More Related Content

Viewers also liked

B2B email list rental information - special offers
B2B email list rental information - special offersB2B email list rental information - special offers
B2B email list rental information - special offersAzam Marketing
 
The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...
The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...
The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...Azam Marketing
 
Volgodonsk gorod-buduschego
Volgodonsk gorod-buduschegoVolgodonsk gorod-buduschego
Volgodonsk gorod-buduschegoOmsk State Univ
 
Создание национальной системы реабилитации наркозависимых
Создание национальной системы реабилитации наркозависимыхСоздание национальной системы реабилитации наркозависимых
Создание национальной системы реабилитации наркозависимыхOmsk State Univ
 

Viewers also liked (6)

B2B email list rental information - special offers
B2B email list rental information - special offersB2B email list rental information - special offers
B2B email list rental information - special offers
 
Perl Vs. Java
Perl Vs. JavaPerl Vs. Java
Perl Vs. Java
 
The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...
The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...
The Affiliate Sales Kit - Writing Killer Proposals and Selling Yourself to Me...
 
Gdb 1-concept
Gdb 1-conceptGdb 1-concept
Gdb 1-concept
 
Volgodonsk gorod-buduschego
Volgodonsk gorod-buduschegoVolgodonsk gorod-buduschego
Volgodonsk gorod-buduschego
 
Создание национальной системы реабилитации наркозависимых
Создание национальной системы реабилитации наркозависимыхСоздание национальной системы реабилитации наркозависимых
Создание национальной системы реабилитации наркозависимых
 

Similar to About the dangers of refactoring

Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In PerlKang-min Liu
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tourSimon Proctor
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tourSimon Proctor
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2ady36
 
Writing Maintainable Perl
Writing Maintainable PerlWriting Maintainable Perl
Writing Maintainable Perltinypigdotcom
 
Functional Pe(a)rls version 2
Functional Pe(a)rls version 2Functional Pe(a)rls version 2
Functional Pe(a)rls version 2osfameron
 
LAMP_TRAINING_SESSION_6
LAMP_TRAINING_SESSION_6LAMP_TRAINING_SESSION_6
LAMP_TRAINING_SESSION_6umapst
 
Functional Pearls 4 (YAPC::EU::2009 remix)
Functional Pearls 4 (YAPC::EU::2009 remix)Functional Pearls 4 (YAPC::EU::2009 remix)
Functional Pearls 4 (YAPC::EU::2009 remix)osfameron
 
Dealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter ScottDealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter ScottO'Reilly Media
 
perl usage at database applications
perl usage at database applicationsperl usage at database applications
perl usage at database applicationsJoe Jiang
 
There's more than one way to empty it
There's more than one way to empty itThere's more than one way to empty it
There's more than one way to empty itAndrew Shitov
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongersbrian d foy
 
PERL for QA - Important Commands and applications
PERL for QA - Important Commands and applicationsPERL for QA - Important Commands and applications
PERL for QA - Important Commands and applicationsSunil Kumar Gunasekaran
 
Benchmarking Perl (Chicago UniForum 2006)
Benchmarking Perl (Chicago UniForum 2006)Benchmarking Perl (Chicago UniForum 2006)
Benchmarking Perl (Chicago UniForum 2006)brian d foy
 
[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And PortKeiichi Daiba
 
Erlang with Regexp Perl And Port
Erlang with Regexp Perl And PortErlang with Regexp Perl And Port
Erlang with Regexp Perl And PortKeiichi Daiba
 

Similar to About the dangers of refactoring (20)

Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In Perl
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tour
 
Perl6 a whistle stop tour
Perl6 a whistle stop tourPerl6 a whistle stop tour
Perl6 a whistle stop tour
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
 
Nop2
Nop2Nop2
Nop2
 
Writing Maintainable Perl
Writing Maintainable PerlWriting Maintainable Perl
Writing Maintainable Perl
 
Php2
Php2Php2
Php2
 
Perl Presentation
Perl PresentationPerl Presentation
Perl Presentation
 
Functional Pe(a)rls version 2
Functional Pe(a)rls version 2Functional Pe(a)rls version 2
Functional Pe(a)rls version 2
 
LAMP_TRAINING_SESSION_6
LAMP_TRAINING_SESSION_6LAMP_TRAINING_SESSION_6
LAMP_TRAINING_SESSION_6
 
Functional Pearls 4 (YAPC::EU::2009 remix)
Functional Pearls 4 (YAPC::EU::2009 remix)Functional Pearls 4 (YAPC::EU::2009 remix)
Functional Pearls 4 (YAPC::EU::2009 remix)
 
Dealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter ScottDealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter Scott
 
perl usage at database applications
perl usage at database applicationsperl usage at database applications
perl usage at database applications
 
There's more than one way to empty it
There's more than one way to empty itThere's more than one way to empty it
There's more than one way to empty it
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongers
 
PERL for QA - Important Commands and applications
PERL for QA - Important Commands and applicationsPERL for QA - Important Commands and applications
PERL for QA - Important Commands and applications
 
Benchmarking Perl (Chicago UniForum 2006)
Benchmarking Perl (Chicago UniForum 2006)Benchmarking Perl (Chicago UniForum 2006)
Benchmarking Perl (Chicago UniForum 2006)
 
Method::Signatures
Method::SignaturesMethod::Signatures
Method::Signatures
 
[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port
 
Erlang with Regexp Perl And Port
Erlang with Regexp Perl And PortErlang with Regexp Perl And Port
Erlang with Regexp Perl And Port
 

Recently uploaded

Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 

About the dangers of refactoring

  • 1. About the dangers of refactoring Andrei Pratasavitski May Perl + Perl Mova 2012-05-12
  • 2. Refactoring Code refactoring is a "disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior" [Martin Fowler in http://refactoring.com/], undertaken in order to improve some of the nonfunctional attributes of the software. Wikipedia
  • 3. Рефакторинг Рефакторинг или рефакторирование (англ. refactoring) — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы. RU.Wikipedia
  • 4. Рефакторинг Рефакторинг (англ. refactoring) — перетворення програмного коду, зміна внутрішньої структури програмного забезпечення для полегшення розуміння коду і легшого внесення подальших змін без зміни зовнішньої поведінки самої системи. UA.Wikipedia
  • 5. Refactoring ● Restructuring an existing body of code ● Non-functional ● Without changing its external behavior
  • 6. THE AXIOM Developers DO love refactoring
  • 7. Refactoring ● Makes developers' lives easy and happy ● Brighter ● Creates an illusion of hardworking brains ● And...
  • 8. And refactoring... ● ...does NOTHING for users
  • 9. Refactoring What they want to do... What they do...
  • 10. Why is Refactoring a dirty word? ● Writing code is easier than reading it. ● So, “refactoring” often means “rewriting”. ● Understanding code requires reading it. ● How can you rewrite code that you don't understand? ● Probably not very well...
  • 11. You can't refactor the world... ● The world is often a messy place. ● If code deals with the real word it probably will be messy too. ● Refactoring can't make the world less complex or messy.
  • 12. Refactoring gone wrong ● People tend to delete what they don't understand in the misguided hope that “it was not used”. ● They do it too early, and too often. Its not like voting! ● They tend to over generalize and violate YAGNI.
  • 13. Refactoring has risks... ● You might... break something ● ... refactor the code in such a way that the maintainer doesn't understand. ● ... annoy your colleagues ● … refactor something for the wrong priority ● … make the code harder to maintain ● … waste time by treading water
  • 14. (Thanks to Yves Orton) Developer Craft (December 2011)
  • 15. This is what business says
  • 16. This is what business says Because ...and business developers wants want results... beauty!
  • 17. This is what business says ...and developers want beauty!
  • 18. This is what business says
  • 23. Code WTF WTF ● Watch
  • 24. Code WTF WTF ● Watch ● Think
  • 25. Code WTF WTF ● Watch ● Think ● Figure out
  • 26. Code WTF WTF ● Watch ● Think ● Figure out Philippe (BooK) Bruhat
  • 28. Code evil is... ● ...map in void context ● ...goto ● ...repeating code ● ...using properties instead of accessors ● ...to not use foreign keys ● ...to do on Perl side what DB can do
  • 29. Code evil is... ● ...map in void context ● ...goto ● ...repeating code ● ...using properties instead of accessors ● ...to not use foreign keys ● ...to do on Perl side what DB can do Why?
  • 30. Because... ● ...it looks ugly! ● ...it is hard to read! ● ...it is a bad practice! ● ...it will bring benefits in the future! ● ...there is another way to do it! ● ...it sucks! ● ...I don't like it!
  • 31. But how about... ...performance?
  • 32. map in void context
  • 33. map in void context use Benchmark qw(cmpthese); my @arr; my $times = 1_000_000; sub ss { $_[0] =~ s/1/a/; } cmpthese( $times, { map1 => sub { @arr = 1..100; map s/1/a/, @arr; }, map2 => sub { @arr = 1..100; map { s/1/a/ } @arr; }, map3 => sub { @arr = 1..100; map &ss($_), @arr; }, map4 => sub { @arr = 1..100; map { &ss($_) } @arr; }, for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; }, for2 => sub { @arr = 1..100; s/1/a/ for @arr; }, for3 => sub { @arr = 1..100; do { s/1/a/ } for @arr; }, for4 => sub { @arr = 1..100; for (@arr) { &ss($_) }; }, for5 => sub { @arr = 1..100; &ss($_) for @arr; }, for6 => sub { @arr = 1..100; do { &ss($_) } for @arr; }, for7 => sub { @arr = 1..100; do &ss($_) for @arr; }, } );
  • 34. map in void context use Benchmark qw(cmpthese); my @arr; my $times = 1_000_000; sub ss { $_[0] =~ s/1/a/; } cmpthese( $times, { map1 => sub { @arr = 1..100; map s/1/a/, @arr; }, map2 => sub { @arr = 1..100; map { s/1/a/ } @arr; }, map3 => sub { @arr = 1..100; map &ss($_), @arr; }, map4 => sub { @arr = 1..100; map { &ss($_) } @arr; }, for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; }, for2 => sub { @arr = 1..100; s/1/a/ for @arr; }, for3 => sub { @arr = 1..100; do { s/1/a/ } for @arr; }, for4 => sub { @arr = 1..100; for (@arr) { &ss($_) }; }, for5 => sub { @arr = 1..100; &ss($_) for @arr; }, for6 => sub { @arr = 1..100; do { &ss($_) } for @arr; }, for7 => sub { @arr = 1..100; do &ss($_) for @arr; }, } );
  • 35. map in void context use Benchmark qw(cmpthese); my @arr; my $times = 1_000_000; sub ss { $_[0] =~ s/1/a/; } cmpthese( $times, { map1 => sub { @arr = 1..100; map s/1/a/, @arr; }, map2 => sub { @arr = 1..100; map { s/1/a/ } @arr; }, map3 => sub { @arr = 1..100; map &ss($_), @arr; }, map4 => sub { @arr = 1..100; map { &ss($_) } @arr; }, for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; }, for2 => sub { @arr = 1..100; s/1/a/ for @arr; }, for3 => sub { @arr = 1..100; do { s/1/a/ } for @arr; }, for4 => sub { @arr = 1..100; for (@arr) { &ss($_) }; }, for5 => sub { @arr = 1..100; &ss($_) for @arr; }, for6 => sub { @arr = 1..100; do { &ss($_) } for @arr; }, for7 => sub { @arr = 1..100; do &ss($_) for @arr; }, } );
  • 36. map in void context use Benchmark qw(cmpthese); my @arr; my $times = 1_000_000; sub ss { $_[0] =~ s/1/a/; } cmpthese( $times, { map1 => sub { @arr = 1..100; map s/1/a/, @arr; }, map2 => sub { @arr = 1..100; map { s/1/a/ } @arr; }, map3 => sub { @arr = 1..100; map &ss($_), @arr; }, map4 => sub { @arr = 1..100; map { &ss($_) } @arr; }, for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; }, for2 => sub { @arr = 1..100; s/1/a/ for @arr; }, for3 => sub { @arr = 1..100; do { s/1/a/ } for @arr; }, for4 => sub { @arr = 1..100; for (@arr) { &ss($_) }; }, for5 => sub { @arr = 1..100; &ss($_) for @arr; }, for6 => sub { @arr = 1..100; do { &ss($_) } for @arr; }, for7 => sub { @arr = 1..100; do &ss($_) for @arr; }, } );
  • 37. Results for7 map4 map3 for6 map2 for4 for5 for3 for1 for2 map1 for7 -- -91% -91% -93% -93% -94% -94% -95% -95% -96% -96% map4 963% -- -5% -26% -29% -32% -33% -45% -52% -52% -53% map3 1022% 6% -- -22% -25% -28% -29% -42% -49% -50% -51% for6 1338% 35% 28% -- -4% -8% -9% -26% -35% -36% -37% map2 1396% 41% 33% 4% -- -4% -5% -23% -32% -33% -34% for4 1461% 47% 39% 9% 4% -- -1% -20% -29% -30% -32% for5 1476% 48% 40% 10% 5% 1% -- -19% -29% -30% -31% for3 1844% 83% 73% 35% 30% 25% 23% -- -12% -13% -15% for1 2110% 108% 97% 54% 48% 42% 40% 14% -- -1% -3% for2 2137% 110% 99% 56% 49% 43% 42% 15% 1% -- -2% map1 2181% 115% 103% 59% 52% 46% 45% 17% 3% 2% --
  • 38. Results for7 map4 map3 for6 map2 for4 for5 for3 for1 for2 map1 for7 -- -91% -91% -93% -93% -94% -94% -95% -95% -96% -96% map4 963% -- -5% -26% -29% -32% -33% -45% -52% -52% -53% map3 1022% 6% -- -22% -25% -28% -29% -42% -49% -50% -51% for6 1338% 35% 28% -- -4% -8% -9% -26% -35% -36% -37% map2 1396% 41% 33% 4% -- -4% -5% -23% -32% -33% -34% for4 1461% 47% 39% 9% 4% -- -1% -20% -29% -30% -32% for5 1476% 48% 40% 10% 5% 1% -- -19% -29% -30% -31% for3 1844% 83% 73% 35% 30% 25% 23% -- -12% -13% -15% for1 2110% 108% 97% 54% 48% 42% 40% 14% -- -1% -3% for2 2137% 110% 99% 56% 49% 43% 42% 15% 1% -- -2% map1 2181% 115% 103% 59% 52% 46% 45% 17% 3% 2% --
  • 39. Results cmpthese( $times, { for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; }, for2 => sub { @arr = 1..100; s/1/a/ for @arr; }, map1 => sub { @arr = 1..100; map s/1/a/, @arr; }, } ); for1 for2 map1 for1 -- -1% -4% for2 1% -- -3% map1 4% 3% --
  • 40. Results cmpthese( $times, { for1 => sub { @arr = 1..100; for (@arr) { s/1/a/ }; }, for2 => sub { @arr = 1..100; s/1/a/ for @arr; }, map1 => sub { @arr = 1..100; map s/1/a/, @arr; }, } ); for1 for2 map1 for1 -- -1% -4% for2 1% -- -3% map1 4% 3% --
  • 41. map in void context ...is faster
  • 42. map in void context ...is faster ...a bit
  • 43. map in void context ...is faster ...a bit ...sometimes
  • 44. map in void context 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 45. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 46. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 47. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 48. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 49. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 50. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 51. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 52. Have a look at... 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 54. Repeating code my ($row, @rows) my $tmp = $sth->fetchrow_hashref(); while ( $row = $sth->fetchrow_hashref() ) { if ( $row->{field} eq $tmp->{field} ) { push @rows, $row; } else { # do something with $tmp and @rows $tmp = $row; } }
  • 55. Repeating code my ($row, @rows) my $tmp = $sth->fetchrow_hashref(); while ( $row = $sth->fetchrow_hashref() ) { if ( $row->{field} eq $tmp->{field} ) { push @rows, $row; } else { # do something with $tmp and @rows $tmp = $row; } } # do something with $tmp and @rows
  • 56. Repeating code my ($row, @rows) my $tmp = $sth->fetchrow_hashref(); while ( $row = $sth->fetchrow_hashref() ) { if ( $row->{field} eq $tmp->{field} ) { push @rows, $row; } else { &do_something($tmp, @rows); $tmp = $row; } } &do_something($tmp, @rows);
  • 57. Repeating code 1. map1 | 2181% | map s/1/a/, @arr; 2. for2 | 2137% | s/1/a/ for @arr; 3. for1 | 2110% | for (@arr) { s/1/a/ }; 4. for3 | 1844% | do { s/1/a/ } for @arr; 5. for5 | 1476% | &ss($_) for @arr; 6. for4 | 1461% | for (@arr) { &ss($_) }; 7. map2 | 1396% | map { s/1/a/ } @arr; 8. for6 | 1338% | do { &ss($_) } for @arr; 9. map3 | 1022% | map &ss($_), @arr; 10. map4 | 963% | map { &ss($_) } @arr; 11. for7 | 0% | do &ss($_) for @arr;
  • 58. Repeating code ...can be useful
  • 59. Repeating code ...can be useful ...if you remember that method/function call is expensive
  • 61. Properties instead of accessors $request->stash(key => 'value');
  • 62. Properties instead of accessors my $stash = $request->stash(); $stash->{key} = 'value';
  • 63. Properties instead of accessors my $stash = $request->{stash}; $stash->{key} = 'value';
  • 65. goto is evil? Really?
  • 66. goto is evil? $ ack-grep -a '^s*gotos+' /usr/lib/perl/5.14/*.pm | wc -l 10 $ ack-grep -a '^s*gotos+' /usr/share/perl/5.14/*.pm | wc -l 29
  • 67. goto is evil? All those cases have goto &somewhere; in AUTOLOAD
  • 69. goto is evil? Yes, it's evil!
  • 70. Do on Perl side what DB can do
  • 71. Do on Perl side what DB can do my @days = &days_from_period('2010-08-01', '2010-08-31'); # here @days = ('2010-08-01', '2010-08-01', '2010-08-01', ... '2010-08-31') my %result = (); my $sth = $dbh->prepare(<<'SQL'); SELECT SUM(amount) AS result FROM Table t LEFT JOIN AnotherTable at USING(field) LEFT JOIN YetAnotherTable yat ON (...) WHERE payday = ? AND (long_long_list_of_conditions) SQL for my $day (@days) { $sth->execute($day); $result{day} = $stf->fetchrow_arrayref()->[0] || 0; }
  • 72. # my @days = &days_from_period('2010-08-01', '2010-08-31'); # here @days = ('2010-08-01', '2010-08-01', '2010-08-01', ... '2010-08-31') my %result = (); # my $sth = $dbh->prepare(<<'SQL'); my $sql = <<'SQL'; SELECT payday, SUM(amount) AS result FROM Table t LEFT JOIN AnotherTable at USING(field) LEFT JOIN YetAnotherTable yat ON (...) WHERE payday BETWEEN ? AND ? AND (long_long_list_of_conditions) GROUP BY payday SQL # for my $day (@days) { # $sth->execute($day); # $result{day} = $stf->fetchrow_arrayref()->[0] || 0; %result = $sth->selectall_hashref($sql, 'payday', undef, '2010-08-01', '2010-08-31'); # }
  • 73. my %result = (); my $sql = <<'SQL'; SELECT payday, SUM(amount) AS result FROM Table t LEFT JOIN AnotherTable at USING(field) LEFT JOIN YetAnotherTable yat ON (...) WHERE payday BETWEEN ? AND ? AND (long_long_list_of_conditions) GROUP BY payday SQL %result = $sth->selectall_hashref($sql, 'payday', undef, '2010-08-01', '2010-08-31');
  • 74. Do on Perl side what DB can do
  • 75. Do on Perl side what DB can do SELECT SELECT SUM(amount) AS result payday, FROM Table t SUM(amount) AS result LEFT JOIN AnotherTable at FROM Table t USING(field) LEFT JOIN AnotherTable at LEFT JOIN YetAnotherTable yat USING(field) ON (...) LEFT JOIN YetAnotherTable yat WHERE ON (...) payday = ? WHERE AND payday BETWEEN ? AND ? (long_long_list_of_conditions) AND (long_long_list_of_conditions) GROUP BY payday
  • 76. Do on Perl side what DB can do X10 slower! SELECT SELECT SUM(amount) AS result payday, FROM Table t SUM(amount) AS result LEFT JOIN AnotherTable at FROM Table t USING(field) LEFT JOIN AnotherTable at LEFT JOIN YetAnotherTable yat USING(field) ON (...) LEFT JOIN YetAnotherTable yat WHERE ON (...) payday = ? WHERE AND payday BETWEEN ? AND ? (long_long_list_of_conditions) AND (long_long_list_of_conditions) GROUP BY payday
  • 78. I don't tell you “ Do NOT refactor! ”
  • 79. I tell you “ Do NOT refactor just because you can! ”