Wednesday, January 21, 2009

The Sweet Spot

Everything I Know, I Learned From Rails, Part II - The Sweet Spot Between Frameworks and APIs

This is the second article in a series to try to convince more developers to learn Ruby on Rails, even if they are not involved in web programming. See also part I and part III.

Rails is described as a Model-View-Controller (MVC) web application framework. It also contains a number of Application Programming Interfaces, or APIs.

What's the difference? Frameworks impose a structure on our program in order to make development easy in a complex paradigm. Frameworks say "implement interface X and overide the doSomething() method". An example of a framework would be the Microsoft Foundation Classes (MFC) for Windows development. Frameworks are great, except when the user needs to do something outside of the framework's capabilities.

An example of this which I encountered in my career was (not sure if it still this way) introducing an MFC split view with separate documents in each view pane. Was not possible as a view references one document. (Author's note: pls don't slam me on this point - at the time, had no other way to show two documents in my view).

APIs, on the other hand, are considerably lower level, offering more flexibility than frameworks, at a cost of complexity moving from the producer to the consumer. An API many of us are familiar with is the Java Swing API. You can do pretty much anything you want, but good luck figuring out how to correctly incorporate the JTree into your application.

I've often said APIs give you what you want, while Frameworks tell you what you want. There is a parallel in the software application space too. Applications can be written as a tool to aid the wisdom of the smart user, or can be the expert system which tells the user what's what.

As developers, we always get squeezed between the limitations imposed by a framework, and the difficulty of using an API in a efficient and robust manner which is maintainable across the future releases of the library. In fear, we wrap the API in a facade which we can adapt to new releases or fix improper usage of it. In essence, we turn APIs into into Frameworks ourselves.

Rails has found, in my opinion, a way to get the best of both worlds. Rails starts as a minimalist framework, doing basic request routing. It also has a series of APIs for building out your functionality.

Rather than impose a structural framework, Rails provides more of a functional framework. Using the metaprogramming of Ruby, rails generates missing methods at runtime, including defining model classes based on a table's structure, and generating find_by methods as they are called. The framework writes itself as it is running. That way, it stays lean and does as little for you as possible, and limits you as little as possible.

In addition to runtime code generation, Rails also comes with a series of static code generators to give you a leg up on fulfilling your part of the framework. Developers need to write model, view and controller classes, and there are generators which output each, plus the necessary tests for each.

While we may not all be able to put metaprogramming into our frameworks in the same manner Rails does, there still are lessons to be learned here. Not all of the restrictions we impose via frameworks are necessary. We can still help users by providing APIs alongside our frameworks, generating code (and tests with it) that use these APIs, but not providing the whole solution to your users, ever.

No comments: