71
Building a Framework on Rack Wednesday, August 12, 2009

Building A Framework On Rack

Embed Size (px)

DESCRIPTION

Describes a high-level evaluation of why one would end up actually implementing a framework, how one should approach it, why one would do it, and then actually shows some examples of writing a Rack-based web application development framework called "Fuck".

Citation preview

Page 1: Building A Framework On Rack

Building aFramework

on RackWednesday, August 12, 2009

Page 2: Building A Framework On Rack

Wednesday, August 12, 2009

Page 3: Building A Framework On Rack

FornicationYou’ve probably heard about my fornication-themed framework called...

Wednesday, August 12, 2009

Page 4: Building A Framework On Rack

Wednesday, August 12, 2009

Page 5: Building A Framework On Rack

Fuck

Wednesday, August 12, 2009

Page 6: Building A Framework On Rack

writing afucking

frameworkIt was the most appropriate name for a simple fuckin framework!

Wednesday, August 12, 2009

Page 7: Building A Framework On Rack

What?I know what I want, but let’s establish what we’re after...

We need to ask some important questions before we get lost in glee and fascination

We’ll start with...

Wednesday, August 12, 2009

Page 8: Building A Framework On Rack

What is the problem we’re solving?

Clearly there’s a reason we need this framework... we’re solving a problem, but what is the problem?

Wednesday, August 12, 2009

Page 9: Building A Framework On Rack

A need to develop similar types of web applications...

Yep... pretty damn simple.

Wednesday, August 12, 2009

Page 10: Building A Framework On Rack

...that another framework doesn’t already do better

One option, though a plugin could probably be better used, or simply using Sinatra or Rack directly

Wednesday, August 12, 2009

Page 11: Building A Framework On Rack

An exercise in challenging expectations

You’re tired or think MVC just doesn’t cut it (it doesn’t)

and think you can come up with something that solves the problem better...

Wednesday, August 12, 2009

Page 12: Building A Framework On Rack

An exerciseOr you’re just itching a mental scratch....

mental masturbation

Wednesday, August 12, 2009

Page 13: Building A Framework On Rack

Abstracting out a solution’s pattern

Most successful frameworks

abstract a working solution

to a generic framework

because their solution solved both a specific and a general problem

Wednesday, August 12, 2009

Page 14: Building A Framework On Rack

What are we abstracting?

We need to find out what we’re abstracting

Wednesday, August 12, 2009

Page 15: Building A Framework On Rack

The hard parts in our solution’s pattern

like the distributed stuff in Mack

or handling uploads, testing, and RESTful routes and routes in general in Rails

Wednesday, August 12, 2009

Page 16: Building A Framework On Rack

Non-application logicConfigurationTemplatingORMs

assembling the working pieces of a stack

request routing et al

Wednesday, August 12, 2009

Page 17: Building A Framework On Rack

Reusable components, tools, and helpers

Wednesday, August 12, 2009

Page 18: Building A Framework On Rack

What should the API look like? if we could use the API

before writing it or testing it, what would it look like?

pseudo-code

Wednesday, August 12, 2009

Page 19: Building A Framework On Rack

a fuckin resource: responds with: all read one accepts: create new update one delete one

Wednesday, August 12, 2009

Page 20: Building A Framework On Rack

CRUD

Wednesday, August 12, 2009

Page 21: Building A Framework On Rack

What applications will it have? How will we use our

framework?

For example, the application the framework will be abstracted out of?

Aurora, JSON-based auth server

Wednesday, August 12, 2009

Page 22: Building A Framework On Rack

An overly simple abstraction of a RESTful CRUD interface

So what are we aiming for with the Fuck framework?

Wednesday, August 12, 2009

Page 23: Building A Framework On Rack

Any object we want to manage RESTfully

CloudKit does something like this, but it’s all automatic

We want to define the data IO (essentially)

Wednesday, August 12, 2009

Page 24: Building A Framework On Rack

Including:

ThreatsRecipesPostsValuesPeopleNounsVerbsCities (called Atlanta)

Ask for some simple objects we could easily serve purely RESTfully

like WeeDB which stores generic key-value pairs (serialized JSON data)

Wednesday, August 12, 2009

Page 25: Building A Framework On Rack

How about a Key-Value store web interface?

If we have time we can write an application that stores to Redis via a Fuck Resource

doubtful, though

Wednesday, August 12, 2009

Page 26: Building A Framework On Rack

What problems have we created?

There always comes some responsibility with writing and sharing a framework

ASSUMING we’re sharing it as OSS, right? RIGHT?!

Wednesday, August 12, 2009

