﻿1
00:00:00,480 --> 00:00:03,920
Today we will carry on
with the previous session

2
00:00:04,080 --> 00:00:07,280
where I explained
that small methods were good.

3
00:00:07,440 --> 00:00:09,160
Today I'll show some examples.

4
00:00:09,320 --> 00:00:12,840
But first, let's quickly review
our previous session.

5
00:00:13,000 --> 00:00:15,280
Sending a message leads to a choice.

6
00:00:15,440 --> 00:00:19,640
A masked choice because several
possible implementations

7
00:00:19,800 --> 00:00:21,560
will be called up.

8
00:00:22,040 --> 00:00:25,960
And Pharo makes a choice
depending on the message receiver.

9
00:00:26,480 --> 00:00:30,360
Class hierarchy defines choices:
More classes = more choices.

10
00:00:30,600 --> 00:00:34,360
And you can easily add
new choices by creating subclasses.

11
00:00:35,760 --> 00:00:40,480
Subclasses can redefine or refine
the code of their superclass.

12
00:00:42,000 --> 00:00:43,920
And sending a message

13
00:00:44,080 --> 00:00:49,360
means giving subclasses
the possibility to change behavior.

14
00:00:50,520 --> 00:00:54,080
Today we'll look at
the Design Pattern template method.

15
00:00:54,240 --> 00:00:56,880
You'll find it
in the Design Pattern manual.

16
00:00:57,640 --> 00:00:59,960
What is a template method?

17
00:01:00,120 --> 00:01:04,600
It's a skeleton
that defines the overall behavior

18
00:01:04,760 --> 00:01:08,800
of an algorithm, for example,
with hooks inside.

19
00:01:08,960 --> 00:01:12,680
And these hooks can be
redefined by subclasses.

20
00:01:13,840 --> 00:01:16,000
This is an algorithm.

21
00:01:16,320 --> 00:01:19,320
It does something,
we don't exactly know what.

22
00:01:20,280 --> 00:01:25,320
Next, it does something
in hookMethod 1,

23
00:01:25,720 --> 00:01:27,080
then something else,

24
00:01:27,240 --> 00:01:29,480
and then something
in hookMethod2.

25
00:01:29,640 --> 00:01:34,200
Since hookMethods 1 and 2
are both complete methods,

26
00:01:34,360 --> 00:01:37,040
they can be redefined in the subclasses.

27
00:01:37,600 --> 00:01:41,320
There are 2 possibilities,
one each for hookMethod 1 and 2.

28
00:01:42,760 --> 00:01:46,520
These methods may or may not

29
00:01:46,680 --> 00:01:49,800
have a default behavior.

30
00:01:50,160 --> 00:01:53,840
Here, let's say that hookMethod 1
has a default behavior.

31
00:01:54,000 --> 00:01:57,160
This means that
if the subclass proposes nothing,

32
00:01:57,680 --> 00:02:03,000
hookMethod 1 has a default behavior
that functions.

33
00:02:04,240 --> 00:02:06,280
Likewise, we could say

34
00:02:06,440 --> 00:02:09,960
that hookMethod 2
does not have a default behavior.

35
00:02:10,120 --> 00:02:12,840
The subclass
must imperatively define one.

36
00:02:13,000 --> 00:02:15,960
As designer of the class,
you can choose

37
00:02:16,120 --> 00:02:19,840
whether or not
to determine a default behavior.

38
00:02:20,640 --> 00:02:23,760
We'll use printString
as a first example.

39
00:02:23,920 --> 00:02:27,640
The idea is that if I send
a printString message to an object,

40
00:02:27,800 --> 00:02:31,120
I get a string of characters
that represents this object.

41
00:02:31,280 --> 00:02:33,160
Here I have a delay.

42
00:02:34,400 --> 00:02:37,640
I've created a 10-second delay.

43
00:02:38,480 --> 00:02:42,960
If I send a printString message
to this delay,

44
00:02:43,120 --> 00:02:47,720
I get a delay and in parentheses,
a millisecond value for the delay.

45
00:02:48,200 --> 00:02:52,840
The printString method is implemented
in the object class like this.

46
00:02:53,600 --> 00:02:56,640
It sends the message
printStringLimitedTo

47
00:02:57,160 --> 00:02:58,560
This implementation

48
00:02:58,720 --> 00:03:02,920
recovers a string of characters
that represents

49
00:03:03,080 --> 00:03:04,880
the object.

50
00:03:05,040 --> 00:03:09,360
And if this string of characters
is too long,

51
00:03:10,200 --> 00:03:13,800
we can cut it off at a certain limit.

52
00:03:13,960 --> 00:03:17,400
Then at the end,
we concatenate with '...etc...'

53
00:03:17,560 --> 00:03:19,880
to say the string is not done.

54
00:03:20,640 --> 00:03:23,600
The important thing here

55
00:03:23,760 --> 00:03:28,120
is that printStringLimitedTo
sends a printOn message to self.

56
00:03:28,280 --> 00:03:29,880
This is the method

57
00:03:30,040 --> 00:03:33,400
that will or will not
be redefined in the subclasses.

58
00:03:34,040 --> 00:03:37,560
If I look at what printString returns

59
00:03:37,720 --> 00:03:40,120
for a Node and for an Apple,

60
00:03:40,280 --> 00:03:43,800
Node new returns a Node.

61
00:03:44,200 --> 00:03:48,440
This is the printString
of the Node class.

62
00:03:49,120 --> 00:03:53,240
And here in Apple, we have
the printString of the Apple class.

63
00:03:53,720 --> 00:03:57,000
We see that this behavior
and the default behavior

64
00:03:57,160 --> 00:03:59,920
are implemented in the class object.

65
00:04:00,080 --> 00:04:04,320
So the default behavior
of printString for any object whatsoever

66
00:04:04,680 --> 00:04:06,000
is one:

67
00:04:06,160 --> 00:04:10,000
Recover the class names.

68
00:04:10,160 --> 00:04:12,840
In this case, Node and Apple.

69
00:04:13,120 --> 00:04:16,720
And two, if the class name
begins with a vowel,

70
00:04:17,640 --> 00:04:19,760
we use the prefix "an".

71
00:04:19,920 --> 00:04:23,000
If it starts with a consonant,
we use the prefix "a".

72
00:04:23,160 --> 00:04:26,320
This is how we get
"a node" and "an apple".

73
00:04:27,880 --> 00:04:30,520
This is the default behavior.

74
00:04:31,120 --> 00:04:34,400
But it is possible to change
this default behavior

75
00:04:34,560 --> 00:04:36,280
by refining printOn.

76
00:04:36,720 --> 00:04:38,480
For a delay,

77
00:04:38,640 --> 00:04:41,560
we see that
the printString of a delay

78
00:04:41,720 --> 00:04:46,240
starts with
the default printOn return.

79
00:04:46,400 --> 00:04:47,640
That is "a Delay."

80
00:04:47,800 --> 00:04:52,720
But afterwards, we can add the delay
in milliseconds in parentheses.

81
00:04:52,880 --> 00:04:56,040
This is exactly what
the printOn method does.

82
00:04:56,880 --> 00:05:01,080
It starts by asking the superclass
for the default printString.

83
00:05:02,160 --> 00:05:05,240
Afterwards,
it opens a parentheses

84
00:05:05,560 --> 00:05:08,080
with a preset number of milliseconds,

85
00:05:08,880 --> 00:05:11,240
and then it closes the parentheses.

86
00:05:11,760 --> 00:05:14,720
We just looked at refinement.

87
00:05:15,040 --> 00:05:18,120
The delay class
refines the implementation

88
00:05:18,280 --> 00:05:21,520
of the printOn method
in the object class.

89
00:05:21,680 --> 00:05:25,200
But a class can also
completely redefine behavior.

90
00:05:25,680 --> 00:05:29,880
This is the case for booleans,
for example.

91
00:05:30,040 --> 00:05:31,760
If I display false,

92
00:05:31,920 --> 00:05:34,800
it will return false.

93
00:05:34,960 --> 00:05:37,240
We don't have "a false",

94
00:05:37,400 --> 00:05:39,120
simply "false".

95
00:05:39,280 --> 00:05:43,200
For this, we just send
the "false" string of characters

96
00:05:43,360 --> 00:05:45,680
in the printOn variables stream.

97
00:05:46,200 --> 00:05:48,080
That's a complete redefinition.

98
00:05:48,240 --> 00:05:51,640
Another example
of complete redefinition is intervals.

99
00:05:51,800 --> 00:05:54,120
An interval defines a set of values

100
00:05:54,280 --> 00:05:56,920
situated between
a minimum and maximum value.

101
00:05:57,680 --> 00:06:02,680
The interval 1 to 100 is displayed by:
(1 to: 100)

102
00:06:04,320 --> 00:06:07,600
The interval 1 to: 100 by: 3

103
00:06:07,840 --> 00:06:10,400
1, 4, and so on,

104
00:06:10,560 --> 00:06:14,720
is displayed in the same manner
with the additional "by".

105
00:06:15,680 --> 00:06:18,080
How is this implemented?

106
00:06:18,240 --> 00:06:22,640
The interval class
redefines the printOn method

107
00:06:23,120 --> 00:06:26,200
and sends different messages
to stream variables.

108
00:06:26,360 --> 00:06:28,600
We start by opening parentheses.

109
00:06:28,760 --> 00:06:31,240
The parentheses here and here.

110
00:06:31,600 --> 00:06:36,560
Then we display the initial value
or the first number of the interval,

111
00:06:36,720 --> 00:06:39,360
that is this "1" here,
and this "1" here.

112
00:06:39,680 --> 00:06:41,440
Then we write 'to:'.

113
00:06:44,600 --> 00:06:47,640
And we write the final value: "100",

114
00:06:48,520 --> 00:06:49,800
and "100".

115
00:06:50,000 --> 00:06:53,720
If there is a "by"
that is different from the default "1",

116
00:06:53,880 --> 00:06:56,800
we write the "a".

117
00:06:59,120 --> 00:07:02,320
And at the end,
we close the parentheses.

118
00:07:04,360 --> 00:07:07,000
We saw that printString

119
00:07:07,160 --> 00:07:11,000
uses the Design Pattern
template method so that classes

120
00:07:11,160 --> 00:07:15,120
can implement
their own textual representation.

121
00:07:15,360 --> 00:07:19,600
Now we'll look at another example,
which is object copy.

122
00:07:19,760 --> 00:07:21,120
What does copy do?

123
00:07:21,280 --> 00:07:25,960
It enables you to take an object
and create a code from it.

124
00:07:26,840 --> 00:07:29,680
Copying objects is complex.

125
00:07:30,880 --> 00:07:33,120
There can be different strategies.

126
00:07:33,280 --> 00:07:35,200
Each class can decide

127
00:07:35,360 --> 00:07:39,200
what the copy of its instances
should look like.

128
00:07:39,720 --> 00:07:43,400
There is a simple
template method solution

129
00:07:43,560 --> 00:07:46,520
that uses copy and postCopy.

130
00:07:46,880 --> 00:07:50,560
Copy is a template method
and postCopy is a hook.

131
00:07:51,360 --> 00:07:54,200
In the object class
there is a copy method.

132
00:07:54,800 --> 00:07:57,640
I'll let you read the commentary.

133
00:07:58,640 --> 00:08:02,920
In this method,
we send shallowCopy

134
00:08:03,080 --> 00:08:05,240
as a message to self,

135
00:08:05,400 --> 00:08:08,640
followed by postCopy
on the result.

136
00:08:08,920 --> 00:08:12,360
What does shallowCopy do?

137
00:08:12,520 --> 00:08:16,200
It creates a new object
that shares all instance variables

138
00:08:16,360 --> 00:08:17,960
with the base object.

139
00:08:18,200 --> 00:08:22,080
We have two objects and
their instance variables are the same.

140
00:08:22,240 --> 00:08:26,640
If I modify the instance variable
of one object, I modify the other too.

141
00:08:28,880 --> 00:08:32,320
That is the default behavior

142
00:08:34,320 --> 00:08:35,720
of shallowCopy.

143
00:08:35,880 --> 00:08:38,800
Depending on what postCopy does,

144
00:08:38,960 --> 00:08:41,400
variables will or will not be shared.

145
00:08:41,560 --> 00:08:44,240
If postCopy is empty,
all variables are shared.

146
00:08:44,400 --> 00:08:48,640
But the classes can decide
to put different things into postCopy

147
00:08:48,800 --> 00:08:52,440
in order to share certain variables
or nothing at all.

148
00:08:53,040 --> 00:08:55,680
The postCopy default setting
shares everything.

149
00:08:55,840 --> 00:08:59,240
It simply returns the current object.

150
00:09:00,440 --> 00:09:04,080
But we could also imagine
other applications for postCopy.

151
00:09:04,240 --> 00:09:06,680
For example, in the Bag class.

152
00:09:06,840 --> 00:09:09,600
Bag is a type of collection

153
00:09:09,840 --> 00:09:13,440
and its postCopy method
copies its contents.

154
00:09:14,640 --> 00:09:17,520
Thus, a Bag is
a contents instance variable,

155
00:09:17,680 --> 00:09:21,080
and the designers
of the Bag class decided that

156
00:09:21,240 --> 00:09:22,920
when you copy a Bag,

157
00:09:23,080 --> 00:09:26,000
you don't want to share
the contents variable,

158
00:09:26,160 --> 00:09:27,920
you want separate variables.

159
00:09:28,080 --> 00:09:31,960
They have the same initial value
but you can modify only one.

160
00:09:33,440 --> 00:09:34,720
Here the idea is:

161
00:09:34,880 --> 00:09:39,440
postCopy is a message sent to copy,
or the new object,

162
00:09:41,880 --> 00:09:45,080
which shares
all of the instance variables.

163
00:09:45,240 --> 00:09:47,200
If we don't want to share them,

164
00:09:47,360 --> 00:09:50,280
we create new ones
and decide upon their value.

165
00:09:50,760 --> 00:09:52,600
Here in my contents variable,

166
00:09:52,760 --> 00:09:55,120
I'll put a copy
of the initial contents.

167
00:09:55,280 --> 00:09:57,000
That way I don't share them.

168
00:09:57,160 --> 00:10:00,080
Each copy of my Bag
has its own contents.

169
00:10:00,600 --> 00:10:03,400
With the dictionary, we go even further.

170
00:10:03,560 --> 00:10:06,840
A dictionary is a collection
of key-value pairs,

171
00:10:07,000 --> 00:10:09,080
or a collection of associations.

172
00:10:09,240 --> 00:10:12,360
Not only do we want to copy
the collection...

173
00:10:12,520 --> 00:10:16,000
If we copy a dictionary,
we want to copy the collection,

174
00:10:16,160 --> 00:10:19,440
and each dictionary
has its own collection of pairs...

175
00:10:19,600 --> 00:10:21,960
But we also want each pair
to be different.

176
00:10:22,120 --> 00:10:26,520
So that if I modify one,
it won't modify the other side.

177
00:10:26,920 --> 00:10:30,640
To do this, I copy the table,
but I also copy

178
00:10:30,800 --> 00:10:32,400
each pair inside.

179
00:10:32,560 --> 00:10:34,720
This is what's going on here.

180
00:10:34,880 --> 00:10:38,640
To conclude, the Design Pattern
template method is very common.

181
00:10:39,040 --> 00:10:41,520
It's a sign of good design.

182
00:10:41,720 --> 00:10:45,880
If you do good object design,
you'll have lots of template methods.

183
00:10:46,040 --> 00:10:48,560
It's perfectly normal and a good thing.

184
00:10:49,080 --> 00:10:50,920
So don't hesitate to use them.

185
00:10:51,080 --> 00:10:56,040
This technique enables subclasses
to define behavior

186
00:10:56,200 --> 00:10:59,640
and partially modify
the behavior of the superclass.