00:00:10.639
okay hello rubyconf thanks for coming uh
00:00:16.400
this talk is dismantling dystopian futures with humane factories
00:00:21.840
uh my name is anthony navarre i am an engineer at homebot where our
00:00:28.080
mission is to empower people to build wealth through home ownership
00:00:33.360
i'm a tech lead on the starfleet team uh i'll i'll mention a little bit later about why
00:00:39.360
that name is important in the context of this talk also an amateur home chef and artist
00:00:46.239
uh my wife and i live full-time in an rv and uh i'm not handy so that comes with its own
00:00:53.120
engineering challenges uh and i'm also a new dad so he's six
00:00:58.800
months old and so i'm pretty low on sleep like all the time so this is about to get a little bit
00:01:04.799
weird perhaps apologies for that uh the lion emoji that's aspirational
00:01:12.320
uh so so why did we choose the name starfleet for our team
00:01:17.840
uh we we have a team day exercise that we regularly do within uh our our team uh and we decided
00:01:25.360
to rename ourselves uh i won't get into the the history there um
00:01:30.479
but a big theme that kept coming up in our aspirations exercises
00:01:35.680
uh aspiration what aspirations do you have for yourself and what aspirations do you have for your team a big word that came up time and time
00:01:42.320
again was inclusivity i grew up with the next generation which
00:01:48.479
is the second series of the star trek tv series but those of you who are familiar with
00:01:54.159
the series uh the original series uh it it kind of broke some boundaries
00:02:01.040
back in the day and um it was it it did a some fantastic work including uh women
00:02:08.160
and people of color as main characters in the the narrative of the show
00:02:15.520
and that was unheard of at the time and lots of other reasons why i like star trek but um but that's kind of one
00:02:23.360
of the ties in into what we're talking about here today
00:02:28.560
when asked about the star trek series from the creator gene roddenberry
00:02:35.280
in uh inside star trek which is a documentary interview style
00:02:41.680
that was done in 1976 ron berry's creator said that star trek was an attempt to say that
00:02:47.840
humanity will reach maturity and wisdom on the day that it begins not just to
00:02:53.200
tolerate but to take special delight in differences in ideas
00:02:58.800
and differences in life forms and and that really resonates with me
00:03:04.480
um this is our our team i'm really proud of them uh uh we don't
00:03:10.480
actually wear uniforms at work um so this this whole inclusivity and um a
00:03:18.319
focus on humanity is a real big part of uh who we are at homebot
00:03:23.920
uh for instance when we when we hire for people we're hiring for for the person that we're hiring and
00:03:30.560
secondarily to tech skills um we want people who are
00:03:36.319
are hungry as servant leaders and inspired when they are learning
00:03:43.920
and we also make this same bet on humanity in our product so
00:03:49.840
the loan officers and real estate agents who are our customers um we're making a bet that the digest
00:03:57.280
that we send out to their customers the homeowners that
00:04:02.560
yes of course accuracy of the data and what we're presenting that's really important in fact that's
00:04:08.640
table stakes but what's really important is that we facilitate a connection a human
00:04:14.480
connection between our customer and their customers uh that we we help them to manage that
00:04:21.759
relationship so uh as for for this talk of course i want
00:04:29.280
to talk about humanity um and i want to talk about how we try to bring humanity to one of the smallest
00:04:35.759
things we do as engineers and and that has to do with our our sample data that we use in factories
00:04:43.120
i really enjoyed matt's keynote where he talked about one of his slides was about how ruby is a human-oriented
00:04:50.080
language and that really resonates with me so i want to talk about how
00:04:55.360
at home bot we're making our factories more human oriented
00:05:02.720
how will we apply the drive principle do not repeat yourself
00:05:07.919
but not just how we're applying that principle on the code level but how we're applying that principle
00:05:15.199
on larger operational systems um that aren't actually necessarily tied to the
00:05:21.520
code um i also want to talk about how we use uh we're using factories in some
00:05:28.000
new unorthodox ways for us um that are a little bit outside of the purview of how factory bot was um
00:05:35.440
was set up originally to solve including ux research and personas
00:05:43.680
so some of the takeaways that i hope that you guys are able to to come away with are i hope you're able to
00:05:50.400
copy us and and apply some of these things to your own data systems
00:05:55.680
but i hope you find ways to apply other principles to
00:06:02.720
higher order systems maybe other solid design principles uh maybe something out of this talk
00:06:09.039
rings a bell for you and you're like i could i could use the open close principle to how i manage my ci systems
00:06:15.120
i don't know uh one thing i won't do uh is is i i won't
00:06:21.440
include statistics or data about how these uh these practices have uh shaped or evolved uh what we do at
00:06:29.039
homebot uh this is more about some things we're trying out and and hoping that you guys
00:06:35.280
can get some mileage out of them too so uh let's talk about some code
00:06:41.120
uh by show of hands who here has never used factory bot
00:06:49.199
okay who here has never heard of factory bot okay
00:06:54.720
so i'll give a very kind of brief uh description of what it's here for and
00:07:01.120
what we use it for to try to make sure we're all on the even keel here so
00:07:06.639
you're you're writing tests for your ruby code and you need some sample data
00:07:12.400
one of the ways that you might go about getting that sample data set up is just with plain old active record
00:07:19.120
instantiation here i have a contrived example about
00:07:24.400
books so in this test example we're expecting
00:07:30.479
uh this book record to be compelling if the author record has the experience flag of true
00:07:36.639
uh so so here we're just instantiating uh author and book our active model
00:07:42.840
records directly in the test nothing wrong with it here but if if your test if your system is growing over time
00:07:49.680
chances are it might eventually grow to look something like this uh the the book model here has grown
00:07:56.720
over time such that we have all these other attributes that are required in order for that model to be valid perhaps
00:08:03.280
we have a title presence check that's needed on on book and that there needs to be at least
00:08:10.639
one publisher at least one chapter right the detail here about experienced the
00:08:17.039
author being experienced it's still there but it gets lost in all this noise so it's not as clear
00:08:23.599
what it is that's important to our system under test here so one of the things you might reach for
00:08:30.960
especially if you've just booted up a fresh rails app you might decide i'm going to use fixtures fixtures is
00:08:36.640
something that you can use right out of the box and you might use a yaml file to
00:08:43.680
provide some canned sample data here's a list of some ruby books
00:08:49.120
that you might find in a books yaml file and the test looks pretty similar
00:08:54.800
where now we're sampling that data instead of uh providing like literal values in the
00:09:01.760
um by instantiating the active model records directly we're pulling them out
00:09:06.800
of the fixtures data but you'll notice here that we've lost the experienced true
00:09:14.320
attribute we're no longer passing it on you have to kind of keep both the yaml file and the the test up in order to
00:09:20.959
know so so this this is kind of the problem that factory bot
00:09:27.360
solves um you can define all of those default
00:09:32.399
attributes that are needed in a separate factory file and then in your test
00:09:38.640
you use either build or create depending on whether you want to instantiate a new record or instantiate
00:09:46.160
and save it to the database but the important part here is that build or create
00:09:52.720
method that's going to automatically give you back uh an active model instance that has all of
00:09:58.880
those defaults that were declared in the factory but it also accepts overrides right so
00:10:05.200
that experience true flag that doesn't get lost anymore and we have it right there ready to go it's easy to tell from the
00:10:11.839
test what's important uh to what you're testing any questions before i keep going
00:10:20.000
okay cool all right so so this is this is part of a larger diagram that
00:10:26.880
i'll i'll show the entire thing but this is the little corner that factories were
00:10:32.399
originally set up to solve for is that you you use them in your specs to get some sample data going
00:10:38.959
um and hopefully it's it's clear that that already we're applying that dry principle of
00:10:44.720
don't repeat yourself in that if i'm doing several different tests
00:10:49.920
that need to interact with these same models i don't need to provide those same
00:10:55.600
boilerplate required details and every single time i instantiate a book right
00:11:00.880
so what i want to talk about here though is is how how
00:11:06.240
we're applying that dry principle not just your tests not just your specs
00:11:11.279
but how we apply them to some higher order systems like let's say for instance our newest team member on on the
00:11:18.399
starfleet team his name is andy and he needs to get his machine set up so what do you need you need sample data
00:11:25.360
in order to run run the app as it's intended um
00:11:30.720
or perhaps in your qa environment you need to you've you're done building the the new feature and you've shipped
00:11:37.200
it off to a qa server again you need the sample data there
00:11:42.720
um so you shouldn't have to go and manually
00:11:48.160
set up that data over and over again um so yeah so here's some of those those
00:11:54.720
questions that come in your qa automations team might say we need the sample data to run our end-to-end tests
00:12:00.800
and ensure integrity there right so
00:12:07.200
so what do i mean by humane factories uh so i i have these these three uh clean
00:12:14.480
common and creative just as like a a mental rubric to to keep it in mind
00:12:22.000
in order for a factory to be humane i think we need to talk a little bit about what does it mean to have humanity
00:12:27.920
um why is clean on this list well uh if if you doubt at all
00:12:34.320
that cleanliness is required for humanity to happen of course you can just put just a little
00:12:40.000
bit of filth on your nose then go out in public and see how quickly humanity evaporates right it
00:12:46.880
just takes a little bit so so things need to be clean and common here what i
00:12:52.560
refer what i'm using that word here is referring to the things we share in common and the ways that we
00:12:59.279
work together as humans to achieve common goals so as it relates to factories having common
00:13:06.320
language is really important so i'm going to get into that in a minute and i say i suggest that
00:13:13.360
by way of setting up your factory to be clean and common that will enable them to be used in more
00:13:19.920
creative ways outside of their original intention uh so so what i mean what do i mean more
00:13:26.399
specifically by clean factories um let's say for instance i i ask you
00:13:32.639
give me an example of an author and you say well what kind of author
00:13:38.000
i might think that you're just being a jerk right but our systems are even worse if you've
00:13:43.600
got a system that is uh invalid by default right like if you
00:13:48.880
need to provide additional attributes to create that author uh and you didn't provide them
00:13:56.000
then you're gonna get an active record record invalid error the moment you try to do this um and that's just rude and lacks
00:14:03.120
humanity right if i'm asking you give me an example of something um maybe in a given
00:14:09.360
context you might need more more details uh about what i'm asking for but generally speaking uh
00:14:16.560
in order for it to have humanity uh i ask you something go ahead and give it to me all right so um
00:14:22.800
so factorybot provides a utility to help us manage this
00:14:28.079
over time uh right in the factory bots getting started on the repo there's a
00:14:34.240
a section on how to do linting for factories so over time you don't necessarily need
00:14:40.240
to check these manually we have a rake task that we run that's
00:14:45.839
uh very similar to the way that they're uh that they recommend here
00:14:51.360
and if any of your factories are invalid when running creator build
00:14:58.399
this will tell us so if i've introduced some some change to a factory uh that that makes the
00:15:04.480
factory invalid i'll know right away um
00:15:09.920
who here has needed to do something like this yeah
00:15:15.600
right this is super bogus right like i just want to be able to get an example of it and it should be ready to go out
00:15:22.000
of the box so um so more of the story here link to your factories
00:15:27.199
um maybe there are other things that go into it besides whether or not it's valid um in terms of like maybe there
00:15:32.720
are association dependencies or some other um some of the things that you need to consider in your app
00:15:39.040
that are important but the the gist of it here is that it should be really easy to to ask for
00:15:45.680
the sample data that we need and i'll also say that
00:15:52.160
if you if you have situations like this where you have a couple of different
00:15:57.440
examples of uh factories that maybe vary um here's here's one where the factory
00:16:04.240
is author with books in multiple languages this is an opportunity to refactor that
00:16:09.519
idea of with multiple languages to refactor that to a trait here i've
00:16:14.560
called it multilingual and this is what it would look like to set up that trait
00:16:20.720
in factory bot so just by passing that multilingual flag
00:16:27.279
the languages attribute on that author model gets populated
00:16:34.320
okay who here is familiar with conway's law
00:16:40.959
a few hands conway's law states that organize organizations design systems
00:16:48.480
will mirror their own communication structure and i would like to suggest that uh
00:16:56.000
this principle is something that we can lean on here and we can lean on a lot of different places but the way that
00:17:01.759
it it shows up here for factories is with that idea of common
00:17:06.959
um so what i i would like to suggest is if you take the time to match the language that you use
00:17:14.720
with your peers with your colleagues to match that language with the language that you use in your
00:17:21.039
code that uh that will pay off for you in spades
00:17:26.959
so this also by the way means that um that you shouldn't need to repeat your factory setups in multiple
00:17:33.440
different apps if if different apps need the same sample data that you should have a means by which
00:17:39.679
to get that sample data into your different apps without duplication of of definition
00:17:47.039
uh and i'll talk in a minute about how one of the ways that we do that across multiple apps at homebot
00:17:55.600
um and so by way of having clean factories that are written with common language
00:18:04.240
we are free to then use those factories in creative and unorthodox ways
00:18:11.440
you recall earlier that we've got all of these these different places where
00:18:16.880
where the sample data is needed for different reasons so i want to talk a little bit next
00:18:22.720
about some of the other things that come up like your happy path is maybe taken care of
00:18:28.400
uh by way of of setting up your specs here on the left and uh by way of working with your qa
00:18:36.320
team maybe you found out that there are also some edge cases
00:18:43.200
that need to be taken care of and your ux team maybe has uh
00:18:48.640
has come back to you and said well we also need to take care of different languages and locales
00:18:53.760
that you know it needs maybe behave slightly differently um and we need to to accommodate for
00:18:59.840
differently able your security team maybe has come to you and said that uh we need to
00:19:06.320
make this a little bit tighter uh of a feature for when a bad actor comes along and tries to to hack it
00:19:14.240
and maybe your sales team is telling you that uh when they're talking to people who are
00:19:19.919
on the go in the airports and they're they're using the app on a mobile device there are problems there there's all
00:19:25.760
kinds of of these different cases that are outside of maybe the happy
00:19:31.280
uh the happy flow that you designed for in the first place
00:19:37.200
and many other that i didn't consider when i was making this light of course um so one of the the tools
00:19:44.080
that uh that we use at home bought on our ux and design teams is the
00:19:49.600
persona in concert with user journeys and all kinds of other
00:19:55.760
ux tools um on our team at starfleet this is matt on the right or sorry on
00:20:02.240
on my left you're right yeah you're right uh that's matt he's our ux researcher and
00:20:09.840
designer on the starfleet team and he's the one who's responsible for for building our personas
00:20:17.280
and what a persona is in his world persona is provides a rough approximate
00:20:23.679
approximation of our users it's a conversation starter a way to arrive at shared understanding
00:20:30.000
of our audience and a lot of thought and effort goes into creating
00:20:37.200
these fictional representations of our real world customers
00:20:43.280
things that go into it we we want our personas to to represent a deep understanding
00:20:49.760
of the demographics of the individuals but also what are their needs and
00:20:54.960
uh what kind of tasks are they going to go in to perform and how patient are they going to be
00:21:00.000
with your loading indicator so i mentioned a minute ago that we will
00:21:06.320
couple these with something like a user journey that's what uh this is what one of those might look like
00:21:12.159
this is one that we did recently for starfleet again this this ux research and stuff i
00:21:17.919
depend wholly on matt for uh for getting this stuff real dialed in this is not my wheelhouse um
00:21:24.480
but it is important that i uh am capable of work working it into
00:21:30.400
my work one of the things that we've done to to try to make it more accessible to everyone working at homebot is
00:21:38.000
that we have a wiki setup and one of the things we have there is a central location where all the user research is
00:21:43.840
accessible but just by having it in a central place doesn't guarantee that it gets used and
00:21:49.120
referenced right in an article titled why personas fail
00:21:54.640
by kim salazar it stated that personas should not be unveiled like a piece of artwork
00:22:01.919
because if so people will use them like a piece of artwork they'll pin them up on their cubicle
00:22:07.120
wall to admire once in a while uh i i chose a kind of like cyberpunk
00:22:14.960
theme when i wrote the description for this because in r in coming up with material for this
00:22:21.039
i i was often reminded of um this description uh from
00:22:27.120
the book is called burning chrome from from sterling and collins
00:22:34.080
and it describes cyberpunk as low combination of low life and high tech and
00:22:40.559
and that's that was really resonating for me with how it feels when you get that record invalid when when there's
00:22:47.360
a disconnect in the the between the the tech that we built
00:22:52.720
and the humanity that it was meant to serve right so so where did that
00:22:58.960
where did that disconnect happen well in that why personas fail uh article um salazar mentions these five reasons
00:23:08.240
but i'm only going to focus on these two i'm not going to try to address the
00:23:14.640
others right now these two here state personas were created in a silo and imposed on people
00:23:20.880
or that there was a communication failure and people didn't know what they were or
00:23:26.159
how to make them useful a lot of the research that i did coming
00:23:32.559
across this said that it's really important that you evangelize personas with your developers and encourage their
00:23:37.760
use etc but this was really important that the
00:23:43.120
more that people engage with the persona and see them as real the more likely they are to consider
00:23:48.400
them during the process design and want to serve them so so this
00:23:54.720
the way that we use our factories in this way i want to argue that
00:24:00.799
integrated use is far more important than evangelized use
00:24:06.559
uh because matt can tell me all day that it's really important to understand and use the personas
00:24:12.640
but if i if i integrate their use directly into my factories it
00:24:19.120
it leads to a much higher chance that the work represented by the personas is
00:24:24.960
going to get uh incorporated into what we deliver
00:24:30.240
um so so here are some of those ways that we uh use factories in slightly unorthodox
00:24:37.760
um ways at factory plot all right sorry at home bot
00:24:42.799
um we use them for seeding our dev and qa staging environments
00:24:48.880
we also use them for end-to-end tests in concert with a hanger gym i'll talk in a minute
00:24:54.240
what what the details are and how that works and as an experimental thing we're also
00:24:59.679
starting to look at how to um i don't have a better nickname for this but when i get to the part um maybe
00:25:05.840
you guys will have some suggestions i'm calling it future proofing with loops so let me talk about what these are in a
00:25:11.840
second so the creator of factory bot actually
00:25:17.039
points out that that there are some risks with using seeds or sorry using factories in your seeds
00:25:24.000
for instance your default attributes might change or you might have some migrations that happen
00:25:29.600
and you have to incur the cost of keeping those things in sync moreover
00:25:35.760
item potential is often required in your seed layer so i'll submit to you though for your
00:25:42.400
consideration that um that these things are okay if you're not in production
00:25:48.480
right i'm willing to incur the cost of keeping my seeds and my factories
00:25:55.039
kind of in sync with one another in exchange for the value that i'm getting to be able to
00:26:00.880
uh rely on those for spinning up sample data for my staging qa environments
00:26:09.679
and also for eye components we can rely on attributes for so factory bot provides us with this method attributes
00:26:16.240
for this is what it might look like inside of a seed rake task
00:26:21.679
where we're using finder create by to still get item potents
00:26:26.720
but we're using attributes for and theoretically we only need to update attributes in our factories
00:26:34.799
um and what i'm missing here in this example is we're not doing a production
00:26:40.000
check right so
00:26:45.039
i also mentioned that we use the hanger gem for end-to-end tests this is what
00:26:50.240
a setup for initializer looks like there the gist of the hanger gym is that it exposes some restful endpoints
00:26:56.880
for um for all of the factories that you have in your system and the benefit to using that
00:27:04.320
is that in our end-to-end test in our case we have our end-to-end system written in uh in node and using axios
00:27:12.559
you could use whatever i suppose but um but this is what it would look like where
00:27:17.600
we're exposing a books endpoint and we might
00:27:24.080
expose a create author method here that should then create
00:27:29.600
books um and then future proofing with loops
00:27:38.240
to allow our systems to grow over time i don't care where this persona's variable is coming from in your system
00:27:45.360
maybe it's just an array this is very experimental for us but the gist here is as you add more
00:27:51.039
personas over time uh if you add a new persona then hopefully our tests will will break to
00:27:57.600
tell us that the old feature no longer works for that new persona
00:28:02.880
and doing something similar with separating out the behaviors so the example that i provided earlier about
00:28:09.279
a bad actor right so so maybe it's a bot
00:28:15.360
here here we would expect that we'd have an exception that would be raised if you create an author and they have the bad
00:28:21.760
actor behaviors um
00:28:30.559
so uh yeah hopefully this gives you an idea of um
00:28:36.559
of how we're using factories in in uh kind of creative ways this is kind of the full
00:28:43.360
diagram where we have our factories and a subset of those are personas or maybe
00:28:48.960
also behaviors they're still used to satisfy our specs and our hangar endpoints
00:28:56.080
make it possible for our end-to-end tests to work across multiple apps i also have here up in the top right
00:29:02.960
that um we may even have rake tasks that help us to spin up data across multiple apps in
00:29:09.600
the indian test suite but that relies in in turn on the hanger
00:29:15.039
restful endpoints and then rate tasks to spin up feature specific
00:29:21.760
seeds in your dev and safety and qa environments so so that's it for my
00:29:29.200
talk if there's any time left there's very little i think i'm happy to ask answer any questions
00:29:36.880
otherwise you can probably find me at the homebot booth in the exhibit hall
00:29:43.360
or you can reach me at anthony navarre homebot.ai or i never use twitter but there's a
00:29:50.480
chance you might find me there at anthonyvar thank you very much for your time
00:30:03.120
any questions yes yeah um the question was how do we reset
00:30:10.159
seeds when we're having qa uh do some testing did i get that right
00:30:15.600
yeah so um so you may have noticed that that we set
00:30:21.440
those seeds up on rake tasks and so
00:30:27.279
of course we have the the typical db reset that's always available to us
00:30:33.360
and then the the base seeds to run but then uh
00:30:38.399
hopefully we've done a little bit of extra work in our planning process to say oh okay for this one it's going to
00:30:43.440
be a little bit trickier to do qa on this so we'll take the time to
00:30:48.640
uh to set up a rake task that that spins up the the data that's necessary for
00:30:53.760
that feature to work as expected uh and and sometimes maybe even setting up the
00:30:59.120
rake tasks such that it will provide data that will take care of the different uh scenarios
00:31:06.880
so so maybe you need to test out pagination and it's important that you
00:31:12.399
have covered the the zero case you've covered the uh i've got one page worth of records
00:31:18.399
i've got 10 page worth of records right so all of those might be part of that
00:31:24.399
rake task that we set up or a couple different rate tasks and if we've been
00:31:30.640
even slightly clever about how we name them and organize them then uh hopefully it's just a matter of running a rake
00:31:36.880
task on the staging server
00:31:42.640
my home bot guys keep me honest here if i'm if i'm missing anything yes i've got
00:31:48.000
another question back here uh the question was how how to back out
00:31:54.080
of a scenario where you've got some bloat in your factories right is that fair
00:32:00.960
um and i think that there's definitely digging to do in those situations uh to try to
00:32:08.559
hunt down i would be tempted in that sort of situation to try to do an audit of like identifying what are all of the
00:32:14.720
different use cases of where the factory is in use so that we know uh where we're
00:32:20.080
starting um a quick way to to help you get started on that audit is rip out the
00:32:26.399
factory and see what breaks right and if you've got really good test coverage that might be a really fast way
00:32:32.000
to get some early signal on on what needs to happen but of course if you if you have less
00:32:38.399
than ideal test coverage there may be more manual process to do there after that i think it becomes an
00:32:44.480
exercise in refactoring and refactoring as a discipline i think is its own
00:32:50.159
set of skills i don't think i'm going to attempt to broach that topic here because it feels
00:32:56.480
like a that would be its own hour-long talk for me um but yeah that that's some of the initial
00:33:03.600
things that come to mind for me i hope that's useful
00:33:10.080
does anyone else in the audience have tips on that i would love to know
00:33:15.279
all right i don't see any more hands but please uh feel free to get in touch with me if you think of any other