Initial version of Abstraction Creep #65

Merged
merged 3 commits into from May 25, 2012

Conversation

Projects
None yet
4 participants
Owner

judofyr commented May 25, 2012

@steveklabnik (or maybe @telemachus?): Could you just quickly go through and see that there's no silly typos?

@steveklabnik steveklabnik commented on an outdated diff May 25, 2012

content/abstraction-creep
@@ -0,0 +1,341 @@
+Title: Abstraction Creep
+Subtitle:
+Author: judofyr
+
+Abstractions are very powerful when you're writing software. You don't
+want to write your web applications in assembly, or an operating system
+in JavaScript for that matter. Choosing the right abstraction makes you
+focus on the real challenges and let's you forget the insignificant
@steveklabnik

steveklabnik May 25, 2012

Collaborator

lets

Collaborator

steveklabnik commented May 25, 2012

Looks legit otherwise. So much profanity, though. :p

Owner

judofyr commented May 25, 2012

Better now?

BTW: Thanks; very much appreciated!

@steveklabnik steveklabnik added a commit that referenced this pull request May 25, 2012

@steveklabnik steveklabnik Merge pull request #65 from judofyr/abstraction-creep
Initial version of Abstraction Creep
512e9b6

@steveklabnik steveklabnik merged commit 512e9b6 into master May 25, 2012

@judofyr judofyr commented on the diff May 25, 2012

content/abstraction-creep
+Is it worth it? I doubt it.
+
+### Fixing the abstraction
+
+Okay, so what's the real problem here?
+
+Controller tests are slow. Why?
+
+Because loading contollers are slow. Why?
+
+Because controllers are too complex.
+
+Why are controllers complex? A controller is rather simple:
+
+* It takes a request and an empty response
+* It let's you define actions which changes the response
@judofyr

judofyr May 25, 2012

Owner

@steveklabnik: This should be "let's", right? Also, is it "changes" or "change"?

@steveklabnik

steveklabnik May 25, 2012

Collaborator

It should be 'lets' and 'change'

@telemachus

telemachus May 25, 2012

@judofyr mnemonic - an apostrophe pretty much always means something is missing let's => let us. So allows => lets is just the regular 's' for the 3rd person singular. Sorry I missed the whole proofreading party, btw; just got home.

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+ end
+{: lang=ruby }
+
+Notice that I'm using the regular Request class. Creating Request
+objects should be just as easy as creating a new controller object. They
+are both very simple classes that have few dependencies.
+
+### What about filters?
+
+You might have noticed that I silently dropped the before_filter in the
+last example. This was intentional because *filters are not crucial to
+what a controller is doing*. That doesn't mean they don't belong there,
+it just means you need to figure out if it's worth the added complexity.
+
+Does it belong another place? Maybe in the router (yes, there are
+frameworks that does the filtering in the router)? Somewhere else? I
@locks

locks May 25, 2012

Contributor

"...frameworks that does the filtering..."

typo: do

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+objects should be just as easy as creating a new controller object. They
+are both very simple classes that have few dependencies.
+
+### What about filters?
+
+You might have noticed that I silently dropped the before_filter in the
+last example. This was intentional because *filters are not crucial to
+what a controller is doing*. That doesn't mean they don't belong there,
+it just means you need to figure out if it's worth the added complexity.
+
+Does it belong another place? Maybe in the router (yes, there are
+frameworks that does the filtering in the router)? Somewhere else? I
+don't know. Maybe filters are lightweight and useful enough to take up
+some controller complexity.
+
+And *this* is what we should focus on: Figuring out what belongs in te
@locks

locks May 25, 2012

Contributor

"...what belongs in te..."

typo: the

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+
+Does it belong another place? Maybe in the router (yes, there are
+frameworks that does the filtering in the router)? Somewhere else? I
+don't know. Maybe filters are lightweight and useful enough to take up
+some controller complexity.
+
+And *this* is what we should focus on: Figuring out what belongs in te
+most basic classes in our framework. Not creating a horrible patchwork
+by adding more abstractions.
+
+### Disclaimer
+
+Just to make it clear: This is by no means an argument against Objectify
+itself, just the part where they introduce another layer on top of
+ActionController. The concept of service objects *does* make sense in
+more complex application, but I believe it's possible to achieve it
@locks

locks May 25, 2012

Contributor

"...more complex application.."

I think you meant "applications" here

@steveklabnik

steveklabnik May 25, 2012

Collaborator

Damn, I suck at proofreading. :)

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+Models in Rails works great as long as you're using them inside Rails'
+request/response-loop where everything is set up for you. The moment you
+step out from that loop (tests, other libraries) it's a big hassle.
+
+It's very tempting to add abstractions on top of ActiveRecord to make it
+easier to work with. Or you could fix the abstraction by using the [Data
+Mapper][datamapper] pattern instead.
+
+## Strive for simple data objects
+
+Abstraction creep often occurs when the data objects are too complex.
+And there's *nothing* about data that makes it complex. Data is really,
+really simple. There's only two things you need to do with data:
+
+1. You need to be able to combine data into one structure
+2. You need to be able to take apart the data again
@locks

locks May 25, 2012

Contributor

