00:00:00.000
ready for takeoff
00:00:16.920
I was just telling Craig that the first
00:00:20.340
time that I ever gave up talking public
00:00:22.439
was an academic conference when I was a
00:00:24.000
grad student and I was similarly in the
00:00:25.920
last session or the last day in a room
00:00:28.019
that was this big or possibly bigger and
00:00:30.660
like exactly three people showed up
00:00:33.480
so thank you for being more than three
00:00:35.820
people and uh thank you for spending
00:00:38.040
your time here this week uh I really
00:00:39.899
appreciate everybody coming out to be a
00:00:41.520
part of the Ruby community
00:00:43.140
so thank you uh let's start by looking
00:00:45.360
at some code Ruby fans here let's uh
00:00:48.000
let's look at some code this is real
00:00:50.100
code from a fake project it's a side
00:00:52.320
project that I do it's a project tracker
00:00:54.420
if you for some reason follow my
00:00:56.160
newsletter or blog you may have seen me
00:00:57.660
write about it
00:00:59.039
uh the important Point here is that this
00:01:01.620
is a project tracker every everything in
00:01:04.320
the tracker is a card every card has a
00:01:07.680
status and the status has been
00:01:09.479
abstracted out to its own object so we
00:01:12.299
have a parent object a parent abstract
00:01:13.920
class called status and a series of
00:01:16.680
subclasses that are the individual
00:01:18.479
status types done started unstarted
00:01:20.759
attic whatever
00:01:22.500
um everybody else everybody every client
00:01:25.140
of this deals with the abstract class
00:01:26.820
and obviously we have all of these
00:01:28.080
classes that have other functionality
00:01:29.880
too this is just sort of a simplified
00:01:31.400
schematic of the problem
00:01:33.540
now the parent class defines a bunch of
00:01:37.500
other services it defines creation
00:01:39.780
methods for each individual status it
00:01:42.180
defines uh strings
00:01:44.579
two strings for each individual status
00:01:46.560
sorry it defines predicate methods for
00:01:48.240
each individual status and it also
00:01:50.220
defines this is this is the main
00:01:52.079
mechanism by which we convert from the
00:01:54.060
active record data structure to our our
00:01:56.700
status comes in here so we have a case
00:01:59.040
statement right and you can quibble
00:02:01.439
about the various implementations of
00:02:02.820
this but let's assume for the point for
00:02:04.320
the sake of the problem this is actually
00:02:06.060
the business logic we need and so my
00:02:10.080
immediate question to you is how does
00:02:13.140
this code make you feel to look at it it
00:02:15.060
kind of shows up on the background there
00:02:16.379
you've got you know these subclasses
00:02:18.599
you've got all of these uh predicate
00:02:21.000
classes the Creator classes this is like
00:02:23.040
does this seem good does it seem right
00:02:25.379
to you or does it give you that kind of
00:02:27.480
unmatched parentheses this is ruining my
00:02:30.480
day I need to fix this immediately kind
00:02:32.220
of feeling
00:02:33.360
uh by the way if you've seen talks of
00:02:35.040
mine before you will know it is
00:02:36.180
extremely on brand that the only image I
00:02:38.040
use is just a bunch of text
00:02:39.959
uh
00:02:42.000
more to the point
00:02:44.099
the question is are put this in a
00:02:46.620
slightly more like domain specific
00:02:48.300
context maybe does this code have
00:02:50.099
duplication
00:02:51.780
right and on one sense the answer is
00:02:53.760
clearly no if I want to find out if I
00:02:57.000
want to find out
00:02:58.260
is this status done or not like there is
00:03:00.720
one place in the code and only one place
00:03:02.340
in the code that has that information
00:03:03.680
but in another way it kind of feels like
00:03:07.980
it has duplication right
00:03:09.720
so like what happens if the list of
00:03:12.840
statuses changes if we want to add a a a
00:03:17.480
status to say that it's been sent to
00:03:19.980
production a deployed status like what
00:03:22.019
do we need to do there lots of things
00:03:23.940
potentially so let's talk about that
00:03:27.000
so this is a talk called in defensive
00:03:30.000
meta programming we'll get there in a
00:03:31.500
second my name is Noel Rappin I work as
00:03:34.560
a staff engineer at chime Financial
00:03:36.300
there are several time people in the
00:03:38.159
audience here we would all be happy to
00:03:39.900
talk to you about chime or anything else
00:03:41.700
in the world you can find me at norwap
00:03:44.959
noradman.com and I promised myself I
00:03:47.099
would only get really self-promotional
00:03:48.480
if I finish the talk in under 30 minutes
00:03:50.760
so we'll get there at the end
00:03:53.459
so I want to start with a definition to
00:03:56.159
make sure we're all talking about the
00:03:57.540
same thing there is a formal definition
00:04:00.420
of meta programming that has to do with
00:04:02.400
changing Behavior at runtime and is only
00:04:05.099
sort of related to what we sort of think
00:04:07.560
of in Ruby the kinds of things in Ruby
00:04:10.019
that we call Meta programming what we're
00:04:12.540
really talking about here and what the
00:04:13.920
way this is frequently referred to in
00:04:15.659
the Ruby Community is Magic
00:04:18.419
and my definition here of magic is
00:04:21.720
anything in Ruby that is program
00:04:23.820
behavior that is not specified like
00:04:26.520
normally not specified the way somebody
00:04:28.800
from another language would come in to
00:04:30.600
know to look for it so normal is a class
00:04:33.720
definition with class a method
00:04:35.759
definition with deaf normal dot Syntax
00:04:38.400
for method for method dispatch that kind
00:04:42.720
of thing and anything else
00:04:44.639
we'll call Magic
00:04:47.340
Ruby is designed to make magic very easy
00:04:51.479
and so we have things like Define method
00:04:54.540
we have links like method missing both
00:04:56.759
of these things allow you to create
00:04:58.340
functionality at runtime without using
00:05:01.259
the normal explicit def keyword we have
00:05:03.600
things like instance eval which allows
00:05:05.460
you to specify the relationship between
00:05:07.080
a message and its receiver at runtime
00:05:09.840
again
00:05:10.919
uh somewhat magically we have all of
00:05:13.800
these features that allow us to do this
00:05:15.540
and it might be like the old maniest old
00:05:18.660
man thing for me to say but there did
00:05:20.160
used to be more magic in the world
00:05:22.440
um
00:05:23.699
rails used to have these long uh these
00:05:27.419
long method missing hacks find by email
00:05:30.120
and name where the the things were
00:05:32.220
arbitrary and it could go on forever and
00:05:34.380
they were method missing and they were
00:05:35.820
wonderful and fun and completely made
00:05:38.580
unnecessary once Ruby added keyword
00:05:40.380
arguments uh so we got rid of them our
00:05:43.259
spec used to have an even more magical
00:05:45.000
syntax if you can imagine people new to
00:05:46.860
our spec and can't imagine that our spec
00:05:48.360
was once like even more inscrutable
00:05:50.340
internally than it is now it was at one
00:05:52.979
point because of directly monkey patched
00:05:55.320
object and again a syntax that you know
00:05:58.320
had its advantages but had a major
00:06:00.000
disadvantage in that it triggered subtle
00:06:01.680
bugs from time to time for no reason and
00:06:04.139
so we got rid of it
00:06:05.699
uh so I think as a in a broader sense
00:06:09.539
this is these are just specific examples
00:06:11.280
and there were reasons for the making
00:06:12.780
these changes there were reasons why
00:06:14.160
these things existed and reasons why
00:06:15.479
they went away but the claim that I want
00:06:17.580
to make here or the Ruby Community is
00:06:19.199
sort of pulled back from Magic and from
00:06:22.139
being proud about it I think as a thing
00:06:24.600
that Ruby is
00:06:26.580
the very first Ruby Community event I
00:06:29.880
ever attended maybe the second oldest
00:06:32.160
man thing I'm going to say up here the
00:06:34.319
the first Ruby first Ruby Community
00:06:36.479
thing I ever attended was in 2008 and
00:06:38.699
the first speaker was Dave Thomas and he
00:06:40.860
was speaking about meta programming and
00:06:42.479
how wonderful it was that Ruby had all
00:06:44.160
of these wonderful tools and he
00:06:45.840
specifically said that
00:06:48.440
the problems that people have with meta
00:06:51.000
programming are not technical problems
00:06:52.620
they're people problems
00:06:54.660
soluble with training and I think that
00:06:57.419
for good reasons and for bad reasons I
00:06:59.460
think over the intervening what 15 15
00:07:02.100
years uh the Ruby Community has decided
00:07:05.100
that these are in fact technical
00:07:06.840
problems
00:07:08.039
uh and we hear from people within the
00:07:10.860
community from people outside the Ruby
00:07:12.360
Community we can't do this it's too
00:07:13.979
complicated it's too hard to maintain
00:07:16.160
developers from other languages won't
00:07:18.180
get it we won't be able to train people
00:07:20.520
and all of that is true to a point it
00:07:23.880
can be complicated especially when
00:07:25.319
misused it can be hard to maintain
00:07:27.120
certainly true that developers from
00:07:28.979
other languages have a learning curve
00:07:30.539
but my argument here is that we've over
00:07:34.319
corrected
00:07:36.000
that we've gone too far in the other
00:07:37.500
direction and we are too defensive about
00:07:39.360
the things that Ruby can do
00:07:42.000
and
00:07:43.259
as I have put together this talk as I've
00:07:45.360
been working on this talk over time I
00:07:47.400
have like felt this tension in myself as
00:07:50.580
to how I want to present this like do I
00:07:52.560
want to come out be like the hot takes
00:07:54.240
guy and be like meta program everything
00:07:56.039
better program all the things and just
00:07:57.960
like scorched Earth and everything
00:07:59.520
everything minor programming is the best
00:08:01.139
everything else is the worst or my like
00:08:04.560
other my more my other instinct is to
00:08:07.380
like be defensive and put everything in
00:08:10.080
maybes don't talk about the weird stuff
00:08:11.940
too loudly the other languages might
00:08:13.500
hear you uh you know maybe this stuff is
00:08:17.280
better sometimes like
00:08:19.400
and so I understand I feel this tension
00:08:22.259
in myself and I don't I don't really
00:08:24.120
like it honestly
00:08:26.099
um but I want to talk about it uh and I
00:08:28.560
want to talk about where uh what ruby
00:08:31.500
what these things that Ruby does well
00:08:33.839
are really is really good for and when
00:08:35.520
they can really be used super
00:08:37.020
effectively within your code base so to
00:08:40.320
put this kind of another way or to talk
00:08:42.180
about the way that Ruby's perceived this
00:08:44.700
completely to scale deeply thought out
00:08:46.680
very well researched chart suggests that
00:08:50.519
there is a small group of things that is
00:08:53.040
sort of encouraged in Java and for Java
00:08:55.500
say any sort of enterprising language or
00:08:57.540
tool set doesn't really matter there's a
00:08:59.880
small there's a subset of things that
00:09:01.380
are encouraged there and there is a
00:09:02.940
larger set of things that is encouraged
00:09:04.620
in Ruby
00:09:06.019
and the attitude that I have experienced
00:09:08.519
sometimes over the years over the last
00:09:10.860
several years is the idea that because
00:09:15.120
Ruby allows all of those extra things
00:09:17.220
it's not serious you can't do serious
00:09:19.800
work in it and um once upon a time I was
00:09:23.820
doing uh training I used to do training
00:09:25.680
when I worked I worked at Groupon and I
00:09:27.240
used to do internal training training
00:09:28.680
and for for whatever reason I was
00:09:30.300
training developers in Ruby who were
00:09:32.880
never ever going to use Ruby but the
00:09:35.339
onboarding had them go through four days
00:09:37.320
of Ruby training which they loved and I
00:09:39.660
loved
00:09:40.800
um and I remember very clearly bringing
00:09:43.800
up string Inquirer or one of the really
00:09:45.420
magical Ruby stuff and having people
00:09:47.519
laugh and not in like the this is
00:09:49.740
delightful programmer happiness kind of
00:09:51.540
way but more in like the here's a nickel
00:09:53.700
kid let me know when you got a real job
00:09:55.080
you know kind of way uh and there's
00:09:57.600
there's this sort of sense that because
00:10:00.720
you can do these these very Dynamic
00:10:03.240
things that it is somehow preventing you
00:10:05.160
from being able to do real work in Ruby
00:10:06.779
unless we don't do those things
00:10:09.000
um there's sort of the related claim
00:10:10.920
that going outside that minor that
00:10:13.740
bubble only has costs and never has
00:10:17.160
benefits and you sometimes see this
00:10:19.140
specifically with static typing the
00:10:21.120
claim that being stricter is always is
00:10:22.920
good you will seem time to see like
00:10:25.620
advantages of static typing without
00:10:27.480
seeing a corresponding disadvantages of
00:10:29.700
static typing I refuse to believe that
00:10:32.459
of all the things in programming and
00:10:34.019
development that have trade-offs and
00:10:36.000
good things and bad things that static
00:10:38.100
typing and uh and not doing Dynamic
00:10:41.040
things is the only thing that has costs
00:10:43.620
and never has benefits
00:10:46.440
um so I want to say like let Ruby do
00:10:48.839
what ruby is good at
00:10:51.000
and what do I think Ruby is good at in
00:10:53.519
this context
00:10:54.600
Ruby is extremely good at managing a
00:10:57.660
certain kind of complexity
00:11:00.899
what do I mean by complexity
00:11:04.200
if you go back to that original code if
00:11:06.779
you can remember it from 10 minutes ago
00:11:09.060
if you go back and you look at this
00:11:11.700
this code is not structurally complex if
00:11:14.100
you run it through a computational
00:11:15.360
complexity analyzer which I did not do
00:11:17.940
uh
00:11:19.560
it will probably not score very high it
00:11:21.899
has no Loops the only conditional is
00:11:24.240
that is that case statement it has a
00:11:26.700
bunch of one-line methods it is
00:11:28.980
generally like on a line by line basis
00:11:32.040
this code is very easy to understand
00:11:35.160
at the same time this code is very
00:11:37.800
organizationally complex
00:11:40.500
there are several Concepts in this code
00:11:43.440
that are actually related
00:11:45.899
that this code makes no effort to
00:11:49.140
enforce that relationship right
00:11:52.019
so there's a class name there's a string
00:11:54.480
representation there's a class method
00:11:56.100
there's a predicate method and there is
00:11:57.720
the branch in the at in the uh in the at
00:12:00.180
statement and those things are all tied
00:12:02.220
to each other
00:12:03.420
they are all they all have a
00:12:05.220
relationship
00:12:06.360
but this code does not that code this
00:12:09.720
code leaves that relationship implicit
00:12:12.600
and my argument here is that that makes
00:12:15.600
the code more complicated over time if I
00:12:18.180
were to come in and I wanted to add a
00:12:20.220
new deployed status there's nothing
00:12:22.380
preventing me from making the class name
00:12:24.839
deployed class and the string
00:12:26.399
representation production uh production
00:12:29.339
and the predicate method deployed in
00:12:31.260
production question mark and all of that
00:12:32.820
stuff and over time that kind of
00:12:35.160
inconsistency can make this code base
00:12:37.440
very hard to work with even though it is
00:12:40.260
not like notionally complicated I forget
00:12:43.260
which one is complicated and which one
00:12:44.579
is complex I always get that wrong it's
00:12:46.980
it's neither in both right
00:12:49.019
uh over time
00:12:51.899
uh this code base just exposes a lot
00:12:56.100
more surface area of the domain to the
00:12:58.920
developer in a way that will I look my
00:13:02.639
claim here is in a way that will make it
00:13:04.079
harder to work with over time
00:13:07.200
so let's look at some other code
00:13:09.480
here's a way around this one way
00:13:12.800
this way in this case I'm not replacing
00:13:15.540
the subclasses the subclasses still
00:13:17.220
exist but I've got a list of all the
00:13:19.139
statuses on the top line there are a
00:13:20.760
list of strings
00:13:21.860
and then I'm looping over each of them
00:13:24.180
and I am converting each string to a
00:13:26.339
class using the rails constantize active
00:13:28.440
support method I'm defining the class
00:13:30.600
method the Creator method to create a
00:13:32.940
new method of that class I'm defining
00:13:34.320
the predicate method using Define method
00:13:36.120
I am defining the two string directly as
00:13:39.779
the string status and then I'm using the
00:13:41.639
app method and using send to define the
00:13:43.440
app method in terms of the other ones is
00:13:45.180
that clear clearish mud mostly
00:13:49.320
uh
00:13:50.519
there's another way so this this uh
00:13:54.060
unifies all of the concepts except the
00:13:56.760
relationship between the class name and
00:13:59.399
the status name but we can actually do a
00:14:01.320
little bit better in Ruby by using
00:14:03.180
Ruby's hook method uh this is a code
00:14:05.639
base this is a version of this code that
00:14:07.620
uses Ruby's hook method inherited if you
00:14:10.980
don't know what inherited does inherited
00:14:12.839
every time a subclass is loaded created
00:14:15.720
at load time it calls this inherited
00:14:18.420
hook of the parent class with the
00:14:20.160
subclass as an argument so every time I
00:14:23.519
Define one of those done sub done
00:14:25.380
statuses uh started statuses whatever
00:14:27.899
this inherited Hook is called and it
00:14:30.300
takes the subclass and it we we extract
00:14:33.600
out the string and we do the same we
00:14:35.160
create the same methods we create the
00:14:36.420
class method we create the string method
00:14:38.579
we create the predicate method and we
00:14:39.899
create the app method
00:14:42.839
so this actually unifies all five of
00:14:45.240
those Concepts in one piece of the code
00:14:46.740
if I want to create a deployed status
00:14:48.959
all I need to do is create a class
00:14:51.000
deployed status and make it a subclass
00:14:52.800
of status and everything else falls out
00:14:55.680
I get the I get the predicate method I
00:14:57.660
get the class method I get the two
00:14:58.980
string I get the at everything comes
00:15:00.720
together
00:15:01.560
okay now
00:15:03.180
code is clearly more complicated than
00:15:06.000
the original code or complex it's one of
00:15:07.740
the two
00:15:08.699
right if you look at this it's got I've
00:15:10.440
got a loop I've got some fairly Advanced
00:15:12.480
Ruby methods in terms of Define method
00:15:14.459
like you need to know you need to
00:15:16.199
understand I'm not shying away from the
00:15:18.240
fact that this requires this is a higher
00:15:20.279
bar to entry
00:15:21.540
piece of code
00:15:24.600
but at the same time
00:15:27.000
it has fewer independent Concepts from
00:15:29.519
the outside if I go to CR if I need to
00:15:31.980
create a new status I have much much
00:15:33.779
less work to do I have separated data
00:15:37.620
and logic in a particular way that they
00:15:40.139
had this set of structural data in terms
00:15:42.480
of what all of these statuses are and
00:15:45.899
all of this logic in terms of how those
00:15:47.579
statuses play out in the actual API of
00:15:49.920
the code and I've now separated them so
00:15:53.040
that adding a new status the whole API
00:15:56.399
falls out
00:15:58.320
this argues to me that there are at
00:16:00.420
least potentially costs here of not meta
00:16:03.300
programming there is this particular
00:16:04.980
kind of complexity that the not meta
00:16:06.899
programming solution has not pretty not
00:16:09.540
then the original solution is also more
00:16:11.459
lines of code more code to maintain
00:16:13.920
again not so much not even just for bugs
00:16:16.980
but for the kind of repetition or
00:16:18.720
inconsistency sorry but for the kind of
00:16:20.399
inconsistency that you might get if
00:16:22.860
people if developers after you know a
00:16:25.079
certain amount of time with developers
00:16:26.699
adding potentially new statuses or
00:16:29.040
whatever and I understand that the
00:16:30.839
individual logic in this case is simple
00:16:32.579
but if you sort of extract this to say
00:16:34.740
shipping costs or tax law against 50
00:16:37.920
states like you can see a case where
00:16:39.920
these these inconsistencies from
00:16:42.860
structure to structure could really
00:16:45.120
build up and that the meta programming
00:16:47.220
is a way to get them under under control
00:16:51.959
so
00:16:53.279
hopefully I have convinced you that this
00:16:55.560
is a reasonable use of meta programming
00:16:57.120
if I haven't I'm sorry we're going to
00:16:59.339
pertune we're going to assume as though
00:17:00.899
I have
00:17:02.160
um but I do want to talk about how to
00:17:03.660
convince your skeptical co-worker that
00:17:05.280
you can do this that this is a valid
00:17:06.959
thing to do in your code base
00:17:09.179
um
00:17:10.280
this is
00:17:12.179
outside of the this is not just a
00:17:14.100
technical problem uh and I think
00:17:15.959
understandably the first thing that you
00:17:17.640
need to do is really convince yourself
00:17:19.079
that it's a good idea and in this
00:17:21.419
particular kind of meta programming that
00:17:23.819
I'm talking about here uh we're talking
00:17:26.579
about answering a few questions in
00:17:28.319
advance like is the code structure
00:17:30.000
driven by external data that's true here
00:17:32.340
it's also true for things like active
00:17:34.679
record active records meta programming
00:17:37.080
to to unify database columns and
00:17:40.559
attributes does the same thing the code
00:17:42.600
structure is driven by internal data
00:17:44.360
rails routes does the same thing to
00:17:47.940
enforce consistency with meta
00:17:50.100
programming to enforce the consistency
00:17:51.480
of URL patterns to controller methods
00:17:54.299
like all of those things have structure
00:17:55.919
that's driven by external data and
00:17:57.780
therefore to my mind are really good
00:17:58.980
candidates for meta programming
00:18:01.440
um Can the magic enforce the kind of
00:18:04.380
consistency that you want in your code
00:18:07.080
um you know before rails had uh
00:18:09.059
resources you had a sort of a
00:18:11.880
free-for-all in terms of what the names
00:18:13.260
of the methods were in individual
00:18:14.520
controllers and it definitely added to
00:18:16.559
the complexity of working with a rails
00:18:18.360
code base
00:18:20.220
is the code easier to use from the
00:18:22.380
outside if you're the meta programming
00:18:24.240
version in this case the user a user of
00:18:26.640
status shouldn't care one way or another
00:18:28.020
but somebody who's working on status
00:18:29.580
it's probably easier to work with and
00:18:31.200
it's definitely easier to change or at
00:18:32.760
least to make a certain kind of change
00:18:35.280
so from there
00:18:37.380
when you're trying to convince somebody
00:18:38.760
I think who is skeptical of this I think
00:18:40.980
it helps to come in humbly and not hot
00:18:43.799
and not with the meta program all your
00:18:45.299
thing all the things waving your arms
00:18:47.700
um but to understand the concerns that
00:18:50.340
they that they will have and some of the
00:18:52.919
things that are really commonly raised
00:18:55.380
as concerns here are you know how do we
00:18:58.200
know it's going to be correct how do we
00:19:00.299
know that people are going to be able to
00:19:01.260
read this how will we be able to
00:19:03.419
discover it will our tooling work with
00:19:05.580
it will people be able to search for it
00:19:07.500
like that that is a real these are real
00:19:09.539
genuine concerns uh that I don't want to
00:19:13.559
minimize I think we want to be able to
00:19:15.660
mitigate them but you have to understand
00:19:16.919
you have to in order to affect this
00:19:19.620
change in your code base and to to get
00:19:21.539
yourself to the place where you can use
00:19:23.580
these tools effectively you have to be
00:19:25.620
able to talk about the trade-offs here
00:19:27.720
and to talk about these genuine concerns
00:19:29.700
of
00:19:30.660
you know readability findability and
00:19:33.120
that kinds of things
00:19:35.039
there's a specific case argument here
00:19:38.160
where
00:19:39.780
the abstraction is such that the
00:19:42.960
argument of I won't be able to search
00:19:44.640
for this thing becomes sort of invalid
00:19:46.500
because the meta programming abstraction
00:19:48.059
is such that you won't need to search
00:19:49.799
for that thing I don't really know how
00:19:52.080
rails handles attributes internally I
00:19:54.360
just know that it matches the database
00:19:55.980
table it's not something I need to
00:19:57.660
understand to be able to use a rails
00:19:59.280
class I think this is true in many cases
00:20:02.160
in my experience is a very very hard
00:20:04.320
argument to make to somebody who has not
00:20:06.240
used meta programmed this kind of meta
00:20:08.340
programming code before and is like very
00:20:10.799
comfortable with the abstractions that
00:20:12.240
already exists
00:20:13.740
um the under the the idea that uh the
00:20:17.340
program structure might make you not
00:20:19.500
have to think about a level of
00:20:21.000
abstraction I think is a very hard sell
00:20:23.580
the first time through
00:20:26.059
later cases you might be able to make
00:20:28.260
that case but the first time through I
00:20:29.640
find I think it's challenging
00:20:32.520
um testing is really important uh for a
00:20:34.799
couple of reasons number one obviously
00:20:36.120
it proves correctness but if you write
00:20:38.039
the tests to be examples it also helps
00:20:40.500
with the discoverability and readability
00:20:41.940
issues because you can point people to
00:20:44.100
the tests as examples of how to use the
00:20:46.320
code and of the range of the kind of
00:20:48.000
behaviors that you're meta programming
00:20:52.440
um you need to document it like this is
00:20:54.299
always true but is especially true if
00:20:56.220
you're meta programming and it is
00:20:57.419
especially true if you're a meta
00:20:58.679
programming uh to a group of people that
00:21:00.840
are less familiar with some of these
00:21:02.580
structure with some of these Ruby code
00:21:03.900
structures
00:21:05.700
um specifically if you're using Define
00:21:07.380
method you need to have a comment that
00:21:09.299
shows a sample version of the method so
00:21:11.820
I didn't include these obviously in the
00:21:13.260
sample code bases but you can show
00:21:15.419
here's here's the predicate method with
00:21:16.919
the sample version of the predicate of
00:21:18.840
the predicate method
00:21:20.580
um you know all of these comments will
00:21:21.960
make the code longer which is fine we're
00:21:24.179
not meta programming to play code golf
00:21:25.679
or meta programming to simplify the
00:21:27.480
amount of Concepts you need to keep in
00:21:28.799
your head in this case the documentation
00:21:30.720
will simplify that even further if you
00:21:33.179
do it right it will also it will also
00:21:35.840
excuse me it will also manage some of
00:21:39.000
the searchability constraints because
00:21:40.260
the comments will have some of the
00:21:41.460
search items in some cases you may have
00:21:44.340
to give up on some of the IDE uh ID
00:21:46.980
issues and that is a potential problem
00:21:49.500
especially if if you're used to static
00:21:52.320
languages and you're used to editor
00:21:53.760
support for static languages obviously
00:21:55.980
that's a loss here like we want to make
00:21:58.380
this simple enough that it overcomes
00:22:00.780
that that Gap but we you can't pretend
00:22:03.960
that that Gap doesn't exist
00:22:06.120
if you're using method missing you need
00:22:09.059
to have a parallel it with with rubies
00:22:10.980
respond to missing and again also have a
00:22:13.320
comment here's uh here's a version of
00:22:15.299
the method here's a version of that code
00:22:16.559
that uses method missing for the
00:22:17.820
predicate
00:22:19.140
um
00:22:20.220
and again has a has a sample version of
00:22:23.700
what uh a real version of this method
00:22:25.679
would be like
00:22:27.659
uh so you really do need to allow for
00:22:29.580
Discovery
00:22:30.840
um
00:22:31.620
it's it's a genuine concern that you
00:22:33.960
that we need to make need to mitigate
00:22:36.539
and also if you're introducing this
00:22:39.059
stuff into a code base
00:22:40.860
um especially a code base where people
00:22:43.080
might be skeptical about it you need to
00:22:44.700
be prepared to teach it you need to be
00:22:46.140
prepared to be the local expert on it
00:22:47.820
for a while and that means that you need
00:22:49.799
to be able you need to be comfortable
00:22:51.120
with explaining it to people you need to
00:22:52.919
be comfortable with pairing with people
00:22:54.179
you need to be comfortable with guiding
00:22:56.100
people to why it's the right thing to do
00:22:58.620
when it's the right thing to do when
00:22:59.880
it's not the right thing to do uh code
00:23:02.340
review that kind of stuff like if you're
00:23:03.960
if you if you are bringing this in to
00:23:06.419
some extent you're taking an expert role
00:23:08.400
our leadership role and and you need to
00:23:10.980
sort of own that
00:23:14.100
this can be fun it can be fun both to
00:23:16.860
use this code both to write this kind of
00:23:18.780
code which is like the strength and the
00:23:20.700
weakness of it like it's fun so we
00:23:22.380
sometimes do it too much but it's also
00:23:24.120
fun so we enjoy doing it and we enjoy
00:23:25.980
talking about it and you know like I
00:23:27.900
think it's worth remembering that this
00:23:31.380
can be fun and it should be fun on some
00:23:33.900
level
00:23:35.159
um this is so uh to summarize uh let
00:23:40.500
Ruby do what ruby is good at
00:23:42.659
meta programming is really good at
00:23:44.520
reducing a certain kind of complexity
00:23:46.320
particularly where you can cleanly
00:23:48.240
separate the structure of the code from
00:23:49.679
the data that's driving that structure
00:23:51.860
stricter is not always better sometimes
00:23:54.659
it is just stricter
00:23:57.419
um I have talked extremely fast because
00:23:58.919
I did this about 10 faster than I
00:24:00.840
expected to but I have a couple uh I
00:24:04.100
therefore I get the promise
00:24:05.760
self-promotion uh this is uh version
00:24:09.000
five of the pickaxe book programming
00:24:10.860
Ruby uh it is available now in ebook
00:24:14.039
form for all of your favorite ebook
00:24:15.659
formats uh it is about two-thirds of the
00:24:18.840
way done you can get it at that URL and
00:24:21.240
with that coupon code the coupon code is
00:24:23.039
good I am told through mid-December
00:24:24.780
through December 15th so you don't need
00:24:27.600
to go out and rush and do this right now
00:24:30.179
um but and it's not like we're going to
00:24:31.860
run out of ebooks so uh uh you know you
00:24:35.760
have you have time on that uh the book's
00:24:37.620
about two-thirds done there should be a
00:24:39.240
print copy coming I would imagine spring
00:24:41.580
I'm hoping April we'll see how that goes
00:24:44.100
there's a lot of logistics involved in
00:24:45.480
that that I don't control uh my name is
00:24:47.880
Noel Rappin you can find me on Twitter
00:24:49.740
at Noel rap and on Mastodon at Knoll rap
00:24:52.260
Ruby social Ruby social normapin.com is
00:24:55.740
uh uh we can find my blog you can sign
00:24:58.440
up for a newsletter the newsletter is
00:24:59.820
sadly dormant right now because every
00:25:01.140
time I try to cite something from the
00:25:02.400
newsletter my brain says why aren't you
00:25:04.020
working on the book
00:25:05.640
um but once the book is done it should
00:25:07.080
come back I work at chime Financial
00:25:09.419
thank thank you to time for sponsoring
00:25:12.000
uh both this conference and my uh trip
00:25:14.340
here thank you all for coming out and
00:25:16.440
being a part of this community thank you
00:25:17.880
to the organizers and the people who
00:25:20.039
make all of this happen and thank you
00:25:22.080
for your time
00:25:26.700
foreign