00:00:00.000
bye
00:00:20.270
sighs by enemies but they tell me that
00:00:23.130
some people do science categorized
00:00:25.470
problem story different ways
00:00:35.230
you get to a solution maybe it might
00:00:37.970
take you a few hours maybe a few days
00:00:40.880
but eventually you will get to a
00:00:42.530
solution these problems are called
00:00:45.010
obvious obvious doesn't mean I will know
00:00:51.800
straight away it means if I sit down
00:00:54.309
then I will know some problems don't
00:00:58.100
work like that so you don't really know
00:01:00.500
how long you will take to get to a
00:01:02.870
solution you might take weeks you might
00:01:05.180
have a few false start and those are non
00:01:07.790
obvious problems and then there are the
00:01:11.030
problems that are harder than either of
00:01:14.300
your sword and obvious and these other
00:01:17.060
problems well you don't even know
00:01:19.130
whether there is a solution maybe there
00:01:21.440
is a solution but it's not optimal maybe
00:01:24.409
you have trade-offs maybe you have to
00:01:26.540
try something different and see what
00:01:28.940
happens you have to experiment maybe you
00:01:31.729
can try a few different things and just
00:01:34.340
settle for the best that you find and
00:01:38.450
those are the problems that some people
00:01:40.789
call deep and I'm going to talk about a
00:01:44.810
deep problem today but first let's talk
00:01:47.780
about refinement it's a feature
00:01:51.469
introduced neo-newbie to you probably
00:01:54.430
know about them in case you want the big
00:01:59.659
picture let's look at what refinements
00:02:02.090
are for what is the problems that the
00:02:04.340
refinements want to solve so why do we
00:02:08.810
have them well in Ruby you can do this
00:02:12.130
most of us know you can reopen a class
00:02:14.810
that already exists and do stuff inside
00:02:17.780
it for example define a new method or
00:02:19.840
redefine a method that already exists
00:02:22.630
here i define the new method shout on
00:02:25.730
stories and now all strings have this
00:02:27.920
method some people call these open
00:02:30.800
classes or dynamic class scope but most
00:02:34.130
of us just call it with these vaguely
00:02:36.860
negative term we call it monkey patching
00:02:40.930
what is multi patching for which is not
00:02:44.650
an obvious question because if you ask
00:02:46.510
to somebody if you show multi passion to
00:02:48.640
somebody works I don't know with Java
00:02:50.920
they will think it's crazy so what are
00:02:53.319
the use cases for it I can think of a
00:02:55.959
few use cases probably so can you like
00:02:58.299
five or six but there are maybe three
00:03:01.689
use cases that are very common I will go
00:03:04.810
for the classic examples one is dsl's
00:03:14.250
once again textbook example from our
00:03:17.439
spec not the latest version of us back
00:03:19.569
an older version here we have something
00:03:23.109
that is meant for testing I want to test
00:03:26.189
integers so I'm saying I'm describing
00:03:29.260
fixed numbs the class for integers they
00:03:32.200
can be added here two plus two should
00:03:34.840
equal four and the interesting side of
00:03:37.060
this is that it looks so nice it reads
00:03:41.109
like it's a language that was designed
00:03:43.650
for testing but it's not it's just don't
00:03:46.510
be so that's why domain-specific
00:03:50.519
language and if you look at this you
00:03:52.989
cannot do this with that monkey patching
00:03:56.500
in this particular case for example
00:03:58.750
should is a method so somebody had to
00:04:02.319
add this method to at least two integers
00:04:05.019
and probably to any object so this is
00:04:08.919
why use case of something that you can
00:04:11.409
only do because of monkey patching there
00:04:13.359
is another one that is maybe less
00:04:15.790
compelling but at least as common which
00:04:19.750
is once again textbook example
00:04:22.830
convenience methods I imported the
00:04:26.289
library and thanks to these library I
00:04:28.300
have these beautiful little methods like
00:04:30.430
hours and minutes and I can do tying
00:04:32.770
calculations and they look really smooth
00:04:35.050
and in the Ruby Ward we pride ourselves
00:04:37.930
on writing code that is beautiful and
00:04:40.389
this is beautiful it's not like it's
00:04:42.400
necessary ok I can get away with having
00:04:45.750
just normal functions they're ours and
00:04:49.840
which take a number but this looks nice
00:04:52.719
and looking
00:04:53.820
I say is important for us then there is
00:04:56.790
another use case which is usually not
00:05:00.500
mentioned but actually I feel it's
00:05:02.790
important because it's so common and
00:05:04.590
it's metal wrappers the idea here is
00:05:08.100
that instead of just story placing a
00:05:10.800
method I'm adding more code around an
00:05:14.400
existing method in this case I'm
00:05:16.950
renaming the method first then monkey
00:05:19.680
patching it the mechanics are not
00:05:21.990
important the important part is the fact
00:05:24.150
that I can rep code around the length
00:05:28.380
method in strings so now when I called
00:05:32.130
length I'm relying on the previous
00:05:35.160
length to do something else incidentally
00:05:39.870
this also shows to why monkey patching
00:05:41.970
is evil and dangerous because if you run
00:05:45.300
this code then you're in the context of
00:05:47.910
a larger program then your program is
00:05:49.980
just a few milliseconds to leave because
00:05:52.050
you just broke a ruby because
00:05:55.290
everybody's or relying on the length
00:05:57.360
method in strings to do exactly what it
00:06:00.660
does now and if you change that then
00:06:03.720
you're dead essentially which is okay in
00:06:07.200
this case because it's pretty obvious
00:06:08.850
but in a large system it might happen
00:06:10.920
you don't even notice it might happen
00:06:13.980
and you don't even have control over it
00:06:16.500
maybe you just had no required to
00:06:20.040
libraries that monkey patch the same
00:06:22.230
method on the same class so they step
00:06:24.900
over each other and unfortunately these
00:06:26.550
things do happen and the problem with
00:06:28.890
this is that they are global right
00:06:31.040
monkey patches are global we don't like
00:06:34.110
global stuff it brings bad luck in
00:06:36.480
programming so we would like local
00:06:39.510
market patches instead and that's what
00:06:43.050
refinements our local monkey patches so
00:06:47.340
let's see how they are not how they are
00:06:51.120
implemented today but what the original
00:06:53.580
idea for refinements was a refinement is
00:06:59.460
very simple a two step process you
00:07:02.250
define the refinement you use the
00:07:04.020
refinement define it
00:07:07.020
you need the module modules are used for
00:07:10.000
a lot of things in Ruby they are used
00:07:12.610
for mix-ins to add methods to your chain
00:07:15.970
of ancestors they are used for
00:07:18.330
namespaces to organize your your
00:07:22.360
constants now they are also used as
00:07:24.400
homes for refinements so this module
00:07:27.850
will carry the refinement and the
00:07:30.070
refinement itself is in here you say I
00:07:32.710
want to refine a string it's a method
00:07:35.949
and you pass a block to this method and
00:07:39.430
inside the block you do exactly what
00:07:41.770
ever you could do with a monkey patch
00:07:43.479
for example you say let's add the metal
00:07:46.660
to shout that's it about defining the
00:07:50.260
refinement there is essentially nothing
00:07:51.970
else to no or very little no then you
00:07:56.710
use it let's say that you want to use
00:08:00.699
the refinement in here I gave this model
00:08:03.880
a very long name just to avoid confusion
00:08:06.669
with the module that is containing the
00:08:08.530
refinement okay to use the refinement in
00:08:10.960
here you use the method using and then
00:08:16.810
the refinement is active and now you can
00:08:19.120
use it that's essentially all there is
00:08:22.720
to know about using a refinement a few
00:08:27.070
details the refinement is active from
00:08:29.889
right after the using to the end of the
00:08:33.909
module the module can be a class a class
00:08:37.719
is just the module there is also another
00:08:41.680
use case you might decide to use using
00:08:44.500
at the top level of your file instead of
00:08:46.870
inside the modular class if you do this
00:08:49.690
then the refinement is going to be
00:08:51.880
active from right after the using to the
00:08:54.640
end of the file and that's it apparently
00:09:00.130
we are done with refinements but there
00:09:03.370
is more than meets the eye here there is
00:09:06.160
a some weird corner case that then kind
00:09:09.339
of explodes in your hands let's look at
00:09:12.250
that
00:09:14.390
we define the refinement recapping we
00:09:18.900
use the refinement in this case inside
00:09:21.810
the class now we said that in a ruby you
00:09:25.620
can or you open a class right you have
00:09:28.110
this dynamic stick so what happens if I
00:09:31.170
or you open the class in here I'm inside
00:09:35.580
the same class and there is a refinement
00:09:37.620
in there will the refinement work simple
00:09:44.430
question right I mean it's in there it
00:09:50.990
slightly more complex case what if i
00:09:53.990
inherit from the class is dead once
00:09:58.590
again it's kinda like the same scope
00:10:01.110
right the scope of these kinda like the
00:10:03.750
scope of C will the refinement work and
00:10:08.690
one more case because the Ruby allows
00:10:12.660
you to do awesome stuff with scopes you
00:10:15.540
can reopen scopes in many different ways
00:10:17.820
in one way that is quite common is by
00:10:20.160
using a method that is called classy
00:10:22.830
ball or or modeling ball it's actually
00:10:27.060
the same method if i use class eval to
00:10:30.060
get back into the scope of the class
00:10:32.160
with the refinement work doesn't look
00:10:37.650
like much it looks like a corner case
00:10:40.110
but let's assume it does because in the
00:10:43.680
very beginning at the original idea as
00:10:47.850
the original idea refinements whether
00:10:50.100
yes it does work it does work which
00:10:54.090
makes sense i mean it's a scope right i
00:10:56.520
get out of the scope i get back into the
00:10:58.920
scope I find all the stuff that I left
00:11:01.320
in there like class instance variables
00:11:05.240
instance methods constants and are fine
00:11:08.610
that's why not so it's supposed to work
00:11:11.370
but the problem is that once you do this
00:11:16.530
you open a can of worms this is called
00:11:20.910
the dynamic scoping this is what we are
00:11:23.700
used to your movie we closed scopes we
00:11:26.280
re-open scopes
00:11:29.330
some people noticed for example of
00:11:33.870
people from the j-o-b team just not that
00:11:38.820
if you do this there you have a few
00:11:41.370
problems that might get you now this is
00:11:44.610
the part of my presentation where I wish
00:11:46.770
I had a couple hours because it's
00:11:48.720
actually quite a lot of stuff but I
00:11:51.660
don't so I will have to be fast and if
00:11:54.870
you wish you can approach me later and
00:11:56.520
ask for more details if your interest
00:11:58.320
but I all I can do now is give you an
00:12:03.420
artfully complicated example here that I
00:12:06.360
created just to to show you what might
00:12:11.010
happen here it is I'm define a method
00:12:14.270
named add that is taking two things
00:12:17.280
probably two numbers and using the plus
00:12:20.790
method on them and then I have two
00:12:23.040
classes some class and some other class
00:12:25.230
and I'm calling add in the context of
00:12:28.290
these two and then i'm using some kind
00:12:32.580
of refinement that the documentation
00:12:35.490
says is refining fixed num plus and then
00:12:40.140
I calling add again now we dynamically
00:12:44.040
scoped the refinement you might have a
00:12:46.170
situation such as this one look at the
00:12:51.540
sorry your results in the three cases in
00:12:54.030
the first case some class is not
00:12:58.560
refining anything irrelevant here so you
00:13:01.980
get to just like you expect some other
00:13:05.760
class is apparently doing some
00:13:10.160
psychotronic casting it was probably
00:13:12.810
written by a JavaScript developer so it
00:13:15.810
converted numbers two strings and then
00:13:18.390
it concatenated the strength okay just
00:13:21.750
because and float point matt is deciding
00:13:27.750
that it will never return integers it
00:13:33.420
always returns floats so it's returning
00:13:36.210
float from
00:13:37.459
operation thing is if you look at this
00:13:40.309
code how do you know what's going to
00:13:43.399
happen I mean these three operations
00:13:46.160
look exactly the same the only way to
00:13:50.059
know what's going to happen is to know
00:13:51.619
exactly what is happening inside the
00:13:53.749
classes whether any of these classes is
00:13:58.240
using any refinement via any possible
00:14:04.189
way in your entire system that changes
00:14:07.189
the behavior not of AD but of any method
00:14:11.509
that is called by yet now some people
00:14:16.519
say this is very confusing some people
00:14:21.230
say this is terribly confusing some
00:14:23.209
people say oh it's just a ruby I mean
00:14:26.179
you can already make a mess right so
00:14:29.119
there is no consensus on these actually
00:14:31.910
I don't know what to think I don't have
00:14:35.089
a strong opinion personally it's very
00:14:37.670
hard to predict what would happen in a
00:14:40.160
real system some people say this is
00:14:42.649
implementation leaking into your
00:14:44.420
interface now you cannot trust anything
00:14:46.939
to be what it looks like anything can
00:14:50.839
change in the space of a single line of
00:14:53.899
code while the other camp says yeah so
00:14:58.610
what the first camp the size of people
00:15:04.040
who worry about this also say wait a
00:15:07.459
minute these also slows down Ruby I want
00:15:11.660
to go into the details again there are
00:15:13.369
technical details because of the way
00:15:15.410
your Ruby interpreters are implemented
00:15:18.259
that mean that for many interpreters if
00:15:21.649
not for all of them these features lows
00:15:25.160
down not only the code that uses or
00:15:27.860
refinements but every piece of code in
00:15:30.709
the system essentially just like you do
00:15:33.410
you have to check whether there are a
00:15:35.119
fine mess active in your code the
00:15:37.429
interpreter has to do the same it cannot
00:15:39.769
to just trust things to be what they
00:15:41.899
look on the surface it has to go in and
00:15:44.420
check whether there are assignments
00:15:45.529
active before it can execute code
00:15:48.620
once again some people say this is a
00:15:51.240
disaster other people say well that's
00:15:53.760
just optimizer another problem is that
00:16:01.050
when you don't understand your code that
00:16:03.390
you are also vulnerable from a security
00:16:07.170
point of view because now you don't
00:16:08.880
understand what is happening and I can
00:16:10.500
trick you into executing code that looks
00:16:12.720
harmless but it's actually dangerous
00:16:15.410
once again not consensus I was talking
00:16:18.540
to under a yesterday because he had the
00:16:20.790
presentation on security and he was like
00:16:24.270
well I can already trick you into
00:16:27.060
executing code that is dangerous I can
00:16:30.900
monkey patch code and then multi pass it
00:16:33.210
back to what it was and you will execute
00:16:36.210
it guaranteed and well yeah maybe one
00:16:45.420
final problem with these implementation
00:16:47.730
of references that there are a few
00:16:49.440
corner cases that might catch you off
00:16:51.540
guard again I won't go into all the
00:16:55.050
details but just to say well there if
00:16:58.470
you execute this code in common line
00:17:01.200
interpreter such as pry or IRB this last
00:17:05.040
line will not work actually will not
00:17:08.790
work like these the refinement will not
00:17:11.070
be active if you execute it in a file it
00:17:13.890
will work the reason for that is a very
00:17:16.980
sound technical reason but as sound as
00:17:19.079
it is it will still catch me off guard
00:17:20.730
it would still surprise me so to cut it
00:17:24.990
short there was some drama there was a
00:17:27.600
lot of debate if you want to wrap it up
00:17:32.550
there is one hugely good side about
00:17:36.450
dynamically scoped the refinements they
00:17:39.390
fix the Maquis patching problem they fix
00:17:41.640
the global monkey patching problem on
00:17:43.380
the other end they come with a few
00:17:45.660
strings attached they make your code
00:17:48.390
potentially confusing they probably
00:17:51.480
slowed down the language they might have
00:17:54.210
security issues and they have weird
00:17:57.600
corner cases so there was a debate if
00:17:59.790
you have one afternoon to go
00:18:01.440
go to the internet or heed the debate on
00:18:03.539
the Ruby core mailing list even a few
00:18:09.720
weeks Isaac before would be to worse or
00:18:12.690
at least there was still a raging debate
00:18:14.909
about it and the core team had to decide
00:18:17.909
are dynamically scoped refinements worth
00:18:21.870
the effort and the risks and for now
00:18:24.809
they decided no they're not they're not
00:18:27.450
so the refinements you have seen the
00:18:30.149
dynamically scoped the refinements are
00:18:32.100
not the refinements you have now your
00:18:34.200
will be let's look at those they look
00:18:38.730
pretty much the same okay same stuff you
00:18:41.309
have the one to process you define the
00:18:45.299
refinement you use the refinement
00:18:46.980
exactly like it did before but this use
00:18:53.039
case where you re open the scope doesn't
00:18:56.250
work neither does are you opening the
00:18:59.100
scope by any other means with the class
00:19:01.379
keyword with inheritance it doesn't
00:19:05.779
reactivate the requirement the
00:19:08.039
refinement stays there okay it stays
00:19:11.779
there where I have that small mark from
00:19:15.570
the point where you use using right
00:19:18.389
after the using to the end of the module
00:19:20.700
or the end of the file or the end of the
00:19:23.879
story if you are creating and storing
00:19:25.289
that contains the refinement and passing
00:19:27.960
it to evolve but it stays there this is
00:19:31.440
called the lexical scope its lexical
00:19:33.870
because it's about text right it's like
00:19:36.120
it's literally there in that piece of
00:19:39.149
text it doesn't leak out no other code
00:19:42.840
from the outside can see the refinement
00:19:49.159
so in this example again my artfully
00:19:52.799
complicated example what happens now
00:19:56.929
some class class of all I don't mind
00:20:02.519
whether some classes are refined or not
00:20:05.669
the only thing that can happen there is
00:20:08.279
that I get it too because even if it is
00:20:11.340
refined I will not see the refinement
00:20:14.850
from here from a separate scope and the
00:20:16.980
same stone or some other class class
00:20:20.190
eval but this one what happens here will
00:20:24.720
I get to or will i get to dot 0 and
00:20:31.200
taking bets on this one matsa you don't
00:20:36.390
need to reply so ok I tried it why is it
00:20:57.330
too it's too because this is purely
00:21:03.230
lexical ok remember what it means it's
00:21:06.330
about text and if I say add here and
00:21:12.350
nobody's are you finding Edie I will get
00:21:16.230
whatever add or it ours somebody is a
00:21:20.130
refining plus which is called by yet but
00:21:23.670
the co2 + does not happen after the
00:21:26.340
using the co2 + happens there in the
00:21:30.000
second line of the cold up there and
00:21:32.370
that they are no refinement is acting ok
00:21:38.990
it is kind of surprising but once you
00:21:43.770
know how it works frankly it's ok but it
00:21:48.930
can catch you off-guard once it already
00:21:51.750
did so it won't do it again this means
00:21:57.060
that this code has almost no no
00:22:01.470
confusing part to it ok almost but let's
00:22:08.280
look at the story use cases so you
00:22:09.780
remember why we introduced the
00:22:11.280
refinement in the first place right to
00:22:13.350
replace monkey patching and monkey
00:22:15.390
patching head at least those three use
00:22:18.300
cases so let's look at the use cases
00:22:20.460
again the first one is the main specific
00:22:23.130
languages
00:22:26.590
what's the point here the point here is
00:22:28.870
that you are passing a block to a method
00:22:32.200
named it let's add parentheses so it's
00:22:36.010
clear that it's a method and inside this
00:22:38.980
block you have a new method named shoot
00:22:41.679
so there should be a refinement in there
00:22:44.440
that adds the shoot method to I don't
00:22:47.140
know object basic object fixed nom the
00:22:50.860
kernel module something but this cannot
00:22:55.690
work now it cannot work with lexically
00:22:59.110
scoped the requirements right so this
00:23:03.250
does not work so this use case is not
00:23:07.809
covered out of the box I can cover it if
00:23:11.230
I a day using right before this code and
00:23:14.230
in fact that's probably one of the
00:23:17.110
reason why our spec moved to a different
00:23:19.360
syntax that doesn't require environments
00:23:22.480
and minimizes multi patching convenience
00:23:26.830
methods will this work
00:23:35.370
not out of the box no not straightaway
00:23:38.600
it can't work because once again I'm
00:23:41.280
reopening a scope and expecting to find
00:23:43.590
some refinements stuff in there we find
00:23:46.050
stuff in there and it's not there it
00:23:48.450
cannot be there if I re open a scope
00:23:50.670
it's not going to be there I can fix
00:23:53.130
this this would fail and I can fix this
00:23:57.180
by idea using but I have to add the
00:23:59.850
using to every model class for example
00:24:03.000
and now it's working it's not very dry
00:24:08.870
the third the use case meta directors
00:24:12.330
this one is good refinements have
00:24:16.500
another very nice feature if I call
00:24:19.110
super from inside the refinement I will
00:24:21.840
call in to the original I refined
00:24:23.910
version of the method so refinements are
00:24:27.929
actually great for this specific use
00:24:30.900
case these works it stays local it
00:24:34.140
doesn't leak out it's it replaces monkey
00:24:37.710
patching just fine still if you look at
00:24:41.730
the entire thing if you take a step back
00:24:43.800
and look at big picture refinements
00:24:46.559
today lexically scoped the refinements
00:24:48.990
do not fix monkey patches not in general
00:24:52.530
not in the general case and they still
00:24:55.650
have a few surprising corner cases on
00:25:00.720
the positive side they do fix monkey
00:25:04.650
patches in some cases or it's some cost
00:25:07.860
like the cost of repeating you're using
00:25:10.650
into every file where you want to use
00:25:13.559
their fine methods they do not make the
00:25:18.960
code particularly confusing they do not
00:25:20.970
impact performance they do not impact
00:25:24.240
security and this is crucial I think
00:25:28.790
they paved the road for something more
00:25:33.179
in the future maybe more powerful
00:25:36.990
refinements maybe something similar
00:25:40.530
maybe something we are not expecting
00:25:42.240
this got me thinking about the problem
00:25:47.950
so look at this code once again it's
00:25:55.649
what we there will be community consider
00:25:59.769
beautiful it or it's smooth its
00:26:03.940
expressive whether you like our speckle
00:26:07.090
not the syntax of this is quite neat but
00:26:11.710
if you look at this code there is a
00:26:13.840
white can exist is because of a number
00:26:16.059
of features in or will be that frankly
00:26:19.630
do not make that much sense when taking
00:26:22.720
on their own right the fact that like
00:26:26.320
the fact that I can skip parenthesis I
00:26:29.639
mean we're used to it but whenever I I
00:26:32.500
don't know when people say why does
00:26:35.769
there we have optional parentheses in
00:26:37.870
method calls the usual other is well
00:26:41.740
Mets liked pearl singleton class is a
00:26:48.490
meta programming why do they exist well
00:26:50.950
let's like small talk and you have to
00:26:56.049
wonder what's matts thinking about the I
00:26:58.029
don't want to know agreement but what's
00:27:01.389
met thinking about these where he
00:27:03.190
decided for single term classes I would
00:27:05.350
bet he was not I mean single term
00:27:08.860
classes in the first virtual server Ruby
00:27:10.720
looked like an implementation detail
00:27:11.980
right and then people started to abuse
00:27:14.409
them and we came up with this and it's
00:27:16.659
pretty awesome it's actually there is
00:27:20.649
some serendipity two days that is pretty
00:27:23.559
awesome so this is the thing that
00:27:29.440
language these are you cannot just sit
00:27:31.659
down and design language that's not how
00:27:34.630
it works oh you can probably do it you
00:27:37.149
end up with Coble
00:27:42.050
but if you want to build a beautiful
00:27:46.470
language that's a deep problem right
00:27:48.720
it's a it's about trying out things and
00:27:52.100
see how they turn out I believe I was
00:27:57.180
starting to believe so in particular
00:28:02.310
dear matt I i have to say when i looked
00:28:06.780
at refinements dynamically scoped the
00:28:11.850
refinements I was pretty scared I stick
00:28:15.450
under scared haha and well we we met at
00:28:21.450
a conference a few years ago and I told
00:28:23.370
you drive at this language that you
00:28:25.290
created it changed my life and you hand
00:28:29.790
in a very you answer the oh it's a big
00:28:33.600
responsibility that was a very mad thing
00:28:35.700
to say and it's a big responsibility
00:28:38.550
indeed I think it applies to all of
00:28:43.110
these or room anymore and one stick that
00:28:47.280
I was considering I was scared and the
00:28:50.220
reason why I was scared is that I'm a
00:28:52.080
bit of a wimp that's why I do not design
00:28:54.720
languages I'm so glad that you are it
00:28:57.810
you and the core team I so glad that you
00:29:02.550
are still willing to to make experiments
00:29:05.550
right to to see what happens to put a
00:29:09.390
new feature in the language and see what
00:29:11.370
happens after a few months when once
00:29:14.340
people start to get the hang of it and
00:29:17.750
well that's what made the language I
00:29:21.000
guess I guess that I'm trying to say
00:29:25.280
thank you so thank you I take it all
00:29:37.200
buy this book I hear it's good