Saturday, July 27, 2013

Models, Controllers and Views

It has taken me a while to get my head around Rails-think for Model-View-Controller. Here are some notes on what I've learned.

Credits:  The testing patterns can be found on the relishapp website.

Rails MVC concept simplified

Web-requests go to a controller.  The controller usually interacts with a model to carry out model-level actions.  Results from those actions are sent to a view.  The view is responsible for returning results in the web-response.

Views

It is very easy to get de-railed (sorry) when writing a view.  HTML templates are filled in using embedded Ruby.  Since it is embedded Ruby, you can write some very expressive code within the view.  Often, one takes a short-cut and places domain-logic in the view code, sometimes without even knowing it.

Views need to stick to the presentation of data and avoid domain logic.  This will become more apparent when one writes tests for views.  If the presentation includes domain logic, you will spend a lot of time writing complex stubs for that domain logic.

My rule-of-thumb is that a view template should only render a single object or a single list of objects.  That is an odd statement as views can support very rich presentations.  The idea is that one should break down a complex presentation into partial views or just partials.  This is to support design-for-test.

As an example, consider a view which presents both a Widget and a Gadget.  That view should have a partial for rendering the widget and a partial for rendering the gadget.  One then tests each partial outside of the main view.

Note:  Even when partials render a single object, one should build a stubbed version of the object in your test code. Otherwise, domain-logic correctness creeps back into the test code.  Stubbing is easy when one is filling in attributes.  It is slightly more tricky when stubbing out an actual method.  One uses the Klass.any_instance.stub pattern.  That pattern is described here.

When testing the main view, one should stub out the rendering of the widget and gadget views.  The relish people provide a good description here.  The technique use stub_template to replace the rendering of a partial template with a stub.  Quite often, the stub merely renders a distinctive string like "Gadget #{@gadget} goes here" where one stubs off the @gadget instance with a string.

Note:  I have to finish writing about models and controllers.

Models

Models are supposed to represent a portion of your overall information model.  For both good and bad, Rails ActiveRecord models are at the persistence layer.  That layer is also known as object-relation mapping (ORM) layer.

Tuesday, July 23, 2013

Controller MicroArchitecture: Functional Authorization

One common use case for functional authorization is pretty simple:  You can't do function X unless you are signed in.  As I've mentioned in other blogs, I had been following Michael Hartl's tutorial design patterns which included authorization.

Hartl located common authorization functions in the SessionsHelper module.  Sessions being an overused term, it took me a while to understand that there is a blend of Authentication and Authorization in that module.

Authentication caching is handled via cookies and is in these methods:
  • sign_in
  • sign_out
  • current_user
  • current_user=
Functional authorization support is in:
  • signed_in?
  • signed_in_user
    • store_location
    • redirect_back_or
Data authorization support is supplied via:
  • current_user? which compares the current user against a different user (often the owner of certain data)
In each controller, one added the before_action :signed_in_user filter.

A Variation

The Ruby-on-Rails/ActionController overview (section 8) discusses moving the check into the ApplicationController.  For those controllers that don't need signin, one opts out by using :skip_before_action.

Observations

In both approaches, Authorization Policy is distributed to the controllers.  The second design pattern is a little less so but one still needs to check each controller to see if there are any exemptions.
I've also observed both an increase in test complexity and test run-time when authorization is enabled.  Creation of a valid user and sign-in before each test take time.  One also needs to test each method against non-authorized users.

Formalizing Authorization

Like the variant above, I place a filter in my ApplicationController
include AuthorizationHelper ... before_filter do |controller| authorize( controller) end
The ApplicationHelper module:
module AuthorizationHelper def authorize( controller) require_signin = true if( controller.is_a?( MyExemptController) ) then require_signin = false end if( require_signin && !signed_in?) logger.info "Signin required for the #{controller.class}::#{controller.action_name} action" store_location flash[:notice] = "Please sign in." redirect_to signin_url end end end
In this approach, all controllers are unaware of the authentication policy. This allows one to look in one place and see what the intended policy is.
Note that the code makes use of the undocumented .action_name attribute. This can allow per-method control over authorization.

Controller Micro-Architecture

A Controller supplies one or more web-service API's.  Those API's are most often closely related to a single Model.  For example, one has a Widget model and a WidgetsController.  That close relationship can cause the lines of responsibility to become blurred.

Controllers also coordinate with the presentation of the response.  Again, the lines of responsibility can be a bit a fuzzy - does the logic go in the controller or in the .erb file?

Here is my sense for controllers:
  • Functional Authorization
    • Does the user have to be signed-in to access the controller's method?
    • Is the user allowed to access the method?  For example, is it superuser-only?
  • Check for basic argument correctness
    • Required parameters
    • Extraneous parameters (e.g. white-list)
  • Data Authorization
    • Is the user allowed to see/modify/delete that particular data?
  • Invocation of domain logic
    • Error handling
  • Assigning domain logic results to instance variables
    • For use by result rendering (HTML, XML, JSON)
  • Selection and invocation of the result rendering code
    • Often done implicitly by Rails!
    • Correct presentation of errors
Next:  Best (for some relative value of best) Practices for each area of responsibility.

Sunday, July 21, 2013

RESTful Design Part 1

There is a lot written on RESTful design. IMO, most of hides the purpose of the RESTful design pattern. I think it worthwhile to restate "why" before looking at the patterns.  In web-applications, the client and server each have state.  Due to several causes, the client state and server state can lose synchronization and become inconsistent.   Some of those causes are:

  • Communication failures and timeouts
  • The ability to move off a page and then back
  • Bookmarked pages
  • The refresh button
  • The infamous back-button
These causes can result in the equivalent of a partitioned system between client and server.  The CAP theorem states that there is a trade-off between Consistency, Availability, and Partition tolerance.  In all web-applications, the choice has been made for Availability and Partition tolerance over Consistency.  The availability choice may not be obvious; it is a result of choosing not to indefinitely lock up the user's web browser.

Fielding's thesis on RESTful design proposes a design pattern to minimize the potential inconsistency.  Quite simply, try to make the server as stateless as possible. If the server has no state, there is nothing to be for the client to be inconsistent with.

Fielding recognized that the application server is responsible calculating the "next state" (in most cases).  He relaxed the server-stateless constraint by allowing the state to move from client to server and back again.  Hence there is State Transfer in REST.

That state transfer from server back to client can be found in the HTML template process.  A template is often filled in with content and links specific to a state.  Another good example is the addition of hidden elements within a form.  Those hidden elements provide additional context (or state) to the server.

Generally, an application is RESTful if the server retains no session state between requests. There are some places where keeping session state is useful. For example, keeping authentication (signed-in) state is very useful.

***

But what about RESTful API's?

Those are RESTful on a small scale and are part of making an application RESTful.  But just providing RESTful API's does't mean that the application is RESTful.

***


Tuesday, July 16, 2013

Controller Design Patterns

Rails has a concept of a controller. Simplistically, a controller is something which responds to web requests. I've seen several different controller patterns emerge in my applications. These are:

  • Resource (or asset) service.  I use this pattern when I need to return an image or other monolithic object without exposing a directory path in the URL.
  • JSON-based restful API's.
  • HTML document services.
The JSON patterns are used to provide access to the business and/or domain logic.  These tend to be fairly pure and understandable.

The HTML document services are a hybrid of presentation, business, and domain logic.  They can be messy as the presentation is coupled to the business part.

For both JSON and HTML patterns, there are variants:
  • ActiveRecord model wrappers.  The ActiveRecord model pattern supplies well-checked (robust) CRUD operations.  Constructor parameters use the params associative hash and thus need to handle checking and deserialization.  The controller code delegates all of its work to the underlying model.
  • ActiveModel model wrappers.  These are akin to ActiveRecord, only not persisted to the database.
  • Other
Rails is really good at generating controllers that are HTML ActiveRecord model wrappers.

The HTML controller has another variant which is composite presentation.  Parts of the composite happen naturally in Rails using application templates.  Other times the controller is merging the presentation of multiple other controllers.  This happens on things like user account summary pages.

Subsequent blogs will talk about controller design problems and solutions.

Monday, July 8, 2013

Architectural Drivers

My apologies to the reader if this sounds obvious.

Application software is now delivered over the Internet.  An extreme type of software delivery is the web-application. One points a browser at a web-site, Javascript is downloaded as it is needed and the application runs.  This type of delivery is quite popular for the following reasons:
  • The software supplier is dealing with a single version of the code.  Bug fixes and enhancements are immediately available to all customers.  Support is greatly simplified.
  • The software is not stored on the user's computer. You have to access the server each time you use it.  This is basically what enables the entire SaaS business model.
  • There aren't that many client machine architectures, i.e. browsers.  It may be a bit ugly but it is not as bad as needing to compile a new binary for each machine.  Technology is not getting in the way of addressable market.
Application delivery times are pretty much a function of the application size and bandwidth.  Somewhat interesting, mobile applications operate in world where repeated downloads of large applications are both slow and expensive.  One installs a client application on a mobile device to minimize both application start time as well as the cost of bandwidth.

The ramification is that what is valued in a web-application is different from what is valued in a mobile application.  This results in fundamentally different technical approaches.  Someday they may be harmonized but that day isn't today.

Since a web-application is download-when-needed, the part that is downloaded to the client is mostly concerned with the user interface.  Server response times (latency) aren't fast enough to run highly interactive UI's over a network.  That work gets done in the client.

Some consequences:
  • People try to minimize the amount of code downloaded.  You'll see people publish stats on the size of their Javascript library as the size impacts page-load times.
  • One minimizes the amount code downloaded by not putting things there you don't immediately need
    • Focus on UI, leave business and domain logic on the server
    • Within the UI, focus on interactive UI and leave static presentation on the server.
    • Javascript libraries become page-specific.  Yes, the wheel of reincarnation has spun and we are managing our own overlays.
  • The server has multiple roles and functions.  It not only has to deal with business and domain logic, it is also implementing portions of the presentation layer.  The server portion of the presentation layer is typically implemented using a templating system.
Most of the development frameworks out there miss this fundamental truth.  Languages like PHP are great at templating but don't help at all with Javascript.  It seems that other frameworks (e.g. Rails, Microsoft's Razor) try too hard to use "just one programming language" and neglect highly-interactive UI's as those UI"s need Javascript.