"to take the data apart again" sounds better to be. this one is personal preference :)

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+As long as you can do this (hopefully with no dependencies at all),
+you can actually use your data objects in other classes. In fact, it
+*encourages you* to create separate classes for separate problems. When
+you can easily use your data objects it's even easier to separate
+functionality to other classes (as opposed to adding more functionality
+to the same class).
+
+## Sometimes change is imminent
+
+Of course, using complex data objects is far from the only way to create
+shaky abstractions. Sometimes we don't even realize it's flawed until
+it's too late. Or maybe the world changes in such way that it
+invalidates the abstraction.
+
+Rack is a typical example of an abstraction that hasn't handled change
+well. Rack is tries to abstract away HTTP in a simple and clear way.
@locks

locks May 25, 2012

Contributor

"Rack is tries to abstract"

"is" doesn't belong

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+invalidates the abstraction.
+
+Rack is a typical example of an abstraction that hasn't handled change
+well. Rack is tries to abstract away HTTP in a simple and clear way.
+When Rack was introduced in 2007, the web was pretty much stateless and
+every request expected an response as soon as possible. A synchronous
+interface makes sense:
+
+ # When the web server sees a request it runs this:
+ env = build_env_from_request
+ status, headers, body = App.call(env)
+ server_response(status, headers, body)
+{: lang=ruby }
+
+The web has *changed*. Suddenly you have long-polling, where the request
+can wait for uptil 30 seconds before the server returns a response. We
@locks

locks May 25, 2012

Contributor

"wait for uptil"

upto

@locks

locks May 25, 2012

Contributor

actually, seems like it's "up to"

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+
+Rack is a typical example of an abstraction that hasn't handled change
+well. Rack is tries to abstract away HTTP in a simple and clear way.
+When Rack was introduced in 2007, the web was pretty much stateless and
+every request expected an response as soon as possible. A synchronous
+interface makes sense:
+
+ # When the web server sees a request it runs this:
+ env = build_env_from_request
+ status, headers, body = App.call(env)
+ server_response(status, headers, body)
+{: lang=ruby }
+
+The web has *changed*. Suddenly you have long-polling, where the request
+can wait for uptil 30 seconds before the server returns a response. We
+have WebSockets which completely breaks the stateless
@locks

locks May 25, 2012

Contributor

either "WebSocket which completely breaks" or "WebSockets which completely break"

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+Rack is a typical example of an abstraction that hasn't handled change
+well. Rack is tries to abstract away HTTP in a simple and clear way.
+When Rack was introduced in 2007, the web was pretty much stateless and
+every request expected an response as soon as possible. A synchronous
+interface makes sense:
+
+ # When the web server sees a request it runs this:
+ env = build_env_from_request
+ status, headers, body = App.call(env)
+ server_response(status, headers, body)
+{: lang=ruby }
+
+The web has *changed*. Suddenly you have long-polling, where the request
+can wait for uptil 30 seconds before the server returns a response. We
+have WebSockets which completely breaks the stateless
+request/response-cycle. The requirements has changed.
@locks

locks May 25, 2012

Contributor

"The requirements has changed."

have

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+
+ # Async call
+ wait_for_long_polling do
+ # Now we can return the request!
+ cb.call(200, {}, [])
+ end
+
+ # Send a dummy "response" in order to be "complient" with the Rack
+ # abstraction.
+ [-1, {}, []]
+ end
+{: lang=ruby }
+
+This is a horrible, hacky abstraction, implemented by some Ruby web servers
+(outside of the Rack specification). Not only does it *look* weird, it also
+breaks the the whole Rack abstraction. Any layer between the web server and the
@locks

locks May 25, 2012

Contributor

"breaks the the whole"

"the repeated"

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+ end
+{: lang=ruby }
+
+This is a horrible, hacky abstraction, implemented by some Ruby web servers
+(outside of the Rack specification). Not only does it *look* weird, it also
+breaks the the whole Rack abstraction. Any layer between the web server and the
+application (that follows the Rack specification) will behave incorrectly when
+it sees the dummy response.
+
+You can't predict the future, and some abstractions are perfect until
+the future comes and ruins everything.
+
+## Sustain the pain; go with the flow. Or: deal with the real problem.
+
+Sometimes you're stuck with crappy abstractions. ActiveRecord isn't
+perfect. ActionController has its problem. You *will* feel a slight pain
@locks

locks May 25, 2012

Contributor

this one I'm not sure again. should it be "problem" or "problems"? /cc @steveklabnik

@steveklabnik

steveklabnik May 25, 2012

Collaborator

Problems.

@locks locks commented on the diff May 25, 2012

content/abstraction-creep
+{: lang=ruby }
+
+This is a horrible, hacky abstraction, implemented by some Ruby web servers
+(outside of the Rack specification). Not only does it *look* weird, it also
+breaks the the whole Rack abstraction. Any layer between the web server and the
+application (that follows the Rack specification) will behave incorrectly when
+it sees the dummy response.
+
+You can't predict the future, and some abstractions are perfect until
+the future comes and ruins everything.
+
+## Sustain the pain; go with the flow. Or: deal with the real problem.
+
+Sometimes you're stuck with crappy abstractions. ActiveRecord isn't
+perfect. ActionController has its problem. You *will* feel a slight pain
+when you're forced to use them in a way don't like. It's very tempting
@locks

locks May 25, 2012

Contributor

"in a way don't like."

something's missing here ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment