Showing posts with label Software Architecture. Show all posts
Showing posts with label Software Architecture. Show all posts

Wednesday, September 27, 2023

RubyConf 2023 How To Build Desktop Applications in Ruby (Workshop Accepted)

My RubyConf 2023 workshop submission titled "How To Build Desktop Applications in Ruby" has been accepted! It will take place in San Diego, California, USA on Monday, November 13, 2023 at 10am PT. Workshop seating is limited, so please RSVP for your spot over here! This workshop expands on last year's RubyConf 2022 talk "Building Native GUI Apps in Ruby".

RubyConf 2023 Workshop Details: 

https://rubyconf-2023.sessionize.com/session/531448


How To Build Desktop Applications in Ruby (2 hours):

Learn how to build desktop applications in Ruby with hands-on code exercises! 

Workshop outline (every step will involve a hands-on exercise or more):

1. GUI Basics (Controls, Properties, and Listeners):

2. MVC (Model-View-Controller) Software Architecture

3. Data-Binding and MVP (Model-View-Presenter) Software Architecture 

4. Advanced Data-Binding

5. Area (Canvas) Graphics

6. Drag & Drop

7. Custom Components (Custom Controls, Custom Windows, Custom Shapes)

8. Application Scaffolding

This workshop will be conducted using Glimmer DSL for LibUI, the prerequisite-free ruby desktop development cross-platform native GUI gem that won a Fukuoka Ruby 2022 Special Award after getting judged by Matz, the creator of Ruby.

Thursday, July 06, 2023

Friday, January 27, 2023

Glimmer Ecosystem, Glimte 3rd Party Framework, PasswordStore

Traditionally, Glimmer GUI gems have been mostly a one-sided effort, with a few 3rd party contributions here and there (like Drag and Drop support for Glimmer DSL for Tk). Well, that changes with Glimte! Glimte is a 3rd party framework built on top of Glimmer (Tk flavor) by Phaengris to facilitate following a certain variation of the MVC pattern (Model-View-Controller) called MVVM (Model-View-ViewModel). It encourages a model of programming for desktop GUI views that is similar to Rails .erb and GTK .glade files, but using the Glimmer GUI DSL in .glimmer.rb files as the view format. As such, it provides a much lighter more programmer-friendly Ruby-native replacement for HTML, ERB, and Glade. Consequently, Glimte ushers in the next era of Glimmer; that is The Glimmer Ecosystem! 

The Glimmer Ecosystem enables the democratization of the style of development followed when building Glimmer desktop applications in Ruby, among many other obvious benefits. That in turn facilitates a vision similar to the Rails vision explained by Yahuda Katz in his keynote speech at RailsConf 2014 (at which I presented too), which was borrowed from Steve Jobs. What Yahuda alluded to was that by continuously building more floors for the lower levels of a building in the form of a framework and a community of open-source projects, we enable developers to start development at higher and higher levels than they would have been able to otherwise, thus helping them leapfrog earlier ways of development in ever increasing productivity!

So, what is Glimte?

"MVVM framework based on Glimmer for creating desktop apps in Ruby / Tk" 

- Source: https://github.com/Phaengris/Glimte

Are there any apps built with Glimte?

PasswordStore - "Tk-based desktop client for the Linux password store manager https://www.passwordstore.org/"
 

What is pass, the Linux password manager that PasswordStore is built for?

"Password management should be simple and follow Unix philosophy. With pass, each password lives inside of a gpg encrypted file whose filename is the title of the website or resource that requires the password. These encrypted files may be organized into meaningful folder hierarchies, copied from computer to computer, and, in general, manipulated using standard command line file management utilities.

pass makes managing these individual password files extremely easy. All passwords live in ~/.password-store, and pass provides some nice commands for adding, editing, generating, and retrieving passwords. It is a very short and simple shell script. It's capable of temporarily putting passwords on your clipboard and tracking password changes using git." 


Below is a full introduction to Glimte, taken straight from the GitHub project page.

Happy Glimmering!


Sunday, September 11, 2022

Rails Remote Conf 2022 Talk Accepted - Ultra Light Wizard

Update 2022-09-12: Correction! the conference will take place February 6-10, 2023, not in September of this year.

My talk proposal for Rails Remote Conf 2022 (Feb 6-10, 2023) titled "Ultra Light Wizard" has been accepted!

Abstract:

Ultra Light Wizard is an approach for building multi-step forms in Rails that avoids issues like code duplication, endless conditionals, and confusing mixing of concerns. That is achieved by adhering cleanly to REST, MVC, OOP, Design Patterns, DDD, and Non-Functional Requirements such as Productivity, Maintainability, Performance, and Security. This presentation will cover common pitfalls in building Rails wizards, how to overcome them with the Ultra Light Wizard approach, and Ruby gems that help with implementing this architectural pattern.

Friday, August 28, 2020

Glimmer Process (Beyond Agile)

Glimmer Process is the lightweight software development process used for building Glimmer libraries and Glimmer apps, which goes beyond Agile, rendering all Agile processes obsolete. Glimmer Process is simply made up of 7 guidelines to pick and choose as necessary until software development needs are satisfied. Not all guidelines need to be incorporated into every project, but it is still important to think through every one of them before ruling any out. Guidelines can be followed in any order. 

GPG (Glimmer Process Guidelines):

  1. Requirements Gathering: Spend no more than a few hours writing the initial requirements you know from the business owner, gathering missing requirements, and planning to elicit more requirements from users, customers, and stakeholders. Requirements are not set in stone, but serve as a good starting point in understanding what the project is about. After initial release, only document small tasks going forward.
  2. Software Architecture and Design Diagrams: Perform software architecture and design activities as necessary by analyzing requirements and creating diagrams.
  3. Initial Release Plan: This guideline's motto is "Plans are Nothing. Planning is Everything" (said by Dwight D. Eisenhower) because the initial release plan is not set in stone and might change completely, but is still invaluable in launching a new project forward. Consider including alpha releases (for internal testing) and beta releases (for customer testing).
  4. Small Releases: Develop and release in small increments. Do not release more than 3-weeks worth of work, preferring releases that are shorter than a week worth of work whenever possible. Break releases down. If you need to support multiple platforms, release for a platform at a time. If a feature includes a number of other features, then release them one by one instead of all at once. If a feature involves multiple options, release the default version first, and then release extra options later. 
  5. Usability Testing: Make sure to observe a user using your software the first few releases or when releasing critical brand new unproven features. Ask them to complete a list of goals using the software, but do not help them to complete them unless they get very stuck. Write down notes silently while observing them use your software. Once done with usability testing, you may then ask further questions about any of the notes you wrote down, and afterwards add the notes as feature enhancements and bug fixes. Implement them and then do another usability test with the improvements in place. Repeat as necessary only.
  6. Automated Tests: Cover sensitive parts of the code with automated tests at the appropriate level of testing needed. Run tests in a continuous integration server.
  7. Refactoring: Simplify code, eliminate code duplication, improve code organization, extract reusable components, and extract reusable libraries at every opportunity possible. 

See the up-to-date version of the Glimmer Process at the Glimmer (Ruby Desktop Development GUI Library) GitHub Repo:
https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md

Sunday, February 14, 2016

Ultra Light Wizard v0.1.0 (beta)

As promised, I rolled out a new update to Ultra Light Wizard (v0.1.0) that is finally feature complete, and thus labeled as beta. Please install, test, and report feedback on GitHub.

In the meantime, here are a few more tasks I'd like to tackle before it is v1.0.0 (production):

  • (must) Write automated tests
  • (optional) Support for nested resources
  • (optional) Modularize (perhaps extracting sub-generators)
  • (optional) General refactorings

Cheers and happy Rails coding!!

Sunday, January 31, 2016

Ultra Light Wizard v0.0.6

Now includes basic Rails scaffolding with attributes as part of the work.


Example:

rails generate ultra_light_wizard:wizard Project steps:basic_info,project_detail,file_uploads,preview attributes:name:string,description:text,start_date:date,delivery_date:date step_alias:part

Output:


More on the way, I promise!

Friday, January 29, 2016

Ultra Light Wizard v0.0.5

We're getting near 0.1.0, but not quite there yet at 0.0.5:
https://rubygems.org/gems/ultra_light_wizard/versions/0.0.5

Still, the gem has become much more useful at this point with form scaffolding and advanced navigation helpers implemented.

A few more things need to happen before we hit 0.1.0, and then automated tests need to be added before hitting 1.0.0

Stay tuned!

Wednesday, January 27, 2016

Ultra Light Wizard v0.0.2

Ultra Light Wizard v0.0.2 is OUT... with view navigation support (Previous/Next) and Rails helper generation.

Also, fixed issues with wizard step controller.

https://rubygems.org/gems/ultra_light_wizard/versions/0.0.2

Enjoy testing and reporting feedback!

Tuesday, January 26, 2016

Ultra Light Wizard v0.0.1

Ultra Light & Maintainable Rails Wizard was a solution pattern I came up with 3 years ago to facilitate creating Rails multi-step forms that adhere to REST, OO, MVC, and other software best practices.



The original blog post about it is over here:
http://www.codepainter.ca/2013/10/ultra-light-maintainable-wizards-in.html

And the RailsConf 2014 talk I gave about it in Chicago is here:
https://www.youtube.com/watch?v=muyfoiKHMMA

From talking to developers at our local Montreal.rb user group and interacting with different client developers, it seems that the pattern has caught on and is being put to good use, sometimes with the aid of the Rubygem Wicked.

Of course, given that the Ultra Light & Maintainable Rails Wizard approach simplifies development and maintenance of wizards immensely, it is not necessary for the many smart and responsible developers out there to have a library. After all, following the approach is supposed to yield a lighter-weight solution than using most libraries out there. Nevertheless, if it is possible to codify the pattern in a library that is light-weight enough and simple to use, then we may as well have one...

And two years after announcing the idea at RailsConf 2014 (and a few hours of work).... I finally have something to show!

Ultra Light Wizard v0.0.1: https://rubygems.org/gems/ultra_light_wizard/versions/0.0.1

GitHub: https://github.com/AndyObtiva/ultra_light_wizard

Please install and use on your projects.

Stay tuned for more developments and enhancements and feel free to suggest ideas via comments.

Thursday, October 24, 2013

Ultra Light & Maintainable Wizards in Rails

Recently I worked on Rails applications that had major requirements for web wizards, and they were built incrementally and iteratively with both junior and senior developers contributing further steps to the wizards over the lifetime of the projects. I presented my approach this past summer at the Montreal.rb user group (Update: and RailsConf 2014 ), and I am writing this blog post to provide more details and code examples.


Late last year and early this year when I scoured the net for web wizard approaches in Rails and wizard libraries, I noticed many different variations, happening across many dimensions, like the number of controllers/actions and how data is persisted across wizard pages.

Examples of controller/actions variations:
  • One controller per wizard page
  • One action per wizard page
Examples of Data persistence variations:
  • Save data in the session on every page and create an ActiveRecord when finishing wizard
  • Save data in a different ActiveRecord per wizard page
  • Accumulate data in a hidden field and use on the last step to create an ActiveRecord
  • Save data in one model with the help of a state machine
  • Manage saving data in the controller
Some approaches try to be modular by having multiple controllers or multiple actions. Others try to be light on session use by saving to the database directly.

Here is my personal feedback on the approaches above:
  • A wizard is editing one resource through multiple steps, so why are there multiple actions or controllers involved in building/updating that single resource? That violates REST. Not that it matters to break guidelines except for the pragmatic fact that it makes it more complex for developers and future team members to maintain the code.
  • A single ActiveRecord is being edited across steps even if some steps edit sub-models within it, so saving different ActiveRecords is an over-complication. That violates Cohesiveness by fragmenting the focus of the data persistence of a wizard.
  • Saving data to the session has server scalability concerns and complexity concerns. That makes Scalability harder.
  • Accumulating data in a hidden field increases complexity. That goes against Simple Design.
  • Managing data persistence details in the controller does not divide responsibilities correctly between the controller and model. That violates MVC, making it harder to maintain the code by developers and future team members.
  • A Wizard is simply editing different facets (data views) of a model, and not necessarily moving a model along a Business State Machine. The steps for entering/editing a model are also a View/Presentation concern, so even if a state machine is involved, it is not a model concern. The model might have genuine business states, but are usually only few compared to the steps of the wizard, which might adjust for usability (presentation) reasons, so although there might be overlap between wizard steps and model business states, one must not mix them as that couples the two incorrectly and unnecessarily, complicating maintainability greatly (with much cost to pay by developers over a year). That violates MVC, abuses State Machine, and worsens Maintainability.
So, where does that leave us?

I ended up solving the problem on both Rails projects with a new simple and clean approach following some concrete goals.
Goal Summary
  • Simplicity
  • Maintainability
  • Scalability
  • Proper MVC
  • Proper REST
  • Proper Object Oriented Design (respect for coupling and cohesion principles)
Starting with this end in mind, one way to think about the wizard is that it is nothing but a model builder, akin of the good old Builder Design Pattern. Without a wizard, you usually have one form that a user fills in to create a model. With a wizard, the model is created in multiple steps however, so the REST resource edited in each step is a model part (aka model data view or model step).

Wizard Flow
  • Starting the wizard creates the model and allows the user to edit the first part (data view) of the model
  • Each subsequent step enables the user to edit more parts of the already created model


Guidelines


  • REST: Following REST, the resource is nothing but the good old Model itself, except a wizard focuses on one part of the model at a time, so more accurately "model part" is the RESTful resource for wizards.
  • MVC: Following MVC, each step can be routed to an ActiveRecord representing a part of the Model. To figure out which part, the Controller relies on the ID parameter, indicating the part (step) being edited in addition to model_id. Also, each model part is a subclass of the main Model ActiveRecord to facilitate connection to the database columns with the least code possible while retaining separation of concerns (an improvement would be to use delegation from a wrapper model, useful as a future refactoring step for the design if the coupling to ActiveRecord becomes undesirable later on. In my experience, that has not been an issue, so I elected to rely on single-table-inheritance style of database mapping reuse as you will see below)

With the two guidelines above, the developer has a complete template for the implementation with everything falling into place, and the rest is details. Let's get down and dirty to illustrate the concepts above with code!

Routes ProjectsController is only responsible for creating a project. Afterward, ProjectPartsController manages the project parts as wizard step resources (REST). The routes above will produce this pattern for moving along a wizard (editing a model part): /projects/:project_id/project_parts/:id/edit

ProjectsController
ProjectsController redirects to the first project part (wizard step) after project creation

ProjectPartsController
ProjectPartsController treats model parts (wizard steps) as the resource that can be edited/updated along the way. params[:id] contains the ID of the resource, which is the model part name (aka wizard step name). Rendered views can then match that ID name. The implementation above is one way to do it. The code could be written differently and optimized depending on needs (such as moving some private methods to a Helper and sharing them with the views if needed, like the step and next step for example, which can be displayed visually on the page for labelling and navigation)

Project model
The main project model contains associations and common logic, and then each wizard step can have its own sub-model if necessary to manage step specific validations without having the validations interfere with other steps. Sub-models also manage data loading upon showing the wizard step edit page (via after_initialize) or after updating (via after_save)

Project::BasicInfo sub-model


Project::Detail sub-model

Views

Note how the views match the wizard steps.

View Forms
All view forms (e.g. basic_info.html.erb) will have the form template above, which is agnostic to which model part is being edited. On one project, the developer actually created a helper (e.g. project_part_form_for) that hides all the details and can be unobtrusively reused across all wizard view pages.

Sub-Models

Note how only the wizard steps that require validation logic and special on edit or on update logic need sub-models.

I hope you found this example implementation helpful in your endeavour to implement Ultra Light & Maintainable Wizards in Rails. Note that it is a simpler version of what I have implemented for my clients, which often grew with their rising needs over time, stretching the implementation without much strain due to its simple design and adherence to sound software development guidelines, such as REST and MVC. This approach really scales well since it allows one to add extra authorization checks in the controller without a hitch and extra hooks/validations on the sub-models depending on need. Additionally, it is compatible with the model having a state machine or following the State Design Pattern as implemented on one of my projects.
Now, no write-up would be complete without a Gotchas section, so let's get to that.

Gotchas
  • Validations live in sub-models. What if one wants to have a second mechanism for editing the model in one page utilizing the same validations? Simple. Chop the validations off into Modules, mix each of them into one of the wizard sub-models and then mix them all into a new sub-model to be used as the model for the second editing page. This approach can also be used to reuse validations for the last step of the wizard and re-run all the validations once again at the end if needed.
  • How do you skip a step based on certain rules? You need to build a check into the controller that sees if a certain model part needs to be skipped (via a skip? method for example on the sub-model). If so, the controller simply redirects to the following step. Covering the details of this is outside the scope of the blog post, but I am sure you can figure it out.

On the first project that I added the wizard to, the CTO was happy to see that the junior developer was able to add new steps to the wizard in record time after spending 5 minutes with me going over the details of how it works. On that same project, a senior developer who joined later on and was working remotely figured out the wizard design in no time and sent me congratulations on how flexible and nicely designed it was. The same happened on the other Rails project I used the wizard approach for, which facilitated growing a wizard from about 5 steps to 15 (with some interesting custom logic on step branching). So, you can rest assured this approach will work well and scale for your Rails projects.

Monday, September 16, 2013

First Experience with Rails 4 Turbolinks

My most recently developed Rails application was built with Rails 4, which ships out of the box with a feature called Turbolinks. Here is its description from the Turbolinks github repo:
Turbolinks makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body and the title in the head.
In effect, hyperlinks become turbolinks as page loading is perceived to be faster without the reloading of JavaScript and CSS despite having the same network load time for the webpage HTML markup.

In this post, I am sharing some of the gotchas I encountered with this feature, how I dealt with them, and my overall experience with the feature.

Gotchas and Solutions:

1. Style changes were not updating on page navigation

I encountered an issue the first time I tried to leverage the controller-specific CSS stylesheet pattern. For those unfamiliar with the pattern, it is actually about loading an extra CSS file in addition to application.css in order to customize the look of pages belonging to a specific controller. To enable the pattern, one would add a line like the following to their layouts/application.html.erb:

<%= stylesheet_link_tag params[:controller], media: "all" %>

This in effect, loads users.css for the page rendered by users#index or users#show for example.

The benefit of the pattern is simply keeping that CSS maintained separately from other pages so that when the Rails Asset Pipeline builds application.css it does not concatenate many potentially conflicting styles and forcing developers to deal with them with all sorts of complicated hacks. Having a controller-specific CSS loaded per controller page in addition to application.css results in much lighter more maintainable page specific styles.

So, what was the gotcha?

Well, upon updating the controller specific CSS, I noticed that its styles were not reflected when I was navigating between the controller pages until I refreshed the browser page completely. Turns out, that is because I did not have turbolinks tracking enabled, so I had to add this option to resolve the problem: , "data-turbolinks-track" => true, changing the erb to:

<%= stylesheet_link_tag params[:controller], media: "all", "data-turbolinks-track" => true %>

2. On-document-ready JavaScript events were not firing on page navigation

For example, if you have JavaScript code that converts form hints into tooltips like the following code (in CoffeeScript):

$ =>
  $('.hint').tooltip(placement: 'right')

The code above relies on jQuery's shortcut method $ for executing some JavaScript (CoffeeScript) code upon page document load (document ready).

When visiting the form for the first time, the tooltips show up. However, when navigating away to the home page, and navigating back to the form page, the tooltips do not show up anymore.

Turns out that it is expected behavior by Turbolinks' definition. After all, the Turbolinks feature does not reload JavaScript files on page navigation, missing out on the activation of hint tooltips on document load.

Fortunately, the Turbolinks feature offers developers a way to get around this through its own event hooks fired on page navigation. They are detailed in the Turbolinks github repo (highly recommended to visit to learn Turbolinks in depth).

The event hook I used in particular was: "page:load" (2020 update: "turbolinks:load"). Using it alone did not resolve the problem however as it worked for page navigation, but not initial page load (2020 update: the docs claim the new "turbolinks:load" now works for both initial page load and later page visits), so I used it in addition to the original jQuery $ method as follows:

$(document).on "page:load", =>
  $('.hint').tooltip(placement: 'right')

So in essence, the gotcha fix was to wrap all the page document load logic in a JavaScript function, and then hook it into both on-document-ready (jQuery $) (2020 update: the docs claim this is no longer needed with "turbolinks:load") and Turbolinks "page:load" (2020 update: now "turbolinks:load")

Experience:

Now regarding my overall experience with Turbolinks, I thought it was a very welcome addition to Rails. It worked quite perfectly once I have gone beyond the two gotchas, resulting in an impressively instant page navigation and making local browser testing much faster and more productive. The JS libraries I have used with Turbolinks by the way are the Spectrum Color Picker, Twitter Bootstrap Tooltips, and Fancybox in addition to usage of JS media queries.

In a way, Turbolinks is the perfect embodiment of the Rails philosophy of discovering common patterns, automating their solutions to be as effortless and friction free as possible for everyone to use, and finally offering the ability to customize or disable all-together. By the way, you can opt out of Turbolinks by adding the attribute "data-no-turbolink" to the HTML body element or divs for which you want links to behave regularly. In essence, Turbolinks' implementation satisfies the 80/20 rule, automating the solution for 80% of the cases (not literally) to increase productivity and allowing developers to customize the solution in the remaining special 20% of the cases (not literally) to allow flexibility. Using Turbolinks is also an instance of following Convention over Configuration.

In conclusion, Turbolinks is like driving your first Porsche. The first couple of times you drive the car, you are out of control and do not know why the hell the car is not behaving like a good old Honda, but then you finally get the hang of it, and suddenly find yourself flying in a 911 Turbo. ;)

Saturday, April 27, 2013

Managing Rails Routes When They Get Out Of Hand

Rails developers have gotten really good over the years in breaking down logic in beefy controllers to business domain logic that lives in Models and some reusable control logic that lives in Controller Modules. Not only does this address cohesion concerns, but also the lines per file recommended limit of no more than say 200 in Ruby or 400 max.

However, what I have not seen done often enough in most of the projects I've worked on is handling of these concerns in the Rails Routes file "routes.rb". I've often seen gigantic routes files that not only take a long time to detangle and understand, but also aren't organized in any fashion as to the grouping of routes per business domain area (e.g. Feature A routes, Feature B routes, etc...), which brings us to the topic of this blog post. :)

If you simply follow the software engineering recommendation to break files into smaller ones once they've surpassed a limit of say 400 lines, then a route file (typically 500+ on bigger Rails projects and sometimes 1000+ or even 2000+) is naturally to be broken into multiple route files.

There are several techniques for doing it, but here is one easy technique that I've used on the last couple of Rails projects I was on:

1. Break routes.rb along these lines: Static Routes, Admin Routes, Account Routes (e.g. authentication with devise), and Per Feature Routes (e.g. Company Management Routes, User Personalized Info Routes, etc...)

2. Create directory "config/routes" to store smaller route files

3. Create a route file under "config/routes" for each one of the functional areas mentioned in Step 1, named "XYZRoutes" and holding a Ruby module like the following example:

module Routes
  module AccountRoutes
    def self.draw(context)
      context.instance_eval do
        devise_for :users, :controllers => { :registrations => "registrations", :sessions => 'sessions' }
        devise_scope :user do
          get "/login" => "sessions#new"
          delete '/logout' => 'sessions#destroy'
          get '/logout' => 'sessions#destroy'
          get '/register' => 'registrations#new'
        end
      end
    end
  end
end


4. Update routes.rb to look like this:


Dir.glob("#{Rails.root.to_s}/config/routes/**/*.rb").each {|route_file| load(route_file)}

SomeApp::Application.routes.draw do
  Routes::StaticRoutes.draw(self)
  Routes::AdminRoutes.draw(self)
  Routes::CompanyRoutes.draw(self)
  Routes::AccountRoutes.draw(self)
  Routes::UserRoutes.draw(self)

  mount JasmineRails::Engine => "/specs" if defined?(JasmineRails)

  root :to => "home#index"
end

This should provide you with a good blueprint for how to better organize routes files in Rails.

To summarize, break down routes.rb in Rails when it gets over 400 lines of code for the following benefits:

  • Higher cohesion per route file, improving general understanding of that area's focus as well as ease of maintainability by allowing you to find URLs for a particular domain area faster.
  • Better management of route content by not having to scroll through 100s of lines of code (sometimes 1000s) to find the URL that you want to change

I've worked in an environment once where the development team wrote an internal library to streamline modularization of routes.rb. If you know of a public open source one, please mention in comments.

2022-03-01 Update:

Rails now supports breaking up route files natively through the `draw` macro:

https://guides.rubyonrails.org/routing.html#breaking-up-very-large-route-file-into-multiple-small-ones

# config/routes.rb

Rails.application.routes.draw do
  get 'foo', to: 'foo#bar'

  draw(:admin) # Will load another route file located in `config/routes/admin.rb`
end

# config/routes/admin.rb

namespace :admin do
  resources :comments
end

This should have been mentioned a while ago, but better late than never I guess.

Sunday, October 02, 2011

Decoupling Views from Controllers in Rails (Smalltalk MVC Style)

Updated on 2022-09-23: mostly clarifications for the latest versions of Rails

Last week, I gave a talk at the Groupon weekly GeekFest event titled "Smalltalk MVC Applied in Rails". Though the talk briefly touched upon Smalltalk's original MVC pattern and how it is applied in desktop development, the main focus of the talk was on decoupling views from controllers in Rails the way they are decoupled in Smalltalk MVC, so I would like to elaborate more on that in this blog post.

The diagram above shows the relationship between Model, View, and Controller in Smalltalk MVC with desktop development.


  • The Controller observes the View for changes caused by user interactions (e.g. clicking a button, making a selectiong, etc...)
  • The Controller causes updates in the Model when it receives a notification from the View
  • The View observes the Model for changes caused by invokations from the Controller (e.g. add a new contact) or by Model change events (e.g. a customer birthday has been reached in system time)
  • The View refreshes itself automatically from the appropriate models it is providing a view of.
Notice that nowhere in that flow does the Controller directly interact with the View to update it with Model data. In fact, well written desktop applications avoid that sort of coupling to ensure clean separation between control flow and presentation logic.

One thing to note also about Smalltalk MVC on the desktop is that Views are objects in desktop applications with the intelligence of any other objects. Like Models, they are responsible for maintaining their own state as per the object oriented paradigm. They do not require another class like a Controller to update them. However, when presentation logic gets complex enough, it is a good practice to then split that into a Presenter layer between Views and Models that follows the Adapter design pattern, adapting View state (e.g. index of contact selected in a list of contacts) into Models (the actual contact object representing the index)

