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
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
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!
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);
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');
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