1
00:00:00,840 --> 00:00:02,090
My name is Ashish Mahabal, and

2
00:00:02,090 --> 00:00:04,900
we'll be continuing with the best
programming practices module.

3
00:00:04,900 --> 00:00:06,280
This will be part III of it.

4
00:00:07,530 --> 00:00:11,370
So we'll be looking at some different
aspects of programming in this.

5
00:00:11,370 --> 00:00:15,910
How a program, in a program you
should try avoiding duplication.

6
00:00:15,910 --> 00:00:19,400
How various subroutines of a program
should be orthogonal in nature, and

7
00:00:19,400 --> 00:00:21,350
especially, how you go ahead and

8
00:00:21,350 --> 00:00:25,450
try to do refactoring of the program so
it becomes more efficient.

9
00:00:26,840 --> 00:00:31,380
So, I will try to duplicate myself a lot
while talking, telling you how important

10
00:00:31,380 --> 00:00:35,340
it is not to do duplication, but that
specifically applies to your programs.

11
00:00:35,340 --> 00:00:37,220
So don't repeat yourself.

12
00:00:37,220 --> 00:00:41,880
In a program, you should have
functions that do separate things,

13
00:00:41,880 --> 00:00:43,530
that are orthogonal from each other.

14
00:00:43,530 --> 00:00:47,280
If you have two functions that
seem to be doing similar things,

15
00:00:47,280 --> 00:00:50,080
that's definitely a case of duplication.

16
00:00:50,080 --> 00:00:53,770
And what you should try to do is
isolate the part that's common to both,

17
00:00:53,770 --> 00:00:57,220
put it in a third function and
make the other two functions call them.

18
00:00:57,220 --> 00:00:58,920
That way, your functions and

19
00:00:58,920 --> 00:01:02,750
your programs will become modular,
and they can be more reusable.

20
00:01:02,750 --> 00:01:05,250
And that can be helped by
being a bit impatient.

21
00:01:05,250 --> 00:01:07,630
Don't try to write the same
piece of code again and

22
00:01:07,630 --> 00:01:09,730
again, if there's a slight variation.

23
00:01:09,730 --> 00:01:11,665
Try to reuse the code that you have.

24
00:01:11,665 --> 00:01:15,850
That'll also stop you from reinventing
things that have already existed.

25
00:01:15,850 --> 00:01:20,200
So, many people have written all kinds
of modules for this good languages have

26
00:01:20,200 --> 00:01:23,950
been developed, so try to use as
much of that as well as possible.

27
00:01:23,950 --> 00:01:27,860
So, there are cheat sheets
that are available.

28
00:01:27,860 --> 00:01:31,450
Those indicate various short
cuts that are possible,

29
00:01:31,450 --> 00:01:36,180
various fast things that you can
do by using built in modules.

30
00:01:36,180 --> 00:01:38,600
So, you should try to master
them as much as possible.

31
00:01:38,600 --> 00:01:40,780
So, try to look at the cheat sheets.

32
00:01:40,780 --> 00:01:44,120
To take an example of Python, you can
visit what is called the cheese-shop

33
00:01:44,120 --> 00:01:47,900
there, which has lot's and
lot's of resources available, telling you

34
00:01:47,900 --> 00:01:52,450
what are the things that you can use
without having to rewrite them yourself.

35
00:01:52,450 --> 00:01:55,490
Similarly, there is a website called
hitchhiker's guide to Python.

36
00:01:55,490 --> 00:01:56,570
Take a look at that.

37
00:01:56,570 --> 00:02:00,640
And for all other languages
you'll find similar websites.

38
00:02:00,640 --> 00:02:04,200
We'll have some of those listed in
the additional resources that go

39
00:02:04,200 --> 00:02:05,552
with this module.

40
00:02:06,570 --> 00:02:08,520
So, what does one mean by orthogonality?

41
00:02:09,920 --> 00:02:13,370
What it means is that each of
your subroutines should try to do

42
00:02:13,370 --> 00:02:15,790
something that is distinct
from other subroutines.

43
00:02:15,790 --> 00:02:18,760
That they should not be
overdependent on each of them.

44
00:02:18,760 --> 00:02:22,440
You may be able to call one
subroutine from another, but

45
00:02:22,440 --> 00:02:25,520
you should not try duplicate what
the first one is doing in any case.

46
00:02:25,520 --> 00:02:29,780
Especially if you have subroutine
a dependent on subroutine b and

47
00:02:29,780 --> 00:02:33,990
subroutine b dependent on subroutine a,
that is definitely not a good idea.

48
00:02:33,990 --> 00:02:37,490
That will lead to chaos,
sooner rather than later.

49
00:02:37,490 --> 00:02:41,920
So, when you have functions or
sub routines that are orthogonal,

50
00:02:41,920 --> 00:02:44,590
what that also means is that
the changes are going to be localized.

51
00:02:45,630 --> 00:02:48,800
If you need to make
a particular change somewhere,

52
00:02:48,800 --> 00:02:50,670
you'll have to make it only in one place.

53
00:02:50,670 --> 00:02:53,710
On the other hand, if you have many
functions that look like each other,

54
00:02:53,710 --> 00:02:56,550
that do things that are similar, and

55
00:02:56,550 --> 00:02:58,810
then you discover that you
need to change something.

56
00:02:58,810 --> 00:03:01,060
You may need to change it
in all of those places.

57
00:03:01,060 --> 00:03:05,230
And that's definitely not a good thing,
because again, you may forget one of

58
00:03:05,230 --> 00:03:09,950
those and then much later, you or
someone else will discover that bug.

59
00:03:09,950 --> 00:03:14,160
Similarly, when specific
functions do only specific things,

60
00:03:14,160 --> 00:03:16,655
then unit testing becomes much easier.

61
00:03:16,655 --> 00:03:21,050
We can write tests in a more straight
forward way testing just that aspect of

62
00:03:21,050 --> 00:03:21,800
that function.

63
00:03:23,220 --> 00:03:25,725
Then reuse becomes easy
as has been already said.

64
00:03:25,725 --> 00:03:27,780
And then if requirements change for

65
00:03:27,780 --> 00:03:31,850
one function, how many functions or
modules should get affected, exactly one.

66
00:03:31,850 --> 00:03:33,850
And that is the mantra
that should be used here.

67
00:03:33,850 --> 00:03:36,520
So, that is how you should
try to design your functions.

68
00:03:36,520 --> 00:03:39,920
And that also makes things
extremely configurable.

69
00:03:39,920 --> 00:03:42,130
Let's take a look at simple example.

70
00:03:42,130 --> 00:03:44,858
If you are defining a line,
and as I put too,

71
00:03:44,858 --> 00:03:46,570
that function you're given three in puts.

72
00:03:46,570 --> 00:03:49,390
The start, the end point,
and the length of the line.

73
00:03:49,390 --> 00:03:50,530
And go and implement that.

74
00:03:50,530 --> 00:03:55,390
And the same function can be written
where it takes only two inputs.

75
00:03:55,390 --> 00:03:56,730
Just the start point and the end point.

76
00:03:56,730 --> 00:04:00,424
Because after all, you can calculate
the length from those two inputs.

77
00:04:00,424 --> 00:04:04,340
And clearly the second function is
more efficient, more manageable.

78
00:04:04,340 --> 00:04:08,138
Because in the first instance,
instance there may be users who by

79
00:04:08,138 --> 00:04:12,280
mistake give three inputs that are not
consistent with each other, and

80
00:04:12,280 --> 00:04:15,200
then how is that going
to affect your program?

81
00:04:15,200 --> 00:04:16,210
We just don't know.

82
00:04:16,210 --> 00:04:20,600
So, try to make them consistent in that
fashion, don't try to, whatever you

83
00:04:20,600 --> 00:04:24,160
can calculate or you need to calculate
within the function you do it that way.

84
00:04:25,990 --> 00:04:29,870
So, when you are using someone else's
libraries, if that means that you

85
00:04:29,870 --> 00:04:33,680
have to write some special code to handle
that, maybe that is not a good idea.

86
00:04:33,680 --> 00:04:38,970
You should try to be as general as
possible and try to avoid such cases.

87
00:04:38,970 --> 00:04:41,500
Which also brings one to global data.

88
00:04:41,500 --> 00:04:44,320
Many times, many programs is global data.

89
00:04:44,320 --> 00:04:49,380
So a function, if it relies on some
global data, it may not be a good idea.

90
00:04:49,380 --> 00:04:52,960
You should be passing
the global data as an argument.

91
00:04:52,960 --> 00:04:55,560
And you may or
may not want to change the global data.

92
00:04:55,560 --> 00:04:58,570
But simil you should
certainly not rely on that.

93
00:04:58,570 --> 00:05:03,010
And in programming languages like
Python and all that's quite important.

94
00:05:03,010 --> 00:05:03,980
to all of them really,

95
00:05:03,980 --> 00:05:08,400
but there are specific cases where the
scope decides how things are happening.

96
00:05:08,400 --> 00:05:11,930
And unless that has been stated
explicitly, there may be grief later on.

97
00:05:12,960 --> 00:05:15,240
Avoiding similar functions,
I've already stated that.

98
00:05:15,240 --> 00:05:16,710
Just restating it to emphasize that.

99
00:05:16,710 --> 00:05:19,780
So, that brings us to refactoring.

100
00:05:19,780 --> 00:05:21,890
You should try to refactor early and
often.

101
00:05:21,890 --> 00:05:26,530
What that means, again, is that you
should, once the program is running fine,

102
00:05:26,530 --> 00:05:29,990
then you want to optimize it if
you want to benchmark it, and

103
00:05:29,990 --> 00:05:33,930
that is where you start seeing better
on the functions are orthogonal.

104
00:05:33,930 --> 00:05:37,980
Whether they are maintainable,
whether the consistency is being checked,

105
00:05:37,980 --> 00:05:41,800
whether the, the syntax is
the way I want them, and so on.

106
00:05:41,800 --> 00:05:44,010
So you can duplication
during this process.

107
00:05:44,010 --> 00:05:49,760
You can make sure that that you bring
in orthogonality to your design.

108
00:05:49,760 --> 00:05:51,580
And if there are some outdated knowledge,

109
00:05:51,580 --> 00:05:54,300
this is the time to take them out,
take that out too.

110
00:05:54,300 --> 00:05:56,220
And you can improve
performance in the process.

111
00:05:57,380 --> 00:06:01,220
One important thing to remember when
you're refactoring is that do not try to

112
00:06:01,220 --> 00:06:03,990
add functionality while
you are doing that,

113
00:06:03,990 --> 00:06:07,870
because the two things are quite
separate from each other.

114
00:06:07,870 --> 00:06:09,434
When you try to add functionality,

115
00:06:09,434 --> 00:06:12,520
you are trying to make changes
that which have not been tested.

116
00:06:12,520 --> 00:06:15,030
Whereas when you're refactoring,
you've already tested things,

117
00:06:15,030 --> 00:06:17,200
you have gone through it,
and then it's working.

118
00:06:17,200 --> 00:06:20,990
You are only trying to make it better,
make it perform better.

119
00:06:20,990 --> 00:06:26,500
So, if you try to do both things, again,
that's likely to lead to sorrow later on.

120
00:06:26,500 --> 00:06:29,420
You can add good tests during refactoring.

121
00:06:29,420 --> 00:06:31,950
And that's always a good thing,
I think, more and more tests.

122
00:06:31,950 --> 00:06:34,200
And you should do that in
very short deliberate steps.

123
00:06:34,200 --> 00:06:38,700
Don't try to reformat the whole
thing during refactoring also.

124
00:06:38,700 --> 00:06:39,860
Take one step at a time.

125
00:06:41,040 --> 00:06:44,080
So, all this can be put together
in something that's called

126
00:06:44,080 --> 00:06:45,170
Design by contract.

127
00:06:45,170 --> 00:06:48,710
And in 1997, Eiffel and
Meyer had suggested that.

128
00:06:48,710 --> 00:06:53,840
So, what a function should do
a function should say that I want these

129
00:06:53,840 --> 00:06:57,810
specific inputs, and then this is the way
I am going to work on those inputs.

