A Java Developer’s Switch to Rails

As I read this account of transitioning from Java EE to Ruby on Rails,”Java Web Apps to Rails, A Developer’s Experience,” I thought the following:

Regarding the lack of a good Ruby/Rails IDE:

When it was time to look at the code, I was a bit disappointed.  TextMate looked like a popular choice but it fell short in many ways.  I struggled to navigate the code, link the methods across files and follow the code. Grep was my only savior.

I am surprised he did not find RubyMine. JetBrains makes awesome IDEs (IntelliJ IDEA for Java, too). I have to admit at being very impressed that the underlying model of the ruby code within the RubyMine IDE is amazingly capable of giving you the same sort of features that it can for a “compiled,” or more type-centric language like Java.

Ruby

Next he mentioned about learning the language…

My approach to learning Ruby was to start looking at code and figuring out pieces of syntax that did not make sense.  That turned out to be a bad idea. Constructs like “do |x| x+1” threw me off. … I found it very important to understand the motivation behind creating the new language.

There are some good books out there, and other resources…

Another comment rang true with me:

I found it very important to understand the motivation behind creating the new language.

More about the motivation behind Ruby… or at least, how I interpret things.

Ruby treats you like an adult. It doesn’t baby you, or hold your hand, or make you type all sorts of (obfuscating, in my opinion) fluff that a compiled language needs. Your code is more compact and obvious and “dense with meaning,” leading to less need for things like method return types and method parameter data types. Or semicolons.

However, I miss parameters list, curly braces, return statements, camel case naming conventions…

Be patient… soon you will grow weary of having to read all that extra stuff when you go back to Java. If you write well-formed classes, and very small, compact, and obvious methods, you don’t need the extra frills. You will run across the concept of “duck typing” which really means that classic C++/Java/C# style interfaces are not needed. If you create a method that expects a passed-in object to respond to a method call (e.g., “torque”), any object of any class will do — as long as it has that method call! And if you pass in an object that does not have that method, Rails will kindly throw an exception.

The concept of ‘open classes’ that allow developers to go in and change a base class sounds scary.

Go back to my opening statement. “Ruby treats you like an adult.” If you are naive, you can blow your code up and break stuff. If you do everything the Ruby way, you’ll be fine — because you will catch it with tests (right?). There are good rules of thumb for how and why and when you should consider adding to an existing class — or worse, monkey-patching. In Ruby you can actually alter the behavior of an existing method of an existing class. Do it poorly, and you will pay the price. And maybe not for a year or two. Mwahahahaha.

Ruby’s metaprogramming is incredibly powerful (even if the syntax takes a bit of getting used to).

Rails

Rails is incredibly opinionated about how the MVC code should look. It is basically a model-driven architecture approach. The framework expects the MVC stack to have a model, a view, and a controller for each domain concept. (As a long-time domain modeler, and UML guy, this is a real treat.) You can use the default rails generators (interesting when first starting, or for banging out a quick prototype), or write your own twist on a generator. Instead of focusing on the boring framework bits with repetitive, template-like code for each domain object, you can focus on quickly creating features that people want to use and pay for 🙂

Supporting Cast

Ruby on Rails has a great ecosystem of wonderfully talented folks providing 1000s of gems to do all sorts of useful things. For example:

The ecosystem of supporting tools is incredible. Some of my favorites:

These all make it so easy to “do the right thing” and write code with BDD/TDD to provide quality from the start.

Personally, my switch from J2EE to Rails (not to mention SQL to NoSQL/MongoDB) has been one of pure pleasure. The kinds of rich functionality and the ability to build stuff faster is imprerssive. I only wish I were better at writing kick-ass Ruby, Rails, CSS, Javascript, MongoDB…

Is it perfect? Of course not. There are other cool things to look at as well… Meteor, Node.js, MEAN, etc. So much to explore, so little time.

Back to my continuous learning!

 


Don’t be the Frog!

Ever hear the muse about the frog and the boiling water?

I use it to describe the behavior where we innocently allow otherwise really odd things to happen to software products over time. “Oh, it’s been like that for 10 years!” It is never a single, discreet moment in time; instead it kind of “sneaks up” on you if you are not paying attention.

For example:

  • Code that is hard to unit test without bringing in all sorts of dependencies (even mocking barely helps)
  • That javascript error that happens in (unsupported) Firefox, but not in (supported) IE or Chrome
    • Instead of being more compatible with all modern browsers via a simpler and more consistent UI framework.
  • Context menus (right-click) that have everything but the kitchen sink in them
    • Instead of more clearly articulating the commonly-used vs the rare menu choices
  • A UI that nearly defies Cucumber/Capybara testing
  • A “Save As” dialog that also offers up to the user the ability to control the next landing page, to deactivate the item, to create a new item under a new parent, and to generate the PDFs for the item All under Save As!
    • Instead of making the UX more clear and solving the real problem: undesirable workflow.
    • We have Save. We have Save As. But wait! There’s more! You can Save As, give a new name, and choose from 3 different pages to go to next!

I often think it stems from a few common shortfalls:

  • The real problem was not solved, but simply masked
  • Complexity begets more complexity
  • The domain is not understood, so incompatible fixes are tacked on in the wrong spots
  • We didn’t have time to do it right, so we just got something that would work shipped
  • The customer(s) wanted it built like this
  • There is no overriding vision for the type of user experience we want to convey
  • There is no hard-ass product owner putting their foot down

Don’t let this discourage you if you are still outside the pot looking in at friends and colleagues who are in the hot water. It’s an opportunity to improve, clean up, straighten things out, and start anew.

Don’t be the frog!

 


 

Best way to Learn Authentication?

This was a question posed on the Rails Studio mailing list…

My initial reply to a suggestion to check out Railscasts was…

And then, once you are happy with your learning, throw away all of your Auth code and get the Devise gem loaded and working 🙂

To which, the OP replied:

Hmm, I would think your own custom solution would always be smoother than using someone else’s code. Why use Devise?

Here is my reply:

One day, in a galaxy far away, I needed to have millisecond resolution timing on the PC to do some reaction time experiments with subjects as they were exposed to various shapes and colors (eventually used to improve HUD symbology for fighter aircraft display). Since the computer timer chip could only get down to 54ms, I was on the prowl for a better way. Lo and behold, I found some assembly code techniques I could use to over clock the timer chip. Problem solved. I hated writing assembly code… But I had to. Must. Not. Be. Blocked.

Product went into production, and was used by the researchers…

A month or two later, I found an awesome timer package for $50. It did what I needed and more, by a guy who specialized in this.

As fast as I could, I ripped out my code and dropped in the new library. I never looked back. You see, timing was not core to my research app, but rather contextual (like printing or graphing). (As an aside, the module grew and grew and kept up with hardcore CPU vagaries… it was able to tune itself in spite of processor logic becoming much less predictable as it went from 286 to 386 to 486 to 586. I was glad I didn’t have to keep up with the CPU technology! I used this same core functionality on apps that I wrote to control missiles in real-time.)

So, if your business is all about writing an authentication module, then that is what is “core” for your work, and you should craft your own and hone it to perfection.

Or, if you just want to do it as a learning exercise, that is great! Learn, and then pitch your code.

But for me, I am all too happy to drop in some other folks’ gem that gets a set of functionality up and running quickly, so I can get on with my core functionality and not be distracted.

YMMMV

Easing New Developer Ramp-up Time

On a recent healthcare start-up team, it grew from my buddy (who moved on after 6 months or so) and I, to a handful of developers/sub-contractors.

Here is how we tried to make it fairly efficient. We just started tracking what was needed, getting feedback as each new developer went through the process, and improving the instructions and process along the way. If something was missing, we added it. If something was not clear, the new developer could amend the wiki.

By the 3rd new developer, or so, we had it down to where they could get started and begin a legitimate issue in less than a half day — from getting set up to being able to commit and deploy a new “feature.”

There was a section at the top that shared a good team chat room session with a new remote developer:

Getting Started Chat Room Conversation

That was followed by the FAQ-like list of links:

One of the first reasons I wanted to make it easy for a new team member to get rolling, was so that our friend Max — who would be doing our QA from Russia — could get started. As we added the first couple of devs, we probably decreased the start-up time as follows:

As part of “Getting Started,” I would include a simple Jira issue that helped them ensure that everything was working and that they followed our dev process:

  • Git and Dev and database (MongoDB) environment obviously had to be set up
  • Access to Jira to assign themselves to the issue, and move it — Kanban style — to the In Progress state.
  • Commit the work and the passing tests
  • Drag the Jira issue to “Done”

 

Since Atlassian’s Confluence Wiki does a stellar job at versioning pages, I actually looked back to see how the page grew and morphed over time. It started out rather modestly (and empty):

After it grew a bit bloated:

It was successively refactored into its current state, here is a snippet of the 70 versions that this page underwent from March 2011 through July 2012.

Wikis, like code, need to be tended to, nurtured, and refactored to provide the best value.

The Challenge of Naming

John Nunemaker wrote a very nice article on assorted tips that improved his code… One of which revolved around naming.

Regarding naming… I absolutely agree. It is worth arguing about. The more critical the class is to the system design, the more I might go to the mat and wrestle a good name to the ground. The decision on a name can be a fleeting event, but it will have everlasting impact. Think: Write Once, Read Many. Don’t screw it up for the rest of us!

For a C++ app for manufacturing (’95-98), I employed a very layered architecture. Portable business objects were sent to the thin client (no UI talking to DB crap allowed!). The paradigm of pick lists was commonplace… show me a list of parts. The list UI component merely needed a set of IDs and Names. So each domain class could basically implement the interface and they too could be tossed into a drop-down list. My clever name for this little device never grew past “IdString” — we kind of joked about it, because a better name never surfaced.

When I see something like “GaugeAttributeServiceWithCaching” in isolation, it is not as easy to unilaterally discuss a better name.

However, were this inside a basic system called “Gauge” and I saw a bunch of other classes prefixed with “Gauge” — I would throw a red flag.

BTW: My rules are strict for domain-y things, and less strict for utility classes, and lesser things.

I mostly dislike prefixes, postfixes, redundant things of any sort in a name — class or attribute. If I have to mentally strip off a prefix to get at the gist of what I am reading, then it should not be there in the first place.

For example (non-Ruby community, mostly):

  • column names prefixed by the table name (Table User; user_first, user_last)
  • public class attributes prefixed by an underscore (Class User; string _first, string _last)

I also raise an eyebrow and look more closely at any (domain) class ending in “er.” Yup. Try it. Look for some. They are usually “doing” things.

You can go too far in making “God” classes that have no properties of their own, are stuffed full of collaborators via the initializer, and wouldn’t know how to delegate if it hit them over the head. It’s the kind of “Manager” class (there’s that ‘er’) that — instead of asking (delegating) for it’s gauges to compute some stat, it gets all the data from the gauges and does the work for the gauges. Don’t be that guy!

Conversely, look for the boring data class. No methods, just accessor stuff. While it might be just fine, and there truly is no business logic for this class, I would look around just to be sure there are no over achiever “er” classes lurking in the dark alleys — ready to pimp the business logic for the data class.

Thanks for sharing, John!

DRY your RSpecs

Inspired by reading DRY your Scopes

Sometimes I find that I can write a bunch of tedious specs in a simplified manner described below.

It started innocently enough. As a certain set of features were growing, I found that I was writing repetitive tests like this:

context 'specialty patient section' do
  it('has specialty patient') { @plain_html.should =~ /Specialty Patient/ }
  it('has specialty patient trauma criteria') { @plain_html.should =~ /Trauma Activation/ }
  it('has specialty patient airway') { @plain_html.should =~ /Advanced Airway/ }
end

So I threw that aside and simplified:

# Test that certain sections only display when there are data to be shown.
dynamic_sections = ['Vital Signs', 'ECG', 'Flow Chart', 'Initial Assessment', 'Narrative',
                    'Specialty Patient — ACS', 'Specialty Patient — Advanced Airway',
                    'Specialty Patient — Burns', 'Specialty Patient — Stroke', 'Specialty Patient — CPR',
                    'Specialty Patient — Motor Vehicle Collision', 'Specialty Patient — Trauma Criteria',
                    'Specialty Patient — Obstetrical', 'Specialty Patient — Spinal Immobilization',
                    'Influenza Screening', 'SAD (Psychiatric Ax)',
                    'Incident Details', 'Crew Members', 'Insurance Details', 'Mileage', 'Additional Agencies',
                    'Next of Kin', 'Personal Items', 'Transfer Details']

  context 'dynamic sections' do
    let(:p) {
      xml_str = ...some XML...
      Parser.new(xml_str) }
    let(:r) { Renderer::Customer1::HTML.new(p) }
    let(:html) { r.render }
    context ', when there is no info, ' do
      dynamic_sections.each do |s|
        it("should not have: #{s}") { html.should_not =~ /#{s}/ }
      end
    end
  end

Simple stuff… nothing amazing. Simply using ruby’s language to simplify the maintenance of the specs. When a new section is added to the HTML template, it merely needs to be added to the array. And since it is generating actual specs, you preserve meaningful error messages:

Renderer dynamic sections , when there is no info,  should not have: Specialty Patient — Trauma Criteria

The intent of the test is very clear, and 24 lines of “it” specs are avoided.

Lets in RSpecs Can Be Blech

Maybe it is just me, but I had suspected some weirdness here and there from using the fancy “let(:var_sym)” syntax. The trusty RSpec book says:

The first call to let( ) defines a memoized output( ) method that returns
a double object. Memoized means that the first time the method is
invoked, the return value is cached and that same value is returned
every subsequent time the method is invoked within the same scope.

So, it would seem that let() is a great way to define an object once, and use it from there onward.

However, I saw that in this particular instance of running an “expensive” operation in the let block, it took 17 seconds instead of 7 seconds to run the specs! I could see my specs ticking along, very slowly, one at a time. What the heck? I asked myself. Is there something that says “turn caching off (or on)?

Fancy Schmancy! To save ~10 seconds, I’ll forgo the niceties of let() and revert to using the @var_name syntax.

Given the following RSpec code:

 context 'instance methods' do
    let(:sample_xml_file) {File.expand_path('../../data/sample_v_1_13.xml', __FILE__)}
    let(:p) {
      xml_str = File.read(sample_xml_file)
      Nemsis::Parser.new(xml_str)
    }
    let(:r) {Nemsis::Renderer::HTML.new(p)}

    describe '#render_html' do
      context "plain HTML" do
        let(:html) { r.render(false) }

        it 'returns not nil' do
          html.should_not be_nil
        end

        it 'has title section' do
          html.should =~ ...
        end

        context 'specialty patient section' do
          it('has specialty patient') { html.should =~ ... }
          it('has specialty patient trauma criteria') { html.should =~ ... }
          it('has specialty patient airway') { html.should =~ ... }
        end

        it "should not have a STYLE section" do
          html.should_not =~ ...
        end

        it "write to html file" do
          write_html_file(sample_xml_file, "simple", html)
        end
      end

      context "fancy HTML" do
        let(:html) { r.render(true) }

        it "should have a STYLE section" do
          html.should =~ ...
        end

        it "write to html file" do
          write_html_file(sample_xml_file, "fancy", html)
        end
      end
    end
    ...

Contrast the above with the more traditional approach that uses a before block and @variables:

 context 'instance methods' do

    before :all do
      @sample_xml_file = File.expand_path('../../data/sample_v_1_13.xml', __FILE__)
      xml_str = File.read(@sample_xml_file)
      p = Nemsis::Parser.new(xml_str)
      r = Nemsis::Renderer::HTML.new(p)
      @html = r.render(false)
    end

    describe '#render_html' do
      context "plain HTML" do

        it 'returns not nil' do
          @html.should_not be_nil
        end

I did a bit more formal timing, which revealed the truth:

  • let() — 10.7 seconds
  • before block — 2.4 seconds

Am I missing something?

Supporting SSL in Rails 2.3.4

Somehow, moving a perfectly happy production app to Rackspace and nginx caused URLs to no longer sport the SSL ‘s’ in “https” — bummer.

Link_to’s were fine… But a custom “tab_to” (responsible for highlighting the current tab) was not so happy (even though it used an eventual link_to).

Turns out, that it is the url_for method as I learned from here.

I also blended it with some ideas I found here.

# config/environment/production.rb
# Override the default http protocol for URLs
ROUTES_PROTOCOL = "https"
...
# config/environment.rb
# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.5' unless defined? RAILS_GEM_VERSION
# Use git tags for app version
APP_VERSION = `git describe --always --abbrev=0`.chomp! unless defined? APP_VERSION
# The default http protocol for URLs
ROUTES_PROTOCOL = 'http'
...
# application_controller.rb
  # http://lucastej.blogspot.com/2008/01/ruby-on-rails-how-to-set-urlfor.html
  def default_url_options(options = nil)
     if ROUTES_PROTOCOL == 'https'
       { :only_path => false, :protocol => 'https' }
     else
       { :only_path => false, :protocol => 'http' }
     end
  end
  helper_method :url_for

Now the real kicker… Since I do not have SSL set up locally, I had to do some dev on our staging server to tweak the code and test that “https” showed up. so I turned off class caching: config.cache_classes = false.

However, when I cap deployed with it set back to “true” https did not show up. @#$$##@!!!!%%$% AARGH.

I suspect it might have something to do with not being able to open up a cached class and redefine it? I don’t know… I am going to have to go explore this oddity next…

Uncle Bob Challenges The Architecture of a Rails App

Uncle Bob has a very interesting keynote at the Ruby Midwest 2011 conference.

I developed apps with the fundamental architecture of the following (with dependencies only crossing one layer):

——
UI Layer
——
Business Object Layer
——
Data Mgt. Layer
——

Born from the one pattern that is king of the hill in my book: “Separation of Concerns.” The above was my architecture for all projects since the early 90s… C++, Java… but so far not so much in Rails.

I have thought about trying it, but not sure if it will pay off or not.

Essentially, it is about cleaving the rails model classes into two parts:

  1. Business Methods, attributes, business rules
  2. Persistence Methods, attributes, all knowledge of the DBMS details

In general, the UI deals with BOs, but sometimes we create dumb “Data Transfer Objects” that are lightweight versions of the business objects to be thrown about the system.

As a side note, in general, moving code to a more “object-oriented” state often ends up with the same lines of code. And often a bit more due to the boiler plate of creating additional classes.

In a current project, we have pulled out the business objects into a separate gem — but mostly because it needs to be used by our web app and by an eventmachine app.

The thing that shocked me the most about Rails, when Corey Haines introduced me to it in 2009, was that it was a lot like “Model Driven Architecture” that I had worked with for a few years. Given an architecture, a vertical slice thru the app, weave the model thru the architecture generator and out comes an application with a consistent architecture for the bulk of the app that is mostly the same (save for model/property names). Commercially, this MDA technology was a failure, last time I checked. Even though I thought it was the smartest way to develop apps, few others did. Except for Rails developers — largely because most rails devs probably have a very different mindset than other devs.

See blast from the past presentation here.

Though Bob pokes fun at Rails high-level directory structure as not revealing the business domain, I am totally fine with that. It’s a good thing. Yea, sure, it is revealing that it is an MVC style app designed to deliver web apps, so what? No matter which architecture is used, I look for the domain classes to tell me what the system is doing…

In my handful of rails apps to date, I have only used MongoDB and MongoMapper — and this is the closest I have gotten to the good old days of when I used the POET Object-oriented Database with C++ back in the late 90s. It is the closest I have been to nirvana. I basically *almost* don’t need to care that there even is a database…

One of these days, I’ll compare and contrast a Rails/MongoMapper app with and without Business Objects separated from Data Management classes.

Do I Still Do Domain Modeling?

Got a very nice “blast from the past” contact (4 levels deep) on LinkedIn. Scott was a member of a team where we went through object modeling for their business application.

The reason I wanted to contact you was two fold:

First for some reason that training has stuck with me more that many trainings and I still go back to the cobweb section of my brain and bring it out every time I have a object modeling task, so thanks you did a good job helping me.  This is true for many of the people that were there.

Second as I have been given another task of modeling a large system from scratch I was wondering  about how you feel about the Domain-Neutral model that was presented in the training you did for us.  I have found it useful over the years but do you still use this model in anything that you design this many years in the future?

Thanks for the help.
Regards,Scott

And yes, I still do domain modeling the basic way that we did 11 years ago (gulp). I only have my old copy of Together anymore, so I am stuck back in time there. In person, I always use post-it notes, flip-charts, and markers. Once I want to make a computer version, I’ll use different tools for modeling depending on the need. For example, UMLet is a great little simple tool to bang out a quick diagram in no time flat and that can be used by anybody.

Another good approach from what we went through 10 years ago, is to follow the color modeling order to help in the discovery process… that is focusing on the following as you walk through the assorted primary user scenarios:

  1. First trying to discover what time-sensitive aspects does the business care about most (the pinks)
  2. Then looking towards the roles that may be at play there (yellows).
  3. Are there any specific things (like contracts, purchase orders — greens)?
  4. And finally, any descriptive elements (blues) to go alongside the greens?

For the past 18 months, I am in major love with Ruby, Rails, and MongoDB — plus all of the surrounding tools and community (see my recent blog posts). Ruby the object-oriented language I wanted when I was doing C++, and MongoDB/MongoMapper is the OO-like DBMS that I always wanted. Putting it all together makes for real productive, high-quality, consistent development — I can quickly model out domain things and try them in a working application.

I’ve never done an adequate job of explaining how I like to approach doing just-enough design up front, but you can find a few snippets here:

Some tips that I find useful when doing initial up-front Domain Modeling (what you are about to do):

  • Spend time with subject matter experts and the business/product owners
  • Build out as you gather high-level features
  • Do breadth first, then depth
  • Only go into details when it will help reduce an unacceptable level of risk

That last bullet is key. I like to do just enough up-front work to please the stakeholders and myself that we can answer the question about: how much? and when? to the level of desired specificity. When you attempt a high-level estimate at a given feature, and it is too big for your comfort, then you can get more detail and break it down further so that it becomes acceptable.

If you do not do enough up front, and your estimate is off by an order of magnitude or three, you might upset the client!

On the flipside, if you do too much up front (detailed modeling), then you risk not getting frequent, tangible, working results into the hands of the client soon enough.

It’s a big balancing act.