ROSIE HOYEM: All right. OK. I think we are
ready
to get going. Thanks so much to everyone
for being here. This is both of our first
times at RailsConf and we're super excited
to be
here as well. It's been a fantastic week.
So fantastic that I'm losing my voice and
I've gotten a little cold, so please forgive
if
I have a crackly voice. I'm all hopped up
on
cold meds, so this should be an entertaining
presentation, anyway.
So my name is Rosie. And I am joining
you here from Minneapolis, and this lovely
lady here
is Sonja, all the way from Washington D.C.
And
today, Sonja and I are going to talk about
APIs. But we're going to take a slightly different
approach to this talk. We both have been through
fairly major career pivots, in the past few
years,
that have lead us to be in front of
you here today as Rails developers. So we
wanted
to take all of our past experiences and use
this to kind of frame this conversation in
a
way that we thought might be relevant and
interesting.
So, my background before I made the transition
to
Rails development was in architecture, as
in bricks and
seal architecture. Not software architecture.
And city planning. Sonja
also worked as a writer and graphic designer
in
a former life. We both spent a lot of
time thinking about the building process and
design elements.
So to start off this presentation, I'm gonna
talk
a little bit about the importance of patterns
in
both the build environment and software that
support good
design. Then I'll get into the meat of the
talk and describe why we think you should
consider
building the API first. And Sonja will go
over
some best practices, and I'll bring it home
with
a bit of conversation about some tools and
best
practices that you can use to build your API.
So, as I mentioned, my background, before
I got
the wild hair to become a Rails developer,
was
in architecture and planning. Along the way,
learning to
program, and learning Rails, has been a fascinating
journey,
partially because everywhere I look, I find
these parallels
between the build environment and the Rails
software stack.
One of these parallels is the role that patterns
play in both of these worlds. Before we dive
into the meat of this talk, I want to
tell a quick story about how I came around
to this topic and why we thought it might
be relevant to approach this topic from the
perspective
of design patterns.
One of the most influential books in the last
half a century in architecture is this book
by
Christopher Alexander, A Pattern Language.
If you're unfamiliar, a
pattern language, in a nutshell, is a method
of
describing good design practices. A pattern
language should facilitate
successfully solving very large, complex design
problems. These patterns
are tools to help abstract away some of the
complexity in our world so our little brains
can
wrap around how to approach solutions.
Design patterns in the build environment go
back hundreds
and hundreds of years, and are very much so
rooted in how we, as humans, experience our
surroundings
and relate to each other. And, for me, as
an architecture student, understanding patterns
was a big part
of my training.
I'm sure you all guess where this is going.
So this book came out in 1977, and responds
to a few decades of really, really bad architecture
that just went in the face of good design
patterns that had developed over the ages.
They ignored
these patterns that support a tried and true
way
humans want to inhabit cities and essentially
ended up
creating a lot of buildings that were really
awful
spaces for humans.
And so now, we fast-forward twenty years,
and these
ideas re-emerge in the software world, and,
Martin Fowler,
for example, is writing about patterns. Not
only is
he writing about patterns, all of the language
that
he uses to talk about object-oriented software
design, comes
straight out of the architecture world.
On this book's Wikipedia page, they point
directly to
Christopher Alexander's book as an inspiration
for Fowler's work
in software. Most people probably take it
for granted
at this point, but all of the language that
we use to talk about software was lifted straight
out of the architecture world. And, as an
extension,
I think the way the profession thinks about
the
organization of things. We like to think that
what
we're doing is new. But take a couple steps
back, and the concepts are really the same.
I don't know if Fowler and Alexander knew
each
other. But I think they would have gotten
along.
And one of the things I like to imagine
is them going out on Tuesdays to drink cappuccinos
and have these really intense philosophical
conversations about the
order of things. Even though, at a glance,
it
seems they come from very different worlds,
at a
conceptual level, I think they would be having
the
same conversation.
So, coming back to Rails, when I started to
think about software, I inevitably brought
this lens of
patterns with me, which meant I was super
primed
to drink the Rails Kool-Aid. Convention over
configuration? Obviously
this was just really smart design. These conventions
mapped
very cleanly in my brain to patterns, and
I
just got it right away.
At first, the process of learning Rails was
just
a smooth progression of these elegantly designed
pieces sort
of clicking into place. Then, inevitably,
I stumbled into
area after area where Rails does not provide
conventions
or strong opinions on what to do. And I
would look to my right, look to my left,
talk to developers around me, and realized
everybody had
a different opinion. And honestly this is
when learning
Rails got kind of hard.
And so this brings us here, today. One of
these areas that I, that we've found without
a
clear, sort of mainstream convention that
everyone seems to
agree on was APIs. Beyond using JBuilder and
the
basic happy path Rails application, there
wasn't clear guidance
how to deal with APIs. And honestly this really
surprised me.
Seems to me, and maybe many of you, most
of the hard problems I deal with today are
related to data transfer. At my current job,
this
is what we do. We build applications that
manage
large amounts of data. This is a really important
piece of our applications. And so, thinking
about this
more as developers, as a new developer I should
say. When we have a question, I, of course,
ask the internet. This sent me down a rabbit
hole where everyone was suggesting something
slightly different, and
nobody seemed quite satisfied with how they
were dealing
with this problem.
I read about lots of solutions, all having
varying
degrees of success. It was all interesting.
And somewhat
helpful. But it wasn't the solid answer I
was
looking for. And honestly it was really frustrating.
I
knew this wasn't rocket surgery, and it left
me
feeling like, OK Rails, if you're so opinionated,
why
don't you have an opinion on this? What should
I do?
And so, here we are. And we believe building
APIs is one of the critical areas where we
should have a shared solution because, obviously,
this is
how our applications talk to each other. This
is
where my application and your applications
cease to be
my problem and your problems, and they're
now everybody's
problem. Especially if we have a public API.
So, for one moment, bring this back to architecture.
The evolution of our great cities is really
the
evolution of shared problems becoming shared
solutions in elegant
and innovative ways. We tend to think of the
development of cities in terms of buildings,
but buildings
come and go, in reality. The interesting story,
and
here I take off the architecture hat and put
on the city planner hat, is, is really the
story of infrastructure. How we came together
and agreed
how electricity should be delivered. How are
sanitation systems
should be constructed. And how we wanted to
get
from point A to point B.
So the starting point of this talk is that
APIs should act as the infrastructure for
our applications.
If passing around data is the most important
thing
your app does, then your APIs should be elevated
from something hobble together to something
that we have
a solid solution for. And starting with the
API
and building your client applications around
it opens up
all sorts of interesting possibilities.
Carried out to the full realization of this
concept,
your APIs could be the foundation that supports
a
variety of clients, such as mobile applications
or rich
JavaScript framework clients. By decoupling
your REST API from
your client, you can more easily support multiple
clients
and have a system that is much more flexible,
but also organized.
If a mobile interface is really important
to your
application, your REST API can support multiple
native mobile
apps with minimal duplication across platforms.
This is a
good thing. You can also use the same API
to serve data to a JavaScript framework. Again,
with
very little duplication.
Your API should be the common denominator.
Without a
good standardize server solution, you can't
have a standardized
way for different clients to talk to the servers.
All right. So we've discussed some reasons
why, for
this new generation of Rails applications
that must embrace
a variety of clients, the API should be the
foundation, and where we think you should
consider starting.
So, one, your application will be designed
to pass
around data from the get-go. And reason two,
if
you need to support multiple clients, you
can easily
do this with minimal duplication across platforms.
And three,
if you create the standardized server code
first, you'll
easily support the creation of standardized
client code.
OK. Now I'm gonna pass it off to Sonja.
SONJA HALL: All right. So, let's discuss some
of
the API best practices. There are a few that
are very important to begin with, when you're
constructing
your API. But before we jump into them, I
think it's important to consider this question.
Why is
a well-designed API so important?
Well, in this image we see falling water,
going
back to architecture just for a moment. This
is
a catilever home in Pennsylvania, built in
1935, that
is among one of the greatest assets to the
architect and design thinker Frank Lloyd Wright.
It is built partly over a waterfall, deriving
its
name from its situation. And will, and has
been
conserved as a museum now since 1963. So,
in
other words, this is a huge asset to the
legacy of Frank Lloyd Wright. A well-designed
API can
be that of a company's greatest assets.
Why? Because users invest their time in obvious
and
not-so-obvious ways. In the obvious ways,
you're writing to
it, buying products that use it. You tell
your
friends and communities about how great this
API is.
You start writing blog posts about it. You're
creating
hype, basically. The less obvious ways is
that the
users are digging into it and spending a significant
amount of time learning how it works and playing
around in the code.
A poorly designed API can be a huge liability.
The same users who would have been promoting
it
and using it as inspiration for new products
are
now calling it, calling in for support and
asking
you what to do about the problems that you've
created with the API, and taking away from
your
productivity, or worse case scenario, they're
just taking one
look at your API and then running away from
it.
So the first guideline to follow, of the best
practices, is to design your APIs for experience
rather
than, and readability, not for data alone.
In other
words, an API should reflect how something
is used,
not just how it is stored. In fact, I
hate to say it, but nobody really cares what
your database looks like.
People want to know how it operates, how they
can use it. The experience should not fill
your
fellow developer with misery or regret, it
should be
methodical and consistent. Which leads me
to the next
best practice of consistency.
By providing a single API that can serve multiple
clients, you get consistent client solutions
across platforms. This
includes having single end points and clean
routes throughout
your API. It's kind of like a telephone pole
with all the cables and wires running through
and
around it. The pole is built with specific
plugins
for specific wires and purposes, allowing
electricity to flow
from the power plant to your computer screen,
or
your light bulb or what have you. And similarly,
an API call retrieves a particular dataset
from your
database, and expects a consistent return
every time.
Without this, we get this. The alternative.
Something hideous
and terrifying. Unfortunately, this slum's
infrastructure does not support
consistency or sustained development of regulated
wiring. It is
inefficiency at its finest, where everyone
seems to have
adopted a 'to each their own' mentality.
You should never have your API making someone
feel
like this. So avoid that. Coming from the
writing
and editing world, documentation is so important.
Especially having
learned how to code later in life. I love
a well-documented gem or, you know, anything
I'm trying
to use, I love when I say a lot
of documentation, and written the write way.
So, documentation is very important to the
wide-spread use
of your API. Public or not. It should act
as a bonus layer of information, though. Like
a
glimpse into a developer's mind that assumes
nothing and
notes everything. It should sit on top of
an
already easy-to-understand API, and so, in
other words, don't
make the documentation do the dirty work.
Your API
should already be understandable, and you're
just providing this
layer of documentation on top of it.
So if you're the type who just grumbled at
my last slide, I know you're out there, let's
chat about a service that makes documentation
a sync.
One that we found was Apiary. It's a structured,
interactive tool that follows the necessities
documentation, using mark
down and a template for easy usage. The result
is an intuitive document incorporating the
basic necessities that
all documentation could contain. Should contain.
So here's an example of Apiary and what it
might look like when you're doing it. But,
generally
speaking, Apiary or not, all documentation
should include the
following:
Examples of the full request and expected
response, a
list of error codes, their significance - like,
what
is causing them. A searchable html interface,
and communication
of versioning and deprecation schedules so
you don't catch
anyone off guard who happens to be using an
API, a version of your API that you're going
to be moving forward from.
So, the life span of an API is important
to consider. It can be difficult to choose
how
you're going to version, or what your strategy
will
be, but you should approach it as if you
have to get the first one, the first version
of your API, absolutely right. It makes it
easier
down the road.
The most important thing, though, to remember,
is that
versioning is inevitable and plan for deprecation
from version
one.
I also like to think of APIs as if
they were a rescue dog. If anyone knows me
from Flat Iron School - I see a few
of you out there - I'm obsessed with rescue
animals. So I had to tie this back in
for a moment. So, this is not a West
Minister Kennel Club winning dog, but he's
more like
a little rescue pup. He has limitless potential
to
be an incredible pet if you let him get
there. Just like you want to set your future
dogs up for success, you'll want to do the
same for your API.
For starters, neither this dog nor your API
require
any fancy things. They simply crave repetition
and unconditional
support in order to be successful. Give them
what
they need to evolve into their new versions,
but
don't ever forget where they came from.
The JSON APIs is one standard for building
APIs
in JSON that is supported by the Rails community.
So, this is Steve Klabnik's quote. By following
shared
conventions you can increase productivity,
take advantage of generalized
tooling, and focus on what matters: your application.
And
we liked the JSON API standards, so I put
an example of it in here.
And like so many of the tools that we've
discussed already today, there are more out
there, and
there's a lot of great ones being developed
right
now. So Rosie's gonna share a few more of
those with you.
R.H.: So, building APIs is a shared problem
for
most developers. It seems there is now a general
shared understanding of what a good API should
consist
of. A shared solution is the next step. So
we can turn these best practices into conventions.
For the last couple of months, we've been
asking
every developer we encounter what they use
to build
APIs. The answers were usually Rails or Sinatra,
with
some combination of the tools available on
Ruby Toolbox,
and usually a partially hand-ruled solution.
We also heard,
more and more, how Rails is being used to
create a REST API that talks to a mobile
client, and there seemed to be growing interest
in
using Rails for JavaSrcipt frameworks.
These may not be traditional Rails applications,
but people
still recognize the value of Rails for creating
a
REST API.
After talking to lots of people, it was evident,
though, that an agreed upon solution still
wasn't clear,
and the whole thing just required way too
much
thinking. There's so many ways to hobble something
together,
but we wanted to know the Rails way. What
will be the Rails way to build a solid
API?
Again, damn it Rails, if you're so opinionated
and
committed to this idea of conventions, tell
me what
to do. We no longer have to be pioneers
venturing out into the unknown.
So, in the middle of all of these conversations,
we did see a Rails way emerging, though it's
not baked in yet. Lo and behold, there are
solutions emerging from the core Rails team
that provide
an opinion on how to create REST APIs. We've
been exploring Rails API in combination with
ActiveModel serializer
for building an API where you only need the
JSON end points.
Rails API is Rails. It utilizes most of the
same generators and conventions and will look
very, very
familiar. For this new generation of applications,
where the
API is your infrastructure that supports a
family of
client applications, we think this is what
the future
might look like.
So Rails API is really just a miniature Rails
stack, where they skipped all of the stuff
that
you need if you were creating views, producing
a
solution that is lighter and faster than the
full
Rails app. But it does still come with a
full suite of baked in solutions for many
poorly
understood problems.
And the documentation, there's a laundry list
of things
that are handled in the middleware layer and
the
ActionPack layer. This is definitely a win.
For example,
you might understand perfectly how to handroll
a solution
for IP spoofing attacks, or maybe not. But
even
if you do, why spend time doing this if
Rails is gonna do it for you? Thanks Rails.
And again, if there's a solution for something
already
out there, I'd rather use that than reinvent
the
wheel.
The other tool we're exploring is ActiveModel
serializers, and
sure, serializers replace hash-driven development
with object-oriented development. For
example, with AcitveModel serializers, when
you're using render JSON
in your controllers, Rails will search for
a serializer
before, for the object and use it if available.
It's an elegant solution to creating server-side
APIs that
doesn't require a view layer.
They act a lot, serializers act a lot like
models and can be easily customized. ActiveModel
serializers also
follows the JSON API standard, so you know
you're
creating a standardized API that will easily
talk to
a variety of clients.
It really helps to take the guessing out of
how your JSON API should be structured.
OK. So, it's time to start wrapping things
up.
A few points to leave you, leave everyone
with.
We find it's increasingly important to design
APIs following
patterns and conventions that fit into the
system as
a whole. To do this, we can leverage existing
best practices and tools, and by doing so
we'll
create APIs that support a more organized
structure for
our applications.
I was inspired by Yehuda Katz's keynote yesterday,
and
I think it's time for us as a community
to move API design out of the area of
experimentation and into the area of collective
shared solution.
We'll all benefit.
And again, trivial choices are the enemy.
Drink your
convention over configuration Kool-Aid. But
brush your teeth afterwards.
Kool-Aid's not good for you. Anyway. We're
often trying
to solve the same problem. And when this is
the case, we should agree on a strong convention
and all follow it.
We'll all benefit in the end. And third, don't
forget about who or what else is going to
want to use this API in the future, and
plan accordingly. This may include native
mobile applications or
a JavaScript client-side framework or something
else that we
haven't even imagined yet. By designing our
APIs today
to be consistent across platforms, we can
make changes
to our client-side applications in the future
much easier.
So tomorrow, someone's not trying to use your
hand-ruled
API that didn't really follow any established
design patterns
or conventions, and you have to explain that,
well,
it seemed like a good idea at the time.
For those of you who aren't from Minneapolis,
this
is the ugliest building in the Minneapolis
skyline. So.
A little context for you. We all drive by
and shake our heads. Like oh, why?
Or worse. Your application gets scrapped because
it was
poorly organized from the get-go and too rigid
to
update.
And last, but not least, document all the
things.
Documentation is the cool to API being used
successfully.
All right. And we've come to the end. I
hope, just want to leave you with one thought.
I hope when you approach your next project,
you'll
consider building your API first.
S.H.: All right, thanks everybody.