130
00:06:57,810 --> 00:07:01,210
And when I am done,
this is how the output of the program or

131
00:07:01,210 --> 00:07:03,800
what the state of
the program is going to be.

132
00:07:03,800 --> 00:07:06,082
So, it will work on
the input that it has given,

133
00:07:06,082 --> 00:07:09,080
there are may be some class
invariants which may not be touched.

134
00:07:09,080 --> 00:07:10,950
So, in this whole process,

135
00:07:10,950 --> 00:07:15,510
what is important is that your function
should be very strict in what you accept.

136
00:07:15,510 --> 00:07:18,110
Function should be able to say,
okay, I want three numbers.

137
00:07:18,110 --> 00:07:21,060
Two of them should be integers,
and one of them should be float.

138
00:07:21,060 --> 00:07:24,840
And the function, right at the outside,
if it does not get exactly that,

139
00:07:24,840 --> 00:07:28,840
should be able to just come out in
a graceful way saying that no, no, no.

140
00:07:28,840 --> 00:07:29,820
This is not our, not what I want.

141
00:07:29,820 --> 00:07:31,950
I want these specific things.

142
00:07:31,950 --> 00:07:35,730
Similarly, a given function should
promise as little as possible.

143
00:07:35,730 --> 00:07:37,640
It should not try to
detain different things.

144
00:07:37,640 --> 00:07:40,930
It should try to do one
specific thing in a proper way.

145
00:07:40,930 --> 00:07:42,330
And then again, you should be lazy, and

146
00:07:42,330 --> 00:07:46,860
you should try to do it in a, in
the most efficient way that is possible.

147
00:07:46,860 --> 00:07:48,750
And if you can do this,
then inheritance and

148
00:07:48,750 --> 00:07:50,840
polymorphism will result automatically.

149
00:07:50,840 --> 00:07:52,750
You will be able to
overload your functions,

150
00:07:52,750 --> 00:07:56,880
you will be able to use the same
function in multiple places much easily.

151
00:07:56,880 --> 00:08:01,570
So, try to inculcate that as early
as possible, designing by contract.

152
00:08:02,980 --> 00:08:07,350
Some more aspects, testing how to
write tests, how to use tests.

153
00:08:07,350 --> 00:08:08,670
What kind of comments should be used?

154
00:08:09,740 --> 00:08:12,660
What kind of arguments should
be there in the program, and

155
00:08:12,660 --> 00:08:14,880
how debugging can be done.

156
00:08:14,880 --> 00:08:16,390
So, let's revisit this.

157
00:08:16,390 --> 00:08:18,610
We just briefly touched upon it earlier.

158
00:08:19,910 --> 00:08:24,250
One thing that you should remember is that
someone is going to test your software.

159
00:08:24,250 --> 00:08:27,810
And if you don't do it yourself,
your users will at that time,

160
00:08:27,810 --> 00:08:31,050
then for some cases it may be too late.

161
00:08:32,150 --> 00:08:36,200
So, we can do the test also against
the contract that specific functions have.

162
00:08:36,200 --> 00:08:40,770
So, if a function is for taking square
root, then the function may have told you

163
00:08:40,770 --> 00:08:44,970
that I'm going to the square roots but
I'll do it only for positive integers.

164
00:08:44,970 --> 00:08:46,780
I'm not going to deal
with complex numbers.

165
00:08:46,780 --> 00:08:48,920
So, I won't allow negative integers.

166
00:08:48,920 --> 00:08:49,490
Fine.

167
00:08:49,490 --> 00:08:50,990
So, as long the contract is there,

168
00:08:50,990 --> 00:08:54,760
as long as the function explicit,
you can test specifically against that.

169
00:08:54,760 --> 00:08:58,130
But assuming that it can
be more generic you,

170
00:08:58,130 --> 00:09:01,340
you should make sure that
the age cases are also tested.

171
00:09:01,340 --> 00:09:04,870
So if you provide zero,
does it work with zero.

172
00:09:04,870 --> 00:09:06,070
What happens when you go out and

173
00:09:06,070 --> 00:09:09,310
you get your number minus four in
this case, it's returning zero.

174
00:09:09,310 --> 00:09:12,480
Maybe that is the situation
that is needed here.

175
00:09:12,480 --> 00:09:14,450
But, what about things
like scientific notation,

176
00:09:14,450 --> 00:09:16,120
many times such things are not tested.

177
00:09:16,120 --> 00:09:19,530
Here, the first input that's
been given is 10 exponent 12.

178
00:09:19,530 --> 00:09:20,730
Does I come back and

179
00:09:20,730 --> 00:09:25,430
in fact give you So if it's taking only
positive numbers surely that should work.

180
00:09:25,430 --> 00:09:27,740
So make sure that there
are tests available for that.

181
00:09:28,980 --> 00:09:32,230
And then, you don't have to
write all these tests by hand.

182
00:09:32,230 --> 00:09:35,370
There are various test templates
available, so you can start with

183
00:09:35,370 --> 00:09:39,560
a test template and just start filling
that up in the way that you want.

184
00:09:39,560 --> 00:09:44,150
And then, while the testing happens,
again there are test harnesses available,

185
00:09:44,150 --> 00:09:47,470
where all the logs and
errors can be easily put together.

186
00:09:47,470 --> 00:09:49,570
So though this may seem
to be a lot of work,

187
00:09:49,570 --> 00:09:51,460
it is not really too much extra work.

188
00:09:51,460 --> 00:09:56,400
But, just that discipline of writing
tests is going to take you a long way.

189
00:09:57,430 --> 00:10:01,320
And of course what is important is
to be able to write test that fail.

190
00:10:01,320 --> 00:10:06,430
Because if all test just pass then
maybe someone has done something,

191
00:10:06,430 --> 00:10:10,060
so that all that the tester doing is
simply take different arguments and

192
00:10:10,060 --> 00:10:11,640
return true, true, true.

193
00:10:11,640 --> 00:10:14,930
So, only when you write a test
which you know should fail, and

194
00:10:14,930 --> 00:10:20,330
then give it to input such at one input
is given and the output don't match and

195
00:10:20,330 --> 00:10:22,670
it returns a false,
you really know that things are working.

196
00:10:24,680 --> 00:10:28,530
So, things to keep in mind
when you write tests, is that,

197
00:10:28,530 --> 00:10:30,820
try to use long subroutine names.

198
00:10:30,820 --> 00:10:35,340
And try to prefix them with the word test
so you know that these functions are not

199
00:10:35,340 --> 00:10:39,270
really the main functions in your program,
but just for testing purposes.

200
00:10:39,270 --> 00:10:43,100
Similarly, you should have stand
alone code specifically for tests.

201
00:10:43,100 --> 00:10:45,050
And they should be stand alone data sets.

202
00:10:45,050 --> 00:10:48,670
So again, you are not interfering
with the main body of the program.

203
00:10:48,670 --> 00:10:52,390
And then you should do clean ups
during the start of the tests and

204
00:10:52,390 --> 00:10:54,080
once the tests are done.

205
00:10:54,080 --> 00:10:57,970
So, that way the entire testing
routine is a separate thing and

206
00:10:57,970 --> 00:11:00,346
doesn't interfere with your main program.

207
00:11:00,346 --> 00:11:04,930
So, in case of Python we saw in the first
part how unit test can be written,

208
00:11:04,930 --> 00:11:08,990
then we saw in the second part how
it can be doctests that can go

209
00:11:08,990 --> 00:11:11,100
in the docstrings also.

210
00:11:11,100 --> 00:11:14,330
Pytest is another simpler mechanism
that works with Python, and

211
00:11:14,330 --> 00:11:15,240
you should take a look at that.

212
00:11:15,240 --> 00:11:17,760
Similarly, there are specific
modules like nose and

213
00:11:17,760 --> 00:11:20,350
tox, and mock that can also be used.

214
00:11:22,800 --> 00:11:24,230
Then coming to comments.

215
00:11:24,230 --> 00:11:27,030
I have already stated that, but
I again emphasizing comments,

216
00:11:27,030 --> 00:11:31,590
documentation are crucial so
that knowledge gets transferred properly.

217
00:11:31,590 --> 00:11:35,010
And all kinds of bits
can be put in comments.

218
00:11:35,010 --> 00:11:37,940
Some people think that if something was
difficult to write maybe it was difficult

219
00:11:37,940 --> 00:11:39,810
to understand, but that's questionable.

220
00:11:40,840 --> 00:11:44,140
And you should also remember that
bad code requires more comments.

221
00:11:44,140 --> 00:11:47,470
So, if you find yourself writing too many
comments, maybe you should take a look at

222
00:11:47,470 --> 00:11:50,540
the code, and maybe you should
try to improve the code itself.

223
00:11:50,540 --> 00:11:53,320
As an example,
you shouldn't have trivial things,

224
00:11:53,320 --> 00:11:56,410
like when you do x equal to x plus 1,
have a comment saying oh,

225
00:11:56,410 --> 00:11:59,710
I'm implementing x,
that's quite obvious from the statement.

226
00:11:59,710 --> 00:12:03,730
On the other hand, if you're implementing
x for a specific reason that

227
00:12:03,730 --> 00:12:07,900
is nonstandard, like you're compensating
for the border as has been shown here.

228
00:12:07,900 --> 00:12:09,770
Then perhaps you should
state that as a comment.

229
00:12:09,770 --> 00:12:15,080
You should say that x equals x plus 1 and
that it's compensating for the border.

230
00:12:15,080 --> 00:12:17,260
So, what kind of comments or

231
00:12:17,260 --> 00:12:20,600
what kind of documentation can
go to live to, in the comments.

232
00:12:20,600 --> 00:12:23,150
So, you can have a list of
functions that are being exported.

233
00:12:23,150 --> 00:12:27,400
You can have revision history,
when and how has the program changed.

234
00:12:27,400 --> 00:12:30,320
Remember, in the first part we
talked about source control,

235
00:12:30,320 --> 00:12:33,370
the source control will keep
that off your comments.

236
00:12:33,370 --> 00:12:35,980
But, you can also have a set of
comments in either a readme file or

237
00:12:35,980 --> 00:12:36,849
in the program itself.

238
00:12:37,890 --> 00:12:41,330
You can list, the other files that
are being used by your program.

239
00:12:41,330 --> 00:12:43,730
And the name of the file itself,
which has the program.

240
00:12:44,740 --> 00:12:46,610
So the documentation can be algorithmic.

241
00:12:46,610 --> 00:12:50,720
You can have full line comments that
describe the algorithm that you're using.

242
00:12:50,720 --> 00:12:52,530
Or you can just simply
list anything where,

243
00:12:52,530 --> 00:12:57,090
there are offline comments like we
talked about bordering commenting.

244
00:12:57,090 --> 00:12:58,510
Or the comments can be defensive.

245
00:12:58,510 --> 00:13:01,090
And these are very important sometimes.

246
00:13:01,090 --> 00:13:06,270
When a piece of code has been slightly
tricky to write, but then figure it out,

247
00:13:06,270 --> 00:13:07,860
it is worth mentioning
that in the comments.

248
00:13:07,860 --> 00:13:11,630
That it had puzzled you before, and
this is how you have done that.

249
00:13:11,630 --> 00:13:15,660
Or you can even have something indicative
that you have done a rather quick and

250
00:13:15,660 --> 00:13:17,620
dirty job, you'd want to revisit that.

251
00:13:17,620 --> 00:13:20,140
The program is working, but user beware,

252
00:13:20,140 --> 00:13:22,250
that it better be rewritten
in different ways.

253
00:13:22,250 --> 00:13:24,540
So, you can have those comments also.

254
00:13:24,540 --> 00:13:27,980
And then you can have discussive comments,
where details of what is being done

255
00:13:27,980 --> 00:13:32,428
can go into plain old documentation,
regular documentation, whatever.

256
00:13:32,428 --> 00:13:36,180
And then, arguments.

257
00:13:36,180 --> 00:13:38,120
That is another important thing.

258
00:13:38,120 --> 00:13:43,320
You should try to have arguments that
are meaningful, arguments to functions.

259
00:13:43,320 --> 00:13:46,560
You cannot, you should not try to have
too many arguments being given to

