-
ERIC ROBERT: All right, hi. I'm Eric Roberts
-
and I'm here to talk to you all about
-
how you can use software design patterns
-
to put your Rails app on a diet
-
and make your tests run really, really fast.
-
Jokes aside, we will be telling you about
some
-
design patterns. Not so much making your tests
run
-
fast. But we're here to talk about domain-driven
design
-
hexagonal architecture in Rails.
-
I'm Eric Roberts. I'm a software developer
and I
-
work at a company in Waterloo, Ontario, Canada
called
-
Boltmade. I met Declan when we worked together
at
-
PrintChomp. Before that, I was a frontend
developer for
-
a number of years, and I'd worked around Rails
-
applications, but mostly at the view layer
until Declan
-
dragged me kicking and screaming into backend
development and
-
made me care about stuff like we're talking
about
-
today.
-
And this is the biggest crowd I have ever
-
presented in front of. So if you'll excuse
me,
-
I need to take a picture and email my
-
mom.
-
DECLAN WHELAN: OK. Hi everybody. Real pleasure
to be
-
here. My name is Declan. I'm the co-founder
of
-
a company called PrintChomp, and my story
is about
-
two years ago, I had a opportunity to launch
-
PrintChomp, and I was looking at technologies,
and I
-
decided that Ruby on Rails was really the
best
-
platform for us. The only challenge was that
neither
-
me nor anybody on my team knew Ruby nor
-
Rails.
-
So it was kind of a brave, maybe, decision,
-
but it's one that I don't regret. And one
-
of the things that drew me to the community
-
was the fact that, or, to the platform, was
-
the community around sharing, around the openness
of, of,
-
of sharing code and, also, a lot about, about
-
the test-focus, which has been pretty important
to me.
-
But the cool part, I think, about it, was
-
we intentionally took on a lot of technical
debt,
-
because I knew that, I knew that I would
-
not know enough about our domain. It was a
-
new domain for me, printing, and I also did
-
not know enough about Ruby. I did not know
-
about, enough about Rails. So, very intentionally
decided to
-
do our best, the best that we could, knowing
-
that we would end up, very likely, with a
-
pretty heaping mound of technical debt.
-
And that turned out to be true. And has
-
anyone had that experience? I don't know.
Yeah. So,
-
but recently we had an opportunity to build
an
-
API, and that was really exciting for me.
And
-
I know there are gonna be some other talks
-
about APIs here later, and I realized that
I
-
had, I had two kind of competing things that
-
could come together. The first was, I had,
I
-
had logic in our application that I needed
to
-
share in our API. How was I going to
-
do that?
-
And all of our code was sprinkled through
various
-
bits of our controller and model logic. Secondly,
I
-
wanted a mechanism to, to have a strategy
for
-
eliminating the technical debt, and what I
turned to
-
was domain-driven design hexagonal architectures,
and I want to
-
share what we've learnt along the way of doing
-
that, and, and where we're going. So I hope
-
you're able to learn something from what we've
done.
-
E.R.: That's great Declan. But what are they
gonna
-
get out of it?
-
VIDEO
-
??: Here's a good idea. Have a point! Makes
-
it so much more interesting for the listener!
-
D.W.: Well, that was from Sandy Metz. He said,
-
you know, if you're gonna have a talk, you
-
should really have a point, and I think Steve
-
Martin said it pretty funnily. And I guess,
our,
-
our number one point is that, there is complexity
-
in the software that we build. There's complexities
in
-
the problems that we're solving. And we need
to
-
embrace that complexity and embrace it in
such a
-
way that we tackle it and deal with it.
-
And deal with it head-on. And by doing that,
-
then we end up having more joy and fun
-
in our work because it's not just about getting
-
this functional piece to work, it's about
really trying
-
to understand our domain and model it and
express
-
that in our code and make our code as
-
expressive as possible.
-
And the second thing that I really realized
was
-
I knew that our code was a mess, and
-
I knew some point refactorings that we could
do,
-
but I didn't know how to, how to, you
-
know, what did the end look like? If it
-
was refactored significantly, what would it
look like? What
-
would the shape look like? What would the
namespaces
-
be? What would the classes be doing, et cetera.
-
And domain-driven design and hexagonal architecture
helped me envision
-
and share with my team what it might look
-
like.
-
The third thing that, that, that we would
like
-
you to take away from this talk is that
-
there's a lot more to just being a Rails
-
developer, the, the ideas and patterns, if
you will,
-
that we, that we're talking about are, some
of
-
them have been written by some of those people
-
that DHH had in his slide, including James
Coplain.
-
But a lot of those patterns have been around
-
for a long time. SO those patterns and those
-
ideas and those practices will serve you well
beyond
-
Rails. They would work in a node application.
They
-
could work in a desktop application. They
can work
-
in a wide variety of areas. So by getting
-
some familiarity with these concepts, you're
able to transfer
-
those skills to things beyond Rails.
-
And so I want to ask Eric just to
-
walk us through kind of some of the, some
-
of the pain that we had with our initial
-
Rails development and see if it resonates
with you.
-
E.R.: All right. So everyone knows what this
is.
-
It's a Rails folder structure. And it's really
great
-
when you get started with Rails. You have
these
-
folders. OK. I, I logically, my things fall
into
-
these areas. Controllers, models, and views
are really what
-
we're focusing on right now.
-
But if the responsibility of your code doesn't
start
-
with M, V or C, what do you do
-
then? And we, and we find it kind of
-
goes like this. You have, you have these areas
-
of responsibility and you have something that
doesn't really
-
fit, and you don't know where it goes, so
-
you just put it on somewhere and things get
-
a little bigger.
-
And continuing on, you keep doing this, things
get
-
bigger, and finally, like, the line between
all of
-
these things is, is blurred. You don't know
what's
-
what. It's hard to extract reusable parts
from all
-
of this, because the, the responsibilities
are split across
-
all these things.
-
And you kind of end up with methods like
-
this. This is one method. It starts on the
-
left and ends on the right. It's about ninety
-
lines.
-
It's not from PrintChomp. It's from another,
another project
-
that I've worked on. And without setting,
it doesn't
-
really matter what it does. The point is it's
-
ugly and you know, it is actually about setting
-
prices on properties and the date ranges are
available.
-
So I have a question. We need to add
-
sales tax to the prices.
-
Anybody care to take on that refactoring?
-
It's pretty horrible. But nobody, nobody sits
down and
-
says, I'm gonna write a ninety line method
today
-
that does property prices with date ranges.
The initial
-
spec was probably something a lot simpler.
And because
-
it's in that spot now, the next person who
-
comes, comes and looks and that method and
goes,
-
oh, well OK, well if I just type this
-
little bit more it'll, it'll do that now.
-
And this was a little bit of a train
-
wreck. At some point you probably, the people
working
-
on this, including myself, probably should
have realized, you
-
know, forty-five lines might have been the
time to
-
split it up. Maybe twenty. Maybe less.
-
But this is, nonetheless, what we ended up
with.
-
Or, you end up with Rube Goldberg machines
for
-
sharpening pencils.
-
So there's a lot of well-known patterns that
can
-
help you out with this. Has anyone read this
-
blog post? Yeah. Anybody use any of the patterns
-
in them?
-
They're pretty great, right. We use a lot
of
-
them, and I'm, we're gonna tell you about
some
-
of them here. But the one thing you've, so
-
you've extracted all of these things into
small responsibilities.
-
Your models, your controllers and your views.
They're all
-
small again.
-
But, OK, so what? I have a bunch of
-
little objects that all go, they all know
too
-
much about each other. They don't fit in any
-
logical structure. They don't, how, how does
this all
-
fit together? You've made, like, an awesome
first step,
-
in that you have small little pieces that
you
-
can use. But where do you go from there?
-
And we think that looks kind of like this.
-
We think that your domain concepts, services,
entities, should
-
be in the middle, and everything else is outside.
-
Your database is an extra concern, your views
are
-
an extra concern. The web, and you know, when
-
you're designing the API, as Declan talked
about a
-
little bit, it's an extra concern. So you
can
-
really focus in on the middle of what your
-
application actually does.
-
I'm gonna let Declan talk a little bit more
-
about that
-
D.W.: Has anyone here heard of domain-driven
design? Oh,
-
quite a few people. Awesome. How many people
have
-
actually, you know, intentionally used it
and, and have
-
worked with it? So, a, a number. SO cool.
-
And it can be quite, it can be quite,
-
it can be quite daunting. And this book by
-
Eric Evans is kind of what kicked it off.
-
And this book was I think written in 2005,
-
and it is a really, really great book, but
-
it is actually quite difficult to read. But
it's,
-
I think it might be the only technical book
-
I've read twice.
-
And that's partly cause it was really good
and
-
partly cause it was rather difficult to get
through
-
some of it. Did anyone else read this book
-
and have a similar experience? like, it's
really great
-
stuff and you kind of read and it and
-
you go, wow, what does that mean to me?
-
Right?
-
And we, at the end, at the end, we'll
-
be posting our deck, and we'll have some references
-
to other material that, that I've actually
found to
-
be a bit more addressable or a little more
-
consumable.
-
But what Eric Evans talked about was really
tackling
-
complexity, and he talks about the, you know,
the
-
critical complexity is really understanding
the domain. What are
-
the business rules that take place inside
our systems?
-
If we're gonna add sales tax, what are the
-
business rules for that sales tax?
-
What are the, what are the rules around who
-
can buy what? And by putting those insides
and
-
thinking of them as the domain of our system,
-
then we're able to have our outside layers
just
-
be, if you will, relatively thin facades,
which allows
-
us to reuse that logic across APIs, across
other
-
applications. We don't have to duplicate all
of those
-
business rules.
-
And the way that he proposes to do that
-
is through ubiquitous language. And this is
a picture
-
of the tower of Babel and if anybody knows
-
the story, it's where everyone in the world
was
-
speaking a different language and, I once
worked on
-
a project that was a financial transaction
processing system,
-
and when I inherited it, the guy who was
-
proceeded me had this, was a model train aficionado,
-
so he had the idea of model trains. So
-
every transaction was like a car, and the
payment
-
engines were, were train tracks. And he had
all
-
of these metaphors around transaction processing
and trains, and
-
was written in Java.
-
So when I was asked to add a new
-
feature, fix a bug, I had to understand the
-
business domain, and then I had to kind of
-
understand, how did that translate into train
speak, and
-
then I had to go look at the Java
-
code to figure it all out, right. So the
-
coding was easy. The hard part was really
trying
-
to understand what was being asked and how
did
-
the code express that, right?
-
And that's what Eric Evans is talking about
with
-
ubiquitous language. We want to have the language
that
-
we speak with domain experts should be readable
in
-
the code. If I'm order, if I'm a customer
-
and I can purchase a product, there should
be
-
a class called customer. There should be a
class
-
called product. And there should be a verb
in
-
there that's somewhere that says purchase,
et cetera.
-
So that there's minimal translation between
the domain experts'
-
language and the language that my code is
written
-
in. Ruby gives us a great opportunity to do
-
that, but this is much more difficult in,
in
-
other more statically typed languages.
-
So that's kind of the, the key thing to
-
take away from domain driven design is to
try
-
to have your, your concepts expressed in code
that
-
are meaningful in the words people use.
-
If they use the word customer, you should
have
-
a customer class. If they use the word user,
-
you should have a user class, et cetera.
-
But beyond that, it also has some kind of
-
key, I, I dare not say it, patterns? Now,
-
I'm almost nervous now to say it.
-
But let me be clear. This isn't science. It's
-
not, right. Because these patterns were not
dreamed up
-
in academia ivory towers. These patterns that
we talk
-
about were empirically derived from people
intentionally doing what
-
we do, which is write code every day, intentionally
-
thinking about, how does that, how does those,
how
-
do those things fit together, and what is
the
-
essence of what I'm doing?
-
And can I extract that into words that I
-
can use to communicate with other people?
The beauty
-
of patterns is I can talk about a value
-
object, and if you know what a value object
-
is and I know what a value object is,
-
we can have a much richer conversation than,
oh,
-
I have to have an object whose state is,
-
whose identity is defined by the state of
its
-
attributes and then, you know, we can have
a
-
much richer conversation.
-
E.R.: You might say you ubiquitous language.
-
D.W.: Yeah. So we're gonna touch a little
bit
-
on some of these patterns. But, but the idea
-
is that these are not academic ivory tower
concepts.
-
These are empirically driven from people who've
worked in
-
the field. And if we're gonna, if we're gonna
-
be successful as an organization, while I
fully agree
-
that we need to go out and write code
-
and we need to read code, I totally think
-
that's true, but we also have to have more
-
effective ways of communicating knowledge,
so that we're not
-
all learning the same things from each other
over
-
and over. WE can learn more easily from each
-
other. And that's what these patterns are.
-
And the next kind of piece that we're gonna
-
talk about is hexagonal architectures. And
it's more than
-
just that. I think we've alluded to a little
-
bit. It's really the idea of, you're going
to
-
have this core domain in the middle, and in,
-
inside your code, surrounding your outside
core are gonna
-
be some application level code that expresses
the rules
-
of your application. And I would draw it slightly
-
differently, perhaps, but, and then we have
adapters on
-
the outside that adapt that code to web calls
-
or database calls or SNTP, or in my case,
-
APIs.
-
And so that's the way that we want you
-
to, that's the way that we are starting to
-
approach the work at PrintChomp is thinking
about it
-
in those constructs. And now we want to jump
-
to some specific patterns and, and show you
some
-
real code that actually, you know, brings
these to
-
life. So Eric, you want to talk about form
-
object?
-
E.R.: Sure. Unfortunately, I can't tell you
what your
-
domain is or what necessarily goes in the
middle
-
of that hexagon. But I can give you some
-
ways to keep other things out of that hexagon
-
that you don't need to be concerned with.
-
One thing that I've been doing lately is form
-
object. One of the really cool things, you
know,
-
if you run Rails scaffold, some model name,
you
-
get a form that you submit, creates the record,
-
edits the record. And that's pretty great.
-
But how do you do that when you don't
-
have a direct one-one mapping with an ActiveModel
record?
-
So instead of instantiating an ActiveModel
record, I've taken
-
to instantiating, I'm gonna call it a form
object.
-
There's a lot of names for a lot of
-
different things. But this is, this is what
I've
-
been calling it.
-
So here's the actual thing that I was building.
-
On the left hand side, you see that you
-
select a ticket price. On the right hand side,
-
your name, email address, and your payment
details. And
-
this is actually two ActiveRecord models in
my database.
-
The, the passengers over there on the right,
you
-
can add a passenger and keep adding it.
-
And if you've ever worked with nested attributes,
probably
-
know it's not always that fun. So this is
-
not using nested attributes. It's done like
this. I
-
have a class TicketForm that includes ActiveModel::Model,
which is
-
how I get nice things, like that magic initialize
-
method of validators.
-
And the passengers method, if I don't have
any,
-
returns me a passenger new. That's how it
puts
-
the name and email address for that first
passenger.
-
And then tickets, I get out of this by
-
taking my passengers and mapping them into
new objects.
-
In the controller, it looks a little bit like
-
this. So you just pass your params off into
-
that. You get it back out and you have
-
tickets. So instead of if ticket dot save,
I
-
do if ticket_form valid and ticketCharger
charges successfully, then
-
we've had success. And ticketCharge takes
care of charging
-
my tickets and knowing that, there was only,
cause
-
there's only one charge for all the tickets,
right.
-
You're paying all at once. No point to split
-
that up.
-
So that's a really useful thing that I've
found
-
to, to help when my mappings aren't just totally,
-
I don't want to just take a record of
-
the database, put it in, or update it.
-
And now Declan's gonna tell you a little bit
-
about request objects.
-
D.W.: Yeah. In this case, has anyone used
a
-
form object or something like that? So quite
a
-
few people. Cool.
-
Has, has anyone done, used something called
a request
-
object? Sort of? I was hoping that I invented
-
this. So maybe I haven't. I don't know. OK.
-
But, request object is now in, you know, think
-
of an API as, we're trying to have a
-
similar behavior to the form object, except
we're trying
-
to take, remember, we're trying to take complexity
out
-
of our controllers and out of our models and
-
put them into more, to simplify our systems.
-
So the idea with the request object is that
-
we're gonna pull that code out and put it
-
into the, into the controller. And now the
request
-
object is going to receive the request. And
the
-
code looks sort of like this, right.
-
There's, I, I've done this slightly differently
than Eric's,
-
Eric's way, in terms of, of, the kind of
-
the core of the class. The core of this
-
class is using a gem called Verdis, which
does
-
something similar to ActiveModel::Model, except
this allows you basically
-
to have a plain-old Ruby object and, the way,
-
and, the cool part is, that, or, I think
-
it's cool. You can, you can declare attributes,
like
-
this. So I have actually, in my domain layer,
-
I have something called the customer and the
billing
-
and the shipping. And if, if somebody supplies
me
-
those three things, then I can complete an
order
-
in my system.
-
We've, there are a couple of pieces missing
here,
-
but we wanted to keep it, fit in a
-
slide. But that's basically it. And we have
the
-
validation. And the cool part about this is
that
-
when a request comes in, we just, I just
-
put in a before loop in the controller that
-
has a before filter that just basically instantiates
the
-
request object using some, some reflection
to figure out,
-
you know, what is the, what is the controller
-
and what is the action being asked, inferring
the
-
request class, instantiating it, and then
just passing it
-
what used to be the params hash.
-
But now it's actually a rich object that I
-
can have validations on, et cetera. So the
net
-
effect of this is that, why would I bother
-
doing this, right? Well, now the controller,
you know,
-
the complexity around validating the request
is at the
-
boundary of my system. That doesn't need to
leak
-
into the rest of my system. It's almost like,
-
you know, does anybody use, you know at the
-
beginning of your methods, you want to put
the
-
guard clauses to catch the exceptions coming
in at
-
the beginning of your methods, so that the
rest
-
of your method is simpler?
-
This is doing the same thing, except it's
doing
-
it at, at a higher level abstraction, at the
-
API request level. And I, this has worked
out
-
really well for us. So I, I quite like
-
that one.
-
Yeah.
-
E.R.: Great. Service objects are another one
that we've
-
been using. I think DHH actually had one in
-
his presentation. I'll give you a hint, he
didn't
-
like it.
-
He used one, it, it's something instantiated
by the
-
controller. We've been looking at controllers
a little bit
-
as just like, OK, I've received this thing,
pass
-
it off to somebody else, and then do something
-
with the result. So we want to keep out
-
that procedural code from our controllers,
and service objects
-
are one way you can do that using a
-
order service to create orders, we've encapsulated
all of
-
the logic about how to create an order in
-
this one area.
-
So if you want to, you can use it
-
from somewhere else, right. You don't have
to hit
-
a controller action to create an order. It's
reusable
-
and extendable. And it has Declan's magic
repository object
-
in there that we'll get to in a bit.
-
And the controller, again, just, it's very
simple. Do
-
this thing, on success do this, on failure,
do
-
this.
-
So those are a few of the patterns that
-
we've been using to help us with this. So
-
now what?
-
What's, what's the elephant in the room? Anybody?
-
How do you get them into Rails? Yeah.
-
Yeah. That's the one we were thinking of.
-
D.W.: That's, ActiveRecord. Yeah. I mean,
I mean, the
-
end, and how do you get into Rails. Yes,
-
there are some interesting challenges around
that. But I'm
-
gonna flip you back to the architectural slide
and
-
just point out that you see what's happened
here
-
is that we're trying to view the application
pieces
-
of our solution here being really on the perimeter
-
of our core system. And the core system composed
-
of services that may be servicing API or application
-
requests.
-
We have some services that may be invariant
across
-
any call, and those would be at the very
-
center. And we have things called entities
which are
-
on the inside. And the key part that's, that
-
we haven't talked about, which actually I'm
planning the
-
most difficult part in this is this repository
which
-
is the bottom, which is the r in the
-
bottom right hand corner.
-
And it's job is to talk to the ActiveRecord
-
model which is in the green, and create an
-
entity object which is the blue object, and,
and
-
how does that actually work? So I'm gonna
show
-
you a bit of code, and this is, this
-
is the first time I've shown my Ruby code
-
in public. So please be kind.
-
And there are probably way better ways to
do
-
this. but this is the repository that I've,
I've,
-
there are some other methods here, but I just
-
wanted to fit on what happen, you know, show
-
you the simple one.
-
So this is what a save looks like. So
-
the save takes a domain object and it converts
-
it through something called a mapper, which
maps the
-
domain object onto a ActiveRecord object,
which is called
-
a record here. Then I, then it calls record
-
dot save, assigns the id and returns the response.
-
So that's pretty straightforward. All that's
really happened is,
-
and I really tried to do this and so
-
far I've been able to, I don't want to
-
have domain dot save. I want to have repository
-
dot save domain, so that there's no persistence
that's
-
leaking into my domain objects. Persistence,
I want to
-
be a secondary concern to what that object
is
-
really doing.
-
And so far, it's worked, although sometimes
it's caused
-
me some difficulty. The method messing down
there is
-
kind of cool. At least I think it's cool.
-
And what it's doing is it's introducing a
scope
-
object, which I'll show you in a, well here's
-
the scope object. That's OK.
-
And it creates a scope object, and this was
-
the trickiest code that I had to write, but
-
what it does, what it, the end result of
-
this code is, that allows you to chain call
-
any of your ActiveRecord find methods of your
scopes
-
and chain them together. So you can now use,
-
so in other words, with this logic, wherever
you
-
have like ActiveRecord dot, you know, find
where id
-
greater than 122 is activated and so on, wherever
-
you might have a chain like that, you can
-
still use that chain now because of this scope
-
class with your domain objects.
-
Except, instead of getting back your ActiveRecord
object, you're
-
getting back its domain representation. Does
that make sense?
-
yeah?
-
OK. And then the mapper is what maps them
-
across, right. And some cases, the mapping
is like
-
really, really simple. What's the next slide
here? Oh,
-
yeah. Yeah. There it is right there.
-
So the mapper, because of the way vertice
works
-
and the way ActiveRecord works with attributes,
you can
-
almost just instantiate one from the other
just passing
-
the attributes back and forth. So it's actually
quite
-
easy except when it's not easy, and then what
-
happens, what I'm doing now is just, wherever
I
-
have something that doesn't fit this model,
I just
-
subclass this mapper with a custom mapper
and override
-
those methods, more or less.
-
And that's the part that I think there, would
-
be more expressive ways to do that mapping
and
-
that's what I'm starting to look at now. But
-
so far this has actually worked pretty well.
-
And it's allowed me to completely separate
the way
-
I think about persistence from the way I think
-
about my domain object. SO we before we, before
-
I had this, we had, used to have an
-
order class, and I kid you not, and I'm
-
in, I'm a Rails noob so you can shoot
-
me, but it had forty-eight attributes in the
ActiveRecord::Model,
-
right.
-
That is now represented by about eight classes
that
-
separate out all the different aspects of
the order,
-
like the shipping, the billing, et cetera,
et cetera.
-
So that, but I think this mapping is, is,
-
is, is one of the more challenging parts.
And
-
then finally, you now I've, then you quickly
run
-
into things like, oh, well what happens if
I
-
get the record. I get the record, I save
-
it, then I save it again. I have to
-
be able to keep track that I've saved it
-
once already.
-
So that I don't have multiple copies around.
And
-
this is an identity map. In fact, an identity
-
map was built into Rails and I think it
-
might, I don't, I don't work in Rails 4,
-
but I think it might be taken out or,
-
or changed slightly. But actually, on the
next slide
-
I'll show you what the identity map looks
like,
-
and this, actually, I stole from Rails and
made
-
it a bit simpler.
-
But all it's doing is just making sure that
-
there's a unique instance on, on a per-API
request
-
call for each entity object. So that I, I
-
can, and it actually serves as a really cheap
-
cache, but that's not what it's intent is.
-
So, so that's kind of where, where we're,
where
-
I'm going now, is most of those service object,
-
form object, request, those all kind of work
well
-
for us, and I'm not looking at what would
-
a repository pattern look like fleshed out.
And that
-
is, by far, the most challenging piece.
-
But I heard a question about where you put
-
things. You can really just put them anywhere.
You
-
know. That's the thing, like, Rails just seems
to
-
be, there's a part that's, I just felt constrained.
-
Like, Rails didn't give me any guidance on
where
-
do I put a service socket. Well, you can
-
really put it anywhere you like. You could
put
-
it on the auto load path or you can
-
put it where Rails might expect to see it.
-
But it, you can just create a services directory
-
and put your service objects there. Rails
will find
-
it. It's not hard. But Rails doesn't really
kind
-
of tell you what to do. So it doesn't
-
make it easy to do these, to think of
-
it, but it actually, it's not hard.
-
And but that's where we're going with that,
and
-
we'll, we'll give you a link to it, to,
-
I've started a Git Repo where I plan to
-
share some of these ideas, and if you're interested
-
in sharing ideas with us on that, we'll, we'll
-
be happy to talk to you or, or join
-
us on the, on the Git Repo.
-
E.R.: Right. So what's the point, again? At
the
-
start, we had these three things. Embrace
complexity. Getting,
-
getting the solution to work is only part
of
-
the fun, right? It's, it's your first draft,
as
-
DHH said, talking about writing. You get,
you do
-
it over and over. And getting things to work,
-
that ninety-line method I showed earlier,
that worked. But
-
does anyone want to go back and use that
-
again? It's no, it's no fun to revisit, unless
-
you're improving it, which, I did do eventually
and,
-
and now it's much nicer to work with. That,
-
that's fun. At least, we think that's fun.
Getting
-
beyond the problem and getting it to a level
-
where we actually don't mind going into our
code,
-
extending things, and changing things.
-
And we do that by breaking them up into
-
the smaller parts with the patterns that we've
talked
-
about.
-
Knowing where you're going. In Alice in Wonderland,
paraphrase,
-
they said if you don't know where you're going,
-
any road will take you there. We think it's
-
important to know where you're going and pick
a
-
road that you think will take you there. It
-
doesn't have to be our road. These are things
-
that helped us, and, and we think they're
good
-
ideas. But it's not gonna solve every problem
for
-
everyone. These aren't rules. Like Declan
said, they're not
-
science. You can't just take them and throw
them
-
on and expect that your code will magically
get
-
better by going on a diet.
-
And be more than just a Rails developer. Not
-
that it's bad to be a Rails developer, but
-
these things apply across, across languages
and stuff. Like,
-
don't just learn Ruby. Learn, learn beyond
that. So
-
as Declan mentioned, we have this GitHUb that
we've
-
set up, and right now it's just a readme.
-
We don't actually have the code in their yet.
-
We'll likely put some of the code we showed
-
today, especially the repository bits.
-
But we'd love to continue the discussion via
issues,
-
pull requests, whatever. That would be awesome.
And, and
-
we'd love to talk to you about some of
-
it throughout this week as well. In fact,
I'm
-
gonna also mentioned, we have reading. You'll
be able
-
to get these slides after, so I'm just gonna
-
gloss over them.
-
These are a couple of the books that we've
-
taken a look at to help us out with
-
these things.
-
D.W.: I think the crowd has spoken and it's
-
time to wrap up. If you want to come
-
up and talk, I'm happy to answer your questions.
-
Thank you.