﻿1
00:00:00,680 --> 00:00:01,800
Hello.

2
00:00:01,960 --> 00:00:04,640
Today we are going
to talk about messages.

3
00:00:04,800 --> 00:00:08,800
You'll see why having lots of messages
and small methods is good.

4
00:00:08,960 --> 00:00:11,520
Contrary to what
many developers believe.

5
00:00:12,640 --> 00:00:16,120
This slide illustrates
a design sequence.

6
00:00:16,640 --> 00:00:18,920
This is valid not only for Pharo,

7
00:00:19,080 --> 00:00:22,280
but for design
in any object-oriented language.

8
00:00:23,800 --> 00:00:27,240
As you know,
message sends are hooks,

9
00:00:27,400 --> 00:00:30,640
places where we can define behavior.

10
00:00:30,840 --> 00:00:35,680
Developers often say
that they like big methods because

11
00:00:35,840 --> 00:00:37,760
they're easy to understand.

12
00:00:37,920 --> 00:00:41,480
You read the lines
and you understand the code.

13
00:00:41,640 --> 00:00:44,320
But in this session I will show you

14
00:00:44,480 --> 00:00:46,720
that this is not such a good thing.

15
00:00:46,880 --> 00:00:50,080
In general,
big methods mean bad design.

16
00:00:51,280 --> 00:00:53,120
A hierarchy of classes

17
00:00:53,280 --> 00:00:56,280
and a same method
implemented in several classes,

18
00:00:56,440 --> 00:00:58,480
is one means of defining choices.

19
00:00:59,000 --> 00:01:02,960
If I take a fat class
with lots of operations,

20
00:01:03,120 --> 00:01:07,320
and I have to choose
an operation according to status,

21
00:01:07,480 --> 00:01:11,240
my code will say: "If I'm in this state,
I do this operation.

22
00:01:11,400 --> 00:01:13,960
"If I'm in that state,
I do that operation."

23
00:01:14,120 --> 00:01:16,680
You'll have big codes

24
00:01:16,840 --> 00:01:19,360
with IFs all over the place.

25
00:01:19,520 --> 00:01:22,520
This means that
when you want to add new cases,

26
00:01:22,680 --> 00:01:25,040
you have to modify methods everywhere.

27
00:01:25,400 --> 00:01:28,400
In the version on the right-hand side,

28
00:01:29,200 --> 00:01:33,880
the operation for each case
is divided into a specific class.

29
00:01:34,240 --> 00:01:38,040
All you have to do
is send an operation message

30
00:01:38,320 --> 00:01:41,280
to an object to create an IF.

31
00:01:41,440 --> 00:01:45,320
The IF does not need to be written
by the programmer.

32
00:01:46,640 --> 00:01:50,480
It's done automatically
via the polymorphism principle.

33
00:01:50,640 --> 00:01:55,920
In the following slides, I'll show you
how to improve one example

34
00:01:56,080 --> 00:01:58,120
by changing small bits at a time.

35
00:01:58,640 --> 00:02:01,760
Here is a big method
that is not easy to understand

36
00:02:01,920 --> 00:02:03,480
and which does many things.

37
00:02:03,640 --> 00:02:05,560
Here's what we want to do.

38
00:02:06,280 --> 00:02:07,640
In a subclass,

39
00:02:07,800 --> 00:02:11,840
we want to give this variable here
a different value.

40
00:02:12,800 --> 00:02:14,720
As it's set up,

41
00:02:14,880 --> 00:02:18,000
the only way to do that
is to create the subclass,

42
00:02:18,160 --> 00:02:20,920
then duplicate all of the code,

43
00:02:21,080 --> 00:02:24,080
adding the small modification
you want to make.

44
00:02:24,920 --> 00:02:27,480
In languages like Java

45
00:02:27,640 --> 00:02:29,160
that use private keywords,

46
00:02:29,320 --> 00:02:32,560
if the attributes
used by the method are private,

47
00:02:32,720 --> 00:02:34,760
what I just did is impossible.

48
00:02:35,000 --> 00:02:39,040
If the method uses
instance variables that are private,

49
00:02:39,200 --> 00:02:42,520
subclasses cannot duplicate code.

50
00:02:42,880 --> 00:02:46,960
But in any case,
duplicating is not good practice,

51
00:02:47,480 --> 00:02:50,120
because duplication copies bugs too.

52
00:02:50,280 --> 00:02:54,560
If I have a bug in my original version,
I'll have a bug in my copies.

53
00:02:55,800 --> 00:03:00,640
And if I modify one copy,
I have to modify every duplication.

54
00:03:01,520 --> 00:03:03,760
It's extra work for the developer

55
00:03:03,920 --> 00:03:07,200
and you must remember
that there are various copies.

56
00:03:08,760 --> 00:03:11,960
The real solution is sending messages.

57
00:03:12,320 --> 00:03:16,560
In a method, when you send a message
rather than writing

58
00:03:16,720 --> 00:03:20,160
the content of the
corresponding method directly inside,

59
00:03:20,320 --> 00:03:22,920
subclasses can override behavior.

60
00:03:24,160 --> 00:03:26,640
If we look at the bar method,

61
00:03:26,800 --> 00:03:28,680
it sends foo to self.

62
00:03:28,840 --> 00:03:30,960
In A, foo returns 10,

63
00:03:31,120 --> 00:03:33,880
but the subclasses
can override this value

64
00:03:34,040 --> 00:03:36,600
and replace it with 42, for example.

65
00:03:37,240 --> 00:03:40,720
So how can we improve
the code you just saw

66
00:03:40,880 --> 00:03:44,360
and benefit from
the inheritance mechanism

67
00:03:44,520 --> 00:03:46,320
without using duplication?

68
00:03:46,480 --> 00:03:50,520
I'm going to extract this part here
and send a message instead.

69
00:03:50,680 --> 00:03:54,200
It's done by a refactoring function
called extract method.

70
00:03:54,360 --> 00:03:58,080
You have tools to transform this code
into this code here.

71
00:03:59,200 --> 00:04:01,960
The code I selected
in the previous slide

72
00:04:02,120 --> 00:04:06,240
was transferred
into a new method called ratio.

73
00:04:07,800 --> 00:04:12,320
And here where the code was written,
we now have a message send.

74
00:04:13,240 --> 00:04:15,880
This means that in the subclasses,

75
00:04:17,000 --> 00:04:20,360
I can change this behavior.

76
00:04:20,520 --> 00:04:22,440
Either change it completely

77
00:04:22,600 --> 00:04:26,640
or recall the behavior of the superclass
and make a modification.

78
00:04:26,800 --> 00:04:28,560
That's what I'm doing here.

79
00:04:28,720 --> 00:04:30,720
I send a ratio message to super

80
00:04:30,880 --> 00:04:34,760
to execute the code as it is
in the superclass,

81
00:04:34,920 --> 00:04:37,720
and I add 10,
which is what my goal was.

82
00:04:39,880 --> 00:04:44,760
Another possible method
is to extract this part here,

83
00:04:44,920 --> 00:04:49,440
so that the subclasses
can change this behavior.

84
00:04:50,360 --> 00:04:53,160
I extract this piece of code

85
00:04:53,320 --> 00:04:55,640
into a specific method.

86
00:04:56,200 --> 00:04:59,440
And in the primary method,
I send a message.

87
00:05:02,120 --> 00:05:03,240
In this case,

88
00:05:03,480 --> 00:05:07,520
the class we want
an instance variable for is in hardcode.

89
00:05:07,680 --> 00:05:11,400
This means that if the subclasses
want to change this class,

90
00:05:11,560 --> 00:05:14,160
to potentially get a UINode subclass,

91
00:05:14,320 --> 00:05:17,280
it will have to duplicate
the entire method.

92
00:05:17,440 --> 00:05:19,600
Here we can use the same process

93
00:05:19,760 --> 00:05:23,440
and extract the class into a method,

94
00:05:23,600 --> 00:05:27,040
so that the subclasses
can change the instance variable.

95
00:05:27,200 --> 00:05:28,840
That's what I'm doing here.

96
00:05:29,000 --> 00:05:32,440
I extract the part that interests me
into a method,

97
00:05:34,720 --> 00:05:36,760
and I send a message.

98
00:05:36,920 --> 00:05:40,560
Sending a message enables the subclasses
to change behavior.

99
00:05:40,920 --> 00:05:43,760
Like I said earlier,
certain programmers

100
00:05:43,920 --> 00:05:46,440
do not agree with this approach.