260
00:13:46,560 --> 00:13:47,640
a single function.

261
00:13:47,640 --> 00:13:50,450
You can bill your universe
with various constants.

262
00:13:50,450 --> 00:13:53,230
You can give all the constants
to the function subroutine,

263
00:13:53,230 --> 00:13:54,660
to the universe subroutine.

264
00:13:54,660 --> 00:13:58,200
But then if the order of that
is given wrong, what then?

265
00:13:58,200 --> 00:14:01,780
Then someone is going to make a mess
of the universe that it built.

266
00:14:01,780 --> 00:14:06,600
So, that can, one can get around that by,
again, having deliberate chart steps for

267
00:14:06,600 --> 00:14:10,740
your arguments, are named arguments,
then it doesn't matter whether you

268
00:14:10,740 --> 00:14:14,270
turn around order in which
the arguments are given.

269
00:14:14,270 --> 00:14:17,720
Then, in your program you should look for
missing arguments, definitely.

270
00:14:17,720 --> 00:14:20,360
And then whenever possible,
you can set default arguments.

271
00:14:20,360 --> 00:14:24,500
So, if you are giving five arguments and
two of them normally have the same values,

272
00:14:24,500 --> 00:14:29,490
you should just set them and let the user
change them through the arguments wish to.

273
00:14:29,490 --> 00:14:33,790
And as far as return values are concerned,
you should try

274
00:14:33,790 --> 00:14:39,500
not to make a sub routine,
do things just by the side effects.

275
00:14:39,500 --> 00:14:43,170
Many people tend to change variables and
leave them like that, and

276
00:14:43,170 --> 00:14:47,540
pass them out without the return values,
if that is possible, if one can

277
00:14:47,540 --> 00:14:50,710
have side effects in the particular
programming language that you are using.

278
00:14:50,710 --> 00:14:54,350
But, that's again a bad thing, because
a user may not realize that that is how

279
00:14:54,350 --> 00:14:58,330
the code has been written, and they may
look just for specific return values.

280
00:14:58,330 --> 00:15:01,460
So try to return everything
that you are modifying, and

281
00:15:01,460 --> 00:15:03,020
that is going to be
significant after that.

282
00:15:04,450 --> 00:15:10,290
So, here is in case of arguments where
you can have the dash dash type and

283
00:15:10,290 --> 00:15:15,140
the dash type, and ordinary types
where you have named values or

284
00:15:15,140 --> 00:15:19,830
you have values being provided along with
the keywords in the command line itself or

285
00:15:19,830 --> 00:15:21,380
just position values.

286
00:15:21,380 --> 00:15:24,000
And then there are normally models of

287
00:15:24,000 --> 00:15:27,850
a level in all good programming
languages which make use of that and

288
00:15:27,850 --> 00:15:31,480
I've given example of Python here,
but you can use the getopt model.

289
00:15:31,480 --> 00:15:34,000
And when you use the getopt model
,then it can separate your,

290
00:15:34,000 --> 00:15:36,660
a different kinds of arguments
in a very meaningful way.

291
00:15:36,660 --> 00:15:37,880
And then you can handle or

292
00:15:37,880 --> 00:15:40,510
use those arguments within your
subroutine quite meaningfully.

293
00:15:42,400 --> 00:15:43,620
Then coming to debugging.

294
00:15:43,620 --> 00:15:47,900
It's of course one important thing to
do because you don't want your code to

295
00:15:47,900 --> 00:15:48,440
have bugs.

296
00:15:48,440 --> 00:15:51,690
And you should remember
that there will be bugs.

297
00:15:51,690 --> 00:15:54,470
And the only bug-free program
is one that doesn't do anything.

298
00:15:54,470 --> 00:15:59,280
So you better make sure that you try
to do as best debugging as possible.

299
00:15:59,280 --> 00:16:03,050
And again, tests, which have been
talked about before, come to your aid.

300
00:16:03,050 --> 00:16:08,380
Write lots and lots of unit tests to look
at each functionality of your program.

301
00:16:08,380 --> 00:16:11,580
So, that all of those
cases are caught early.

302
00:16:11,580 --> 00:16:15,500
And make sure that the programs
compile without warnings.

303
00:16:15,500 --> 00:16:20,080
Many times, people go ahead when they see
that there is no error during compilation.

304
00:16:20,080 --> 00:16:23,150
So, even if there are some warnings or
this did not work, or there may be

305
00:16:23,150 --> 00:16:27,300
an issue with this, so long as it is
not a showstopper they just go ahead.

306
00:16:27,300 --> 00:16:28,570
But I don't think that's a good idea.

307
00:16:28,570 --> 00:16:31,920
And you should definitely take care of
any warnings that are being raised,

308
00:16:31,920 --> 00:16:33,050
because they are being raised for

309
00:16:33,050 --> 00:16:35,550
some specific reason and
you'd better take a look at that.

310
00:16:37,010 --> 00:16:40,300
So when dealing with bugs,
make them reproducible.

311
00:16:40,300 --> 00:16:45,220
Be able to show that this bug
crops up every time you had in

312
00:16:45,220 --> 00:16:46,530
a particular situation.

313
00:16:46,530 --> 00:16:50,400
And if you can not isolate the situation
then there are some complex [INAUDIBLE].

314
00:16:50,400 --> 00:16:53,750
So, try to isolate that by
going down to one subroutine to

315
00:16:53,750 --> 00:16:55,920
another subroutine apart of
the subroutine, and so on.

316
00:16:55,920 --> 00:16:58,330
So that exactly with the single command,

317
00:16:58,330 --> 00:17:02,240
you should be able to
get the bug reproduced.

318
00:17:02,240 --> 00:17:04,690
And then if needed,
you can visualize the data.

319
00:17:04,690 --> 00:17:06,990
You can set various break points.

320
00:17:06,990 --> 00:17:10,210
And these are the standard ways
that you can look for bugs.

321
00:17:11,870 --> 00:17:15,220
When you do find a bug, there are some
trivial things that you can do.

322
00:17:15,220 --> 00:17:17,560
First, check for boundary conditions.

323
00:17:17,560 --> 00:17:21,360
Is the bug coming up because of the first
case or because of the last case, or

324
00:17:21,360 --> 00:17:25,420
is it something else, because those
are the simpler bugs to catch.

325
00:17:25,420 --> 00:17:29,770
Then, this may seem a bit psychiatric,
but describe the problem to someone else.

326
00:17:29,770 --> 00:17:33,670
Many times when you are doing that, you
usually realize what may be going wrong,

327
00:17:33,670 --> 00:17:35,240
and you are able to catch the bug.

328
00:17:35,240 --> 00:17:36,209
So definitely you've got to try.

329
00:17:37,310 --> 00:17:40,110
Then ask yourself,
why wasn't it caught before.

330
00:17:40,110 --> 00:17:43,870
So, what assumptions you may
have made that were wrong.

331
00:17:43,870 --> 00:17:46,070
So you,
that's definitely worth investigating.

332
00:17:46,070 --> 00:17:50,930
And then ask yourself also whether
the bug could be lurking somewhere else.

333
00:17:50,930 --> 00:17:53,580
If your code is orthogonal,
then if you find a bug somewhere,

334
00:17:53,580 --> 00:17:55,890
it's very unlikely that
it's somewhere else too.

335
00:17:55,890 --> 00:17:58,260
But if it's not orthogonal,
it could be somewhere else.

336
00:17:58,260 --> 00:18:01,260
So, make sure that you find
all instances of the same bug,

337
00:18:01,260 --> 00:18:03,510
so you can go after the same
bug multiple times.

338
00:18:04,630 --> 00:18:06,330
And then, you have tests, right?

339
00:18:06,330 --> 00:18:09,800
And you have the tests ran fine,
the tests didn't catch the bug.

340
00:18:09,800 --> 00:18:11,180
Then maybe the tests are bad.

341
00:18:11,180 --> 00:18:13,680
You should have a relook
at the tests themselves.

342
00:18:13,680 --> 00:18:15,930
So this is what you can
do about debugging.

343
00:18:17,670 --> 00:18:21,160
Next time we'll be looking at
the portfolio building and

344
00:18:21,160 --> 00:18:22,037
some meta programming.