Now, if we were to transfer all of these ideas transparently to the web, View state is simply the parameters (request or session) that are populated by user actions. Controllers get access to them temporarily on user actions to cause updates in Models, but then once they render a View, the View itself can be responsible for translating its state (parameters) into Model objects via a Presenter layer. The Presenter layer in Rails is nothing but the good old (badly named) Rails Helpers. They automatically get access to the View context (request and session parameters), allowing them to act as Adapters that neatly hide the details of converting request and session parameters into Model objects the View can rely on to render its contents. This frees Controllers to focus only on Model updates and routing control logic, avoiding the typical clutter with Model loading logic that we often see in Rails applications. This then decouples the Views from Controllers the way they are in original Smalltalk MVC.

Here is an example of typical Rails MVC code:


Controller:

def show
  @contact = Contact.find(params[:id])
  @region = Region.find(session[:region_id])
  @friend_contacts = @contact.friends_by(@region)
  @news = News.latest
end

View:

_contact.html.erb:

Name: <%= @contact.first_name %>
Last Name: <%= @contact.last_name %>
Phone: <%= @contact.phone_number %>
...

_region_header.html.erb:

<%= @region.name %>
<%= @region.state %>
<%= @region.city %>
...

_friends.html.erb:

Friends
<% @friend_contacts.each do |friend_contact| %>
  <%= link_to friend_contact.name, contact_path(friend_contact) %>
<% end %>
...

_news_feed.html.erb:

Latest Happenings:
<% @news.each do |news_feed_item| %>
  <%= news_feed_item.story %>
<% end %>
...

Here is the same example benefiting from the Smalltalk MVC pattern:

Controller:

def show
end

Helper (Presenter):

def contact
  Contact.find(params[:id])
end

def region
  Region.find(session[:region_id])
end

def friend_contacts
  contact.friends_by(region)
end

View:

_contact.html.erb:

Name: <%= contact.first_name %>
Last Name: <%= contact.last_name %>
Phone: <%= contact.phone_number %>
...

_region_header.html.erb:

<%= region.name %>
<%= region.state %>
<%= region.city %>
...

_friends.html.erb:

Friends
<% friend_contacts.each do |friend_contact| %>
  <%= link_to friend_contact.name, contact_path(friend_contact) %>
<% end %>
...

_news_feed.html.erb:

Latest Happenings:
<% News.latest.each do |news_feed_item| %>
  <%= news_feed_item.story %>
<% end %>
...


Notice how the last partial did not even need a Presenter and went to the Model directly since it did not rely on any specific View state (parameters).

Of course, you might want to memoize helpers if you use repeatedly in the view:

Helper (Presenter) with memoization:

def contact
   @contact ||= Contact.find(params[:id])
end

def region
   @region ||= Region.find(session[:region_id])
end

def friend_contacts
   @friend_contacts ||= contact.friends_by(region)
end

Here is a summary of the benefits of decoupling Views from Controllers by allowing them to refresh their data directly from Models as per Smalltalk MVC or use Helpers as Presenters/Adapters for View state (request and session parameters):
  1. Unclutter Controllers from data loading logic for multiple objects that the View needs, allowing each part of the View to load its data directly.
  2. Make View partials easily reusable as they rely on Presenters/Adapters (Helpers) to load their data by pull instead of having to include code in every reusing Controller to push the data into the Views.
  3. Easily test-drive and maintain the logic of Presenting/Adapting View data in small cleanly separated methods instead of having that logic all mixed in Controllers.
  4. When Models needed for the View have dependencies in their load order, there is no need to explicitly order their loading in the Controller. Helper methods can be composed of other helper methods, resolving the dependencies automatically.
  5. Avoid the dissonance in View code caused by a mix of "@object" references and Helper "object" references. All objects in the View get populated from Helpers with "object" references or directly from model classes making the code more readable.
  6. Trivial extraction of partials from Views given that they do not contain any "@object" variables and all references are "object" references. Developers thus do not need to put any effort into error-prone switching of "@object" variables into "object" locals. The helper "object" references can already serve as locals.
  7. Controllers already have access to the context of Presenters (Helpers) thus are able to reuse the View data loading logic without the need to duplicate.
  8. If multiple Controller actions and Views rely on the same data object being present as in the new, create, edit, update, and show actions (e.g. contact object). A single Presenter method (e.g. "contact" helper) can take care of loading that object regardless of whether new or existing in the database already (e.g. Contact.find_or_initialize_by_id(params[:id]) [more recently Contact.find_or_initialize_by(id: params[:id])] )
These are some of the benefits experienced in my last three Rails projects, giving the team great flexibility in maintaining Views, Models, Controllers, and Presenters without the mix of concerns typically experienced in Controllers, allowing for much easier test-driven development and flexibility in composing/modifying features for customers.

In fact, by following Smalltalk MVC correctly in Rails, you would not need any extraneous "View Component" libraries because you would already be building view components natively as demonstrated by the presenter examples above, which can either be well-factored helpers or partials. Such extraneous libraries only add layers of unnecessary complexity due to a misunderstanding of how to follow Smalltalk MVC correctly in the first place.

p.s. The "region" Helper above can optionally be enhanced to manage the region session state in isolation of any Controller, thus maximizing reuse for the Views relying on that View state (parallel to how desktop Views manage their own on-going state as smart objects). Here is one of several ways to do this:

def region
  session[:region_id] = params[:region_id] if params[:region_id]
  Region.find(session[:region_id])
end

p.s.2 Though "before_filter"s in Rails (more recently "before_action"s) can be used to easily load data in controllers, they still put the onus on the controller to do the data loading by push, requiring developers to add such logic to every conroller that will reuse a particular View partial, and adding complexity to reasoning about the code.

--

If you have any questions, remarks, or corrections, feel free to share in comments.

Wednesday, September 07, 2011

The Rails Engine That Could

I gave a lightning talk at Groupon's weekly tech event "GeekFest" the other day titled "The Rails Engine That Could"

The talk covered a successful utilization of Rails Engines in a Rails 3 project to modularize MVC features as reusable components. These components provide the best of both worlds, improved productivity through reusable MVC code, and better flexibility by allowing different applications to customize behavior as needed without dirty conditionals by relying on the Extension Point pattern (as used in the Eclipse IDE). Of course, given the benefits of Ruby, no XML is involved in the extension points, but how that was accomplished is beyond the scope of the lightning talk and can be covered in a future blog post.

Check out the slides over here:

Follow-up one-hour long presentation has been posted over here: The Rails Engine That Could - In Motion

Tuesday, June 03, 2008

Internal DSLs: Part 1

Ruby as a language helps rapid application development by facilitating composition and use of internal DSLs (domain specific languages) without the need to write complex parsers and compilers.

Rails, a popular Ruby web framework, benefits quite a bit from that fact as it has a DSL for specifying object model relationships, a DSL for naming pluralization rules, and a DSL for routing of web URLs to actions.

RSpec, a very popular Ruby testing library, allows developers to write unit-tests and functional tests with a syntax that is very close to plain English, making test code easy to maintain and useful as specifications of the software.

So, DSLs help developers raise the level of abstraction and reduce the input needed from users/developers to the absolute minimum necessary for getting the job done.

As an example from Glimmer, a new Eclipse Technology Project for SWT GUI development, here is how a UI author would create a shell with a label:

shell {
  label {text "Welcome!"}
}

As you can see, this is the bare minimum needed to visually represent a shell containing a label.

Coding the same example in plain Java yields the following:

Shell shell = new Shell(Display.getDefault());
Label label = new Label(shell, SWT.NONE);
label.setText("Welcome!");

With the Java API, the developer has to be concerned with lower-level details, such as object assembly mechanisms and setting values following the JavaBeans standard, neither of which are truly UI authoring concerns.

Here is another example taken from Rake, a popular Ruby make-like build tool:

task :generate do
  # code generation logic
end

task :load => :generate do
  # database data loading logic
end

task :test => [:generate, :load] do
  # test running logic
end

What is noteworthy about the Rake DSL is the visual factor of the syntax. Arrows are used to indicate dependency in a similar fashion to how one might use arrows in a hand-drawn diagram.

Without a DSL, the tasks could have been written as:

def generate
  # generate running logic
end

def load
  generate unless generate_ran
  # load running logic
end

def test
  generate unless generate_ran
  load unless load_ran
  # test running logic
end

As you can see, with purely imperative logic, the developer works at a lower abstraction level by having to manage the task run-order dependencies. While it may seem simple in that example, that can bloat to pages of code with enterprise Rake scripts, increasing the code surface and probability of making mistakes.

Therefore, not only does relying on internal DSLs help developers raise the level of abstraction, but it also minimizes the amount of code needed, thus reducing the probability of making mistakes and increasing productivity further.

Nonetheless, with all the excitement about internal DSLs, people may wonder... How do they compare to external DSLs? Where does their use really fit in? Can they be used by stakeholders or are they limited to developers only? Are there other alternatives?

Stay tuned for answers to these questions in future blog posts.

Wednesday, January 02, 2008

Glimmer Repolished

While many people in Chicago celebrated the new year with a binge of chain-smoking since it's banned in public places starting 2008, I spent the first day of 2008 with a different kind of binge... yes, you guessed it: a programming binge! :P

I initially started Glimmer as a giant spike with the help of Nick Malnick. Later, I covered it with unit-tests with the help of Dave Hoover. Now, I finally re-wrote Glimmer test-first to make it extensible.

What are the benefits I realized from test-driven development:
  • 100% unit-test coverage: every line of code was driven by a failing test, so I have a level of confidence about the reliability of the code
  • Test-driven design: having tests covering my code as a safety net enabled me to make bold refactorings to produce code that is very modular, maintainable, and extensible
  • Incremental sustainable pace: since I only write enough code to satisfy functionality required by one failing test at a time, I never get stuck debugging a mountain of issues as when writing code for a lot of functionality at a time. This gives me a sustainable pace of test/implement/refactor.

Additionally, test-driven design of the code opened my eyes to several ideas, one of which is applying the Chain of Responsibility Design Pattern. After all, Glimmer's DSL processes different commands that perform different tasks, such as instantiating a widget, setting a property, and data-binding, so why not create a chain of command handlers ordered in a certain way, and hand them the job of processing the DSL syntax? Makes a lot of sense, doesn't it? Especially, given the fact that with this design, any programmer can contribute new command handlers to the chain, thus extending Glimmer in any way needed.

In the future, I will talk more about how to extend Glimmer given its new architecture. For now though, happy new year everyone! :)

Sunday, December 30, 2007

Domain-Driven or Database-Driven?

Rails' style of domain modeling with ActiveRecord has developers create database migrations that are used to generate database tables and domain models.

Hibernate on the other hand, which is the technology used by Grails, encourages developers to create the domain models first, and then generate a migration for the database (using SchemaUpdate.) The focus of the developer work is on pure domain modeling.

Given that the focus of the ActiveRecord approach is on the structure of the domain models as persisted in the database, I call it Database-Driven. On the other hand, since the Hibernate approach puts the focus on pure domain modeling in the programming language, I call it Domain-Driven.

Is either approach better than the other?

While, it is generally a matter of personal taste, there are potential trade-offs.

Benefits of the Database-Driven approach over the Domain-Driven approach are:
  • Programmers with a DBA background may be more comfortable designing the database first
  • If performance was a typically big concern in the environment due to server limitations or other reasons, the Database-Driven approach reminds programmers to consider performance implications of their model design early


  • On the other hand, benefits of the Domain-Driven approach over the Database-Driven approach are:

  • Since the Database-Driven approach requires programmers to think about things like foreign keys and join tables, which are not related directly to the business domain model, programmers with an OO and Domain-Driven Design background might be more comfortable with the Domain-Driven approach.
  • Programmers who test-drive every line of code, including creation of the domain models, through the application layer (controllers), will be more comfortable with the Domain-Driven approach since the Database-Driven approach may seem distracting with the requirement to write migration code and generate the models amidst the TDD cycle.


  • Which approach do you prefer and why? It would be interesting to learn about other trade-offs between the two approaches.

    Wednesday, December 05, 2007

    Validation Bubbles

    Over the last week, I have cooked a mini-framework on top of Struts at a client site to facilitate development in a domain-driven way inspired by the Naked Objects approach. This was done by benefiting from the latest features in Hibernate 3, which are utilized in the JBoss Seam web framework.

    Validations were defined on domain model fields using Hibernate Annotations, such as @NotEmpty, @Email, and @Regex. Based on these annotations, database tables were generated automatically using the hbm2ddl tool, and validations were performed automatically utilizing a technique that I like to call Validation Bubbles.

    How do Validation Bubbles work?

    Whenever a model is saved, it validates itself (using the Hibernate validation framework.) If errors are found, they are wrapped and thrown in a validation exception, which bubbles up from the domain model layer to the application layer. At that point, the exception is caught by a custom Struts action super-class that stores validation messages as a request attribute. When the JSP page is being rendered, a custom JSP tag picks the validation messages from the request and renders them on the web page to the user.

    What benefit do we get from Validation Bubbles?

    The application layer gets cleaned up quite a bit as Struts actions do not need to invoke validation explicitly anymore. As long as a Struts action extends the custom Struts super-class that catches bubbled validation exceptions, its logic only needs to handle orchestrating the business use-case.

    Additionally, by placing business validation rules on domain models, and generating the database tables and page-level validations from them automatically, we eliminate redundancy as we do not need to define the same validation rules in multiple places anymore.

    Now, it would be cool if we can somehow additionally generate client-side javascript validations from the Hibernate annotations on the domain models. That will be my next endeavor.

    Sunday, November 04, 2007

    Why RESTful Web Services Matter: Part 4

    In Part 3, I concluded my discussion of the benefits of the uniform interfaces in RESTful web services. Today, I will compare message formats between SOAP and RESTful web services.

    SOAP Web Services require sending messages in XML. The format normally used is that specified by the SOAP XML Schema, which is very flexible and able to handle any complex combination of parameters and return values for invoking an operation. The messages consist mainly of an envelope and a body. The envelope describes the message and its encoding, and the body holds the details of the message regarding the request or response.

    For an example, please check this basic SOAP tutorial.

    As you can see, messages in SOAP include information about which operation is being invoked. On the other hand, messages in RESTful web services do not need to include such information as it is implied in the HTTP protocol method being invoked (e.g. GET -> Get, PUT -> Create, POST -> Update, DELETE -> Delete) Due to that, messages in RESTful web services do not need to follow a particular format either, and thus usually have a much ligher format than SOAP.

    Since SOAP messages follow a standard, they do not need to be manually coded as there are tools that can generate them and consume them automatically, based on existing interfaces in the language of choice. On the other hand, RESTful messages are usually proprietary, requiring extra effort on behalf of the programmers to design, generate and consume. That said, there have been efforts to standardize RESTful messages in particular domains and provide automatic generators and consumers. The best example for that is the Ruby on Rails RESTful web services generated using the Rails scaffold_service command.

    The benefits one gets from using SOAP messages are:

    • Flexibility to handle any method names, combination parameters, and return values

    • Preserving continuity of domain models across the wire, by being able to pretend you are working with a local service

    • Availability of Web Service generation/consumption tools due to having a standard


    The benefits in having a less-rigid message format as usually used in RESTful web services:

    • Easier to read messages when troubleshooting problems

    • Less data overhead in the message format, improving performance over the wire dramatically, especially when sending and receiving many small messages.

    • Breaking the domain model by switching to simple CRUD operations when data traverses wires reminds developers of the important concerns related to network communication, such as reliability and performance.


    If your integration use-cases are usually simple and not numerous, you can save yourself from dealing with a lot of complexity by employing RESTful web services instead of SOAP Web Services (or a hybrid approach), gaining generally better performance, scalability, reliability, and popularity for your web services. One of the best examples is the Amazon S3 web service, which due to RESTfulness has a very wide popularity over the web today.