Page 27: Building A Framework On Rack

Specialty DomainYou’re solving a special problem that other frameworks don’t, right?

Wednesday, August 12, 2009

Page 28: Building A Framework On Rack

Unfamiliar ExpectationsDevelopers don’t know what to expect from your framework...

What content type does it default to?

Does it support forms?

Wednesday, August 12, 2009

Page 29: Building A Framework On Rack

Maintenancecommunity & emailbug fixes & issue trackingheckling (j/k)speaking opportunitiesfeature improvementtesting

Wednesday, August 12, 2009

Page 30: Building A Framework On Rack

Why?One last sanity check

Wednesday, August 12, 2009

Page 31: Building A Framework On Rack

Why doesn’t Rails work for our needs?

Wednesday, August 12, 2009

Page 32: Building A Framework On Rack

Why doesn’t Sinatra work for our needs?

Wednesday, August 12, 2009

Page 33: Building A Framework On Rack

Why doesn’t work for our needs?

anything

Wednesday, August 12, 2009

Page 34: Building A Framework On Rack

How?So how do we do it?

This is after all the crux of the talk

Wednesday, August 12, 2009

Page 35: Building A Framework On Rack

How simple can we make it?

We still need to ask the right questions...

So how can we make the framework as simple as possible?

And why?

Wednesday, August 12, 2009

Page 36: Building A Framework On Rack

Simplest possible implementation of the solution but no simpler

Wednesday, August 12, 2009

Page 37: Building A Framework On Rack

For Example:

Only resourcesOnly RESTfullyNo explicit routesNo explicit configurationNo assumptions about IO

These are essentially what Fuck is designed around

IO includes templating and DB persistence

BUT specifically requests and responses

Wednesday, August 12, 2009

Page 38: Building A Framework On Rack

100 LOCKeep the code as small, lean, and clean as possible...

100 LOC is a little arbitrary and meaningless, but it’s small...

Can we meaningfully create a framework in 100 LOC? Yep.

Wednesday, August 12, 2009

Page 39: Building A Framework On Rack

How do we reuse existing tools? This is a talk about

building a framework on Rack, after all

Wednesday, August 12, 2009

Page 40: Building A Framework On Rack

Rack abstracts server integration into a simple, consistent interface This is why Rack was

written initially

Wednesday, August 12, 2009

Page 41: Building A Framework On Rack

Rack provides a simple DSL for injecting logic in the call cycle through middleware

Why we don’t worry about auth, caching, et al

Wednesday, August 12, 2009

Page 42: Building A Framework On Rack

Rack has many great libraries, middleware, and guides freely available already

Rack::CacheRack::JSONPRack::BugCloudKit

Get audience to name some middleware they’ve found useful or interesting

Wednesday, August 12, 2009

Page 43: Building A Framework On Rack

Rack is constantly improving and many popular frameworks use it internally

Rails 2.3+ is built on top of Rack and supports Metal endpoints (Rack apps)

Sinatra, Ramaze, Halcyon, Mack, etc

Wednesday, August 12, 2009

Page 44: Building A Framework On Rack

How do we write it?So how do we even begin to know how to write a framework?

Wednesday, August 12, 2009

Page 45: Building A Framework On Rack

WRONGYOU’RE DOING IT

WRONGWRONGWRONGWRONGWRONGWRONGWRONG

Stop, you retard...

you’re doing it wrong!

You write the tests first!

This will answer so many questions early on about how to write it!

Wednesday, August 12, 2009

Page 46: Building A Framework On Rack

How do we test it?

Wednesday, August 12, 2009

Page 47: Building A Framework On Rack

We write our tests first. TATFT

Wednesday, August 12, 2009

Page 48: Building A Framework On Rack

It allows us to exercise the API before implementing it...

Our opportunity to design the API

Wednesday, August 12, 2009

Page 49: Building A Framework On Rack

...and ensures our expectations are met as we implement. Failing tests are always a

good way to bring attention to problematic or incomplete portions of the library/framework

Wednesday, August 12, 2009

Page 50: Building A Framework On Rack

How do we write it?Now we can think about writing it once we’ve established or at least started our tests...

TDD/BDD works great!

Wednesday, August 12, 2009

Page 51: Building A Framework On Rack

...But lets wait until the end of the talk to see...

Wednesday, August 12, 2009

Page 52: Building A Framework On Rack

How do we get it to run?

No need for JBoss servers and all that bullshit...

Essentially calls Mongrel and then loads the environment

Wednesday, August 12, 2009

Page 53: Building A Framework On Rack

rackup -p 3000 config.ru

Wednesday, August 12, 2009

Page 54: Building A Framework On Rack

require 'fuck'require 'posts'

run Fuck

config.ru

Fuck the class responds to the class method #call to handle requests (it figures out what resource to defer to)

Wednesday, August 12, 2009

Page 55: Building A Framework On Rack

How do we release it?

Wednesday, August 12, 2009

Page 56: Building A Framework On Rack

RubyGemsRip

Talk about the Gem spec and simple Rakefile to make this simple

Mention the GitHub restriction

Rip, developed by Chris Wanstrath of GitHub, looks very promising ; specifically the branching and sharing

Wednesday, August 12, 2009

Page 57: Building A Framework On Rack

Wednesday, August 12, 2009

Page 58: Building A Framework On Rack

Implementingthe Framework

Wednesday, August 12, 2009

Page 59: Building A Framework On Rack

Tests TATFT

Wednesday, August 12, 2009

Page 60: Building A Framework On Rack

class Posts < Fuck::Resource def all respond "Fuckin A!" end def create respond params["a"] end def read(id) respond "You asked for #{id}?" end def update(id) respond params["a"] end def delete(id) respond "You asked me to delete #{id}" endend

Simplistic CRUD with a nonsensical implementation

Wednesday, August 12, 2009

Page 61: Building A Framework On Rack

require 'rubygems'

require 'fuck' # set load path first

require 'rack/mock'require 'stringio'

require 'test/spec' # or whatever

Dependencies for testing

Wednesday, August 12, 2009

Page 62: Building A Framework On Rack

env = Rack::MockRequest.env_for( "/posts", "REQUEST_METHOD" => "GET")

Fuck.call(env)#=> [status, headers, body]

A mock request is essentially the environment hash of the request (PATH_INFO et al)

This sets off the resource routing

Response is minimal required response for Rack

Wednesday, August 12, 2009

Page 63: Building A Framework On Rack

context "Fuck can route" do specify "to list all of the resources" do status, headers, body = get("/posts") status.should == 200 body.should =~ /Fuckin A!/ end end

Slightly specific totest/spec

wrote this a few months ago and would probably pick context or shoulda or rspec now...

Didn’t mention this but wrote a helper method for sending a mock request for all of the HTTP verbs

Wednesday, August 12, 2009

Page 64: Building A Framework On Rack

FrameworkLet’s get to the actual framework already!

But we’ll add tests for each feature we start to implement

Wednesday, August 12, 2009

Page 65: Building A Framework On Rack

BaseThe initial routing handler...

Wednesday, August 12, 2009

Page 66: Building A Framework On Rack

require 'rack'

class Fuck class << self PATH_INFO = %r{/?(\w+)(/(\w+))?} # matches /posts and /posts/1 def call(env) if handler = find_handler(env["PATH_INFO"], env["QUERY_STRING"]) handler.call(env) # dispatch the request else # not found end rescue Exception => e # internal server error end def find_handler(path_info, query_string) # determine the resource from the path info # /posts => Posts end end autoload :Resource, "fuck/resource"end

find_handler finds the resource class (Posts) that will handle the request

stripped down but we definitely respond with proper status codes and log to rack.errors

Would probably just require now instead of autoload because thread-safety concerns

yay for minimal dependencies

Wednesday, August 12, 2009

Page 67: Building A Framework On Rack

Resources

The actual request handlers;

essentially a resource controller, for instance

Wednesday, August 12, 2009

Page 68: Building A Framework On Rack

class Fuck class Resource DEFAULT_HEADERS = {"Content-Type" => "text/html"} attr_accessor :params def initialize(id, params); @id, @params = id, params; end def call(env) request_method = find_method(env["REQUEST_METHOD"]) || :not_implemented return not_implemented unless self.respond_to?(request_method) send(request_method, *[@id].compact) or not_found rescue Exception => e # internal server error end def find_method(request_method) # determine the type of request (GET, PUT, POST, DELETE, etc) end def respond(body = "OK", options = {}, headers = {}) # prepares a Rack-compatible response: [status, headers, body] end def not_found; respond("Not Found", :status => 404); end def not_implemented; respond("Not Implemented", :status => 501); end endend

find_method figures out what request method is being used and whether an ID was set or not in order to determine to call the :all, :create, :read, :update, or :delete methods...

Wednesday, August 12, 2009

Page 69: Building A Framework On Rack

Wednesday, August 12, 2009

Page 70: Building A Framework On Rack

Wednesday, August 12, 2009

Page 71: Building A Framework On Rack

Wednesday, August 12, 2009