101
00:05:47,120 --> 00:05:51,520
They find it difficult to read lots of
small, spread out methods.

102
00:05:51,680 --> 00:05:54,280
They'd rather read a big method
line by line.

103
00:05:54,440 --> 00:05:58,200
This isn't good practice,
because reading code line by line

104
00:05:58,360 --> 00:06:01,400
won't work
if the application is very big.

105
00:06:01,560 --> 00:06:05,640
You can't read line by line
and understand what's going on.

106
00:06:05,800 --> 00:06:10,440
This is where abstractions are useful
and extracting bits of behavior

107
00:06:10,600 --> 00:06:13,040
or expressions from methods
makes sense.

108
00:06:13,200 --> 00:06:17,320
You can read a method globally
without understanding every detail.

109
00:06:18,040 --> 00:06:21,520
So little methods are good,
you should use them everywhere.

110
00:06:22,400 --> 00:06:24,920
Let's carry on.

111
00:06:26,160 --> 00:06:30,240
Here we see that
the value 55 appears in hardcode

112
00:06:30,400 --> 00:06:31,800
in the method code.

113
00:06:31,960 --> 00:06:36,000
This means the subclasses
cannot change to 100, for example.

114
00:06:36,160 --> 00:06:40,480
So we will extract this value
like we did previously,

115
00:06:41,800 --> 00:06:46,600
and put it in a separate method so that
the subclasses can change the value.

116
00:06:47,440 --> 00:06:50,120
Another advantage is that previously

117
00:06:50,280 --> 00:06:52,520
the value 55 was written here.

118
00:06:52,680 --> 00:06:54,720
Now it's called self averageRatio.

119
00:06:54,880 --> 00:06:58,560
This means we replaced
a numerical value by a name,

120
00:06:58,720 --> 00:07:02,200
and I now know what
the value 55 corresponds to.

121
00:07:02,360 --> 00:07:07,440
I know it means averageRatio
and when I read the code, I understand.

122
00:07:07,600 --> 00:07:11,240
So having many small methods
helps to read the code.

123
00:07:11,680 --> 00:07:14,800
Creating an averageRatio method
to return 55

124
00:07:14,960 --> 00:07:17,720
enables all subclasses
to change values.

125
00:07:17,880 --> 00:07:21,640
But how can we let class users
change their value too?

126
00:07:22,000 --> 00:07:23,360
What we can do,

127
00:07:23,520 --> 00:07:25,840
is use an instance variable.

128
00:07:26,640 --> 00:07:30,600
The averageRatio method
used in the previous slide

129
00:07:30,760 --> 00:07:33,920
will return the value
of the instance variable,

130
00:07:34,080 --> 00:07:38,480
if it contains a value.
If not, it returns the default value.

131
00:07:38,800 --> 00:07:40,920
The default value was 55.

132
00:07:41,640 --> 00:07:45,120
And the users of a node object

133
00:07:45,280 --> 00:07:48,080
can program
whatever value they like inside.

134
00:07:48,240 --> 00:07:49,680
With this design,

135
00:07:49,840 --> 00:07:54,520
subclasses can override
the defaultAverageRatio

136
00:07:55,000 --> 00:07:56,320
and change the value.

137
00:07:56,480 --> 00:08:01,120
And class users can set a value
by executing the program.

138
00:08:01,640 --> 00:08:04,360
This is called
gruyere-oriented programming.

139
00:08:05,400 --> 00:08:09,440
An object-oriented program,
a WIN method,

140
00:08:09,600 --> 00:08:12,200
contains holes called hooks,

141
00:08:12,360 --> 00:08:15,960
which can be filled with subclasses.

142
00:08:16,800 --> 00:08:18,320
As a conclusion,

143
00:08:18,480 --> 00:08:22,280
code can be reused
and refined in subclasses.

144
00:08:22,440 --> 00:08:25,280
Each time we send a message,

145
00:08:25,440 --> 00:08:29,240
subclasses can change
the behavior of the superclass:

146
00:08:29,400 --> 00:08:31,600
Refine it or completely change it.

147
00:08:32,560 --> 00:08:37,760
Small methods are great because
they give names to bits of expressions,

148
00:08:38,080 --> 00:08:42,560
and because they give subclasses
the freedom to change behavior.