Dean Wampler's Mind: Category Ruby and Ruby on RailsRuminations and Ruinations on Softwaretag:blog.aspectprogramming.com,2005:TypoTypo2007-10-02T14:07:02-05:00Dean Wamplerurn:uuid:46764fb9-bcc2-41dd-9946-20010e605d6b2007-10-02T14:06:00-05:002007-10-02T14:07:02-05:00Presentation on Aquarium with Exercises<p>I’ve posted a <a href="http://aspectprogramming.com/papers/Aquarium_RubyAOP.pdf"><span class="caps">PDF</span></a> for the presentation I did last night on <a href="http://aquarium.rubyforge.org/">Aquarium</a> at the Chicago Ruby Users Group (Chirb).</p>
<p>I also posted a <a href="http://aspectprogramming.com/papers/Aquarium_RubyAOP_exercises.zip">zip</a> file with three exercises that are adapted from the examples on the aquarium web site.</p>Dean Wamplerurn:uuid:5bc010d2-a2d7-462a-b851-ae7bf225a3d32007-09-29T08:30:28-05:002007-09-29T08:30:29-05:00Speaking at the Chicago Ruby Users Group (Chirb)<p>I will give a presentation on Aquarium at Chirb this Monday evening, Oct. 1st. David Chelimsky will also be speaking on new developements in RBehave and RSpec. Details are <a href="http://chirb.org/">here</a>.</p>
<p>David and I will be doing a joint presentation at the December meeting. It will be a tutorial on Ruby metaprogramming.</p>Dean Wamplerurn:uuid:049342b2-318c-4eda-b2aa-77b8a479149a2007-09-17T21:15:00-05:002007-09-29T08:26:42-05:00ANN: Aquarium v0.1.5 released<p>This is primarily a bug-fix release. I labeled it “v0.1.5” instead of “v0.1.1”, because a non-trivial <span class="caps">API</span> change was required; Aquarium no longer automatically adds methods to <code>Object</code>, due to collisions with Rails. This means that users of the “DSL methods” will need to require a new file or include a new module.</p>
<p>See the “CHANGES” file in the distribution of <a href="http://aquarium.rubyforge.org/changes.html">here</a> for more information.</p>Dean Wamplerurn:uuid:8c008adc-056e-4b46-b395-9548b8e980622007-08-23T17:18:00-05:002007-09-29T08:27:02-05:00Announcement: Aquarium v0.1.0 - An Aspect-Oriented Programming Toolkit for Ruby<p>I am pleased to announce the first release of <a href="http://aquarium.rubyforge.org/">Aquarium</a>, an Aspect-Oriented Programming toolkit for Ruby.</p>
<p>I created Aquarium to address a few goals that aren’t adequately addressed by other <span class="caps">AOP</span> toolkits for Ruby. Most of these goals reflect the issues you encounter when using sophisticated aspects in large systems.</p>
<p>First, the most important feature of any <span class="caps">AOP</span> toolkit is the “pointcut” language it provides, which is how you succinctly specify the “join points” across a system where behavior changes are required to support the “cross-cutting concern” that the aspect implements.</p>
<p>Most people assume that Ruby doesn’t need an <span class="caps">AOP</span> framework because its built-in metaprogramming facilities make method interception and wrapping easy. This is the “advising” part of an <span class="caps">AOP</span> toolkit. However, the real value of <span class="caps">AOP</span> is the modularity capabilities provided by the pointcut language. One goal for Aquarium is to match and even exceed the power of the AspectJ pointcut language. I also hope to make it as user-friendly as possible.</p>
<p>Next, Aquarium seeks to handle the issues that arise when multiple advices are applied to a single join point, including precedence control.</p>
<p>Another goal is the ability to add and remove advice dynamically. For example, you might want to insert troubleshooting advice in a running system, then remove it later when the issue is resolved. The first release already implements this feature, with some limitations.</p>
<p>Finally (for now), I want to use Aquarium as a vehicle for experimenting with <a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html"><span class="caps">DSL</span></a> implementation ideas. For several years, there has been discussion (started by Ivar Jacobson) of the idea that aspects share an affinity with Use Cases (or User Stories), because both concepts cross-cut the application domain object boundaries, in one sense or another. So, if I define a <span class="caps">DSL</span> that directly represents a user story, can I map it quickly and efficiently to the implementation objects using aspects? We’ll see.</p>
<p>There is extensive documentation at the <a href="http://aquarium.rubyforge.org/">Aquarium</a> site. Please give it a try and let me know what you think!</p>Dean Wamplerurn:uuid:8e410c37-880e-4372-8ada-1abf784286722006-07-02T23:13:00-05:002006-07-02T23:19:34-05:00RailsConf 2006<p>I attended the first annual <a href="http://www.rubyonrails.org">Ruby on Rails</a> <a href="http://www.railsconf.org">RailsConf</a> in Chicago last weekend and I’ve finally found the time to blog about it ;)</p>
<p>About 500-550 people attended, from novices to Rails experts, including 8 out of 11 of the Rails “core” team. The atmosphere was collegial and somewhat cozy. Everyone realized that future Rails conferences will be a lot bigger and probably more commercial too, given the growing interest in Rails.</p>
<h3>Dave Thomas’ Keynote</h3>
<p>Dave’s was the first keynote of the conference. He described the top-3 unsolved problems on his list of <i><span class="caps">TODO</span>’S</i> for Rails. The list contains somewhat conventional items that you might expect, but what was interesting about the keynote was how the list anticipated some spirited philosophical discussions throughout the weekend.</p>
<h4>Data Integration Improvements</h4>
<p>Dave would like <a href="http://wiki.rubyonrails.com/rails/pages/ActiveRecord">ActiveRecord</a> to extract more information from the schema into the models, such as constraints and associations. He would like better foreign key and compound key support. He would like non-database back-ends supported, like <span class="caps">JMS</span>/MQ systems and he would like support for distributed transactions with two-phased commits, <i>etc.</i></p>
<p>These are all reasonable requests from someone familiar with the typical challenges of “enterprise” (more on that word below…) applications, especially legacy systems. However, this surfaced an on-going debate between the two Daves; Dave Thomas and David Heinemeier Hansson (<a href="http://money.cnn.com/popups/2006/biz2/peoplewhomatter/frameset.34.exclude.html"><span class="caps">DHH</span></a>). <span class="caps">DHH</span> has made clear his preference for keeping all domain logic in the application and using the database as a relatively simple-minded storage vehicle.</p>
<p>As subsequent presentations and discussions indicated, the Rails “core” will get smaller in the future and plugins will provide added support for things not considered “core”. No doubt people will implement plugins for all the things Dave (Thomas) wants, but they won’t be part of the Rails core. But this is okay, as it will satisfy various needs, yet keep Rails lean, mean, and architecturally clean (you can quote me…;) ).</p>
<h4><span class="caps">CRUD</span> and Scaffolding</h4>
Create, Read, Update, Delete (CRUD) operations are the core of typical database-based applications. Dave argued that the Rails scaffolding, which is used to generate stubs for functionality, <i>etc.</i> could be improved to better reflect the growing capabilities of Rails. He would like scaffolding that supports table relationships, in-browser validation JavaScript, <span class="caps">AJAX</span>, <i>etc., etc.</i></p>
<p>Who could argue with that? Well, some people feel that scaffolding is too much of a crutch that discourages neophytes from understanding Rails and adapting it to their needs. Others feel that the scaffolding command-line tools are too primitive and should be more sophisticated. For a promising example of the latter, see the forth-coming <a href="http://www.streamlined.relevancellc.com">Streamlined</a>.</p>
<p>Perhaps most interesting was <span class="caps">DHH</span>’s own keynote, where he discussed his thoughts on more fully realizing the “vision” of <span class="caps">CRUD</span> in rails, but more on that later.</p>
<h4>Deployment</h4>
Dave’s third item was deployment of applications. While <a href="http://wiki.rubyonrails.org/rails/pages/Capistrano">Capistrano</a> is a widely-praised tool for automating deployments, it does have some limitations. For example, out of the box, it really assumes that the developer does the deploying. This may be true for many small shops, but larger enterprises typically have system administrators who handle deployments. The Developers know <i>what</i> to deploy and administrators know the <i>where, when, how,</i> etc. for the deployments. So, Dave advocated enhancements that logically-separate application and deployment configurations. He sighted one example where <span class="caps">J2EE</span> got it right (at least in theory); packaging applications as “archives”, WARs, EARs, <i>etc.</i>, which can be deployed to any standard server.</p>
<p>Deployment was a popular topic at the conference, with several sessions devoted to Capistrano, server topology considerations, <i>etc.</i>
<h3>David Heinemeier Hansson’s Keynote</h3>
<p>Jumping ahead to <span class="caps">DHH</span>’s keynote on Saturday, he replied to some of Dave Thomas’ comments by reaffirming his <a href="http://www.loudthinking.com/arc/000516.html">opinions</a> on topics such as the roll of the database and how far ActiveRecord should go in supporting various database features. For example, he was emphatic that composite keys are a known evil in the database world and ActiveRecord should not support them, at least not as a core feature. Perhaps someone will write a separate plugin, but <span class="caps">DHH</span> believes that if you do bad stuff, it should be painful, not easy.</p>
<p>For most of hist talk, however, <span class="caps">DHH</span> focused on more fully realizing the “vision” of <span class="caps">CRUD</span> in Rails. Create, Read, Update, and Delete are the standard operations in database-backed applications. In forthcoming versions of Rails, <span class="caps">DHH</span> wants to make this model more consistently applied throughout Rails.</p>
<p>For example, <span class="caps">HTTP</span> actually defines four methods, <span class="caps">GET</span> and <span class="caps">POST</span>, which we all know an love, but also <span class="caps">PUT</span> and <span class="caps">DELETE</span>. Roughly, these correspond the Read, Create, Update, and Delete operations in <span class="caps">CRUD</span>.</p>
<p>Our current way of organizing models, controls, and the behavior they offer is reflected in URLs of the form
<pre>.../model/action/id</pre>
For example:</p>
<table>
<tr><th><span class="caps">HTTP</span> Method</th><th>Example URL</th><th>Meaning</th></tr>
<tr><td><span class="caps">POST</span></td><td><code>.../person/create/1</code></td><td>Edit Person with <span class="caps">ID 1</span></td></tr>
<tr><td><span class="caps">GET</span></td><td><code>.../person/read/2</code></td><td>Read Person with <span class="caps">ID 2</span></td></tr>
<tr><td><span class="caps">POST</span></td><td><code>.../person/update/3</code></td><td>Update Person with <span class="caps">ID 3</span></td></tr>
<tr><td><span class="caps">POST</span></td><td><code>.../person/delete/4</code></td><td>Delete Person with <span class="caps">ID 4</span></td></tr>
</table>
<p>Instead, we should be writing more “CRUD’y” URLs of the form
<pre>.../model/id</pre>
and using the <span class="caps">HTTP</span> method to indicate the <span class="caps">CRUD</span> operation. This would allow Rails to apply more <i>conventions</i> for these typical controller operations, thereby minimizing code. For example:</p>
<table>
<tr><th><span class="caps">HTTP</span> Method</th><th>Example URL</th><th>Meaning</th></tr>
<tr><td><span class="caps">POST</span></td><td><code>.../person/1</code></td><td>Edit Person with <span class="caps">ID 1</span></td></tr>
<tr><td><span class="caps">GET</span></td><td><code>.../person/2</code></td><td>Read Person with <span class="caps">ID 2</span></td></tr>
<tr><td><span class="caps">PUT</span></td><td><code>.../person/3</code></td><td>Update Person with <span class="caps">ID 3</span></td></tr>
<tr><td><span class="caps">DELETE</span></td><td><code>.../person/4</code></td><td>Delete Person with <span class="caps">ID 4</span></td></tr>
</table>
<p>Unfortunately, browsers don’t usually support <span class="caps">PUT</span> and <span class="caps">DELETE</span>, so Rails is adopting a convention that hacks around this limitation. For example, the <span class="caps">URL</span> for the update case will look something like
<pre>.../model/id;update</pre>
where the idea for using the semicolon ”;” is based on some documentation written by Tim Berners-Lee himself (for “Semantic Web” concepts, I think).</p>
<p>But there are more ways to “embrace the <span class="caps">CRUD</span>.” Consider a typical example with a <code>Person</code> model and a <code>Group</code> model, where one or more <code>Person</code>s can be a member of one or more <code>Group</code>s. Typically this is handled thusly:</p>
<div class="typocode"><pre><code class="typocode_ruby "> <span class="keyword">class </span><span class="class">Person</span> <span class="punct"><<</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
<span class="ident">belongs_to</span> <span class="symbol">:group</span>
<span class="punct">...</span>
<span class="keyword">def </span><span class="method">remove_from_group</span> <span class="punct">...</span>
<span class="keyword">def </span><span class="method">add_to_group</span> <span class="punct">...</span>
<span class="punct">...</span>
<span class="keyword">end</span>
<span class="keyword">class </span><span class="class">Group</span> <span class="punct"><<</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
<span class="ident">has_many</span> <span class="symbol">:people</span>
<span class="punct">...</span>
<span class="keyword">def </span><span class="method">remove_person</span> <span class="punct">...</span>
<span class="keyword">def </span><span class="method">add_person</span> <span class="punct">...</span>
<span class="keyword">end</span></code></pre></div>
<p>Where should those <code>add</code> and <code>remove</code> methods really go? <span class="caps">DHH</span> pointed out that if we <i>reify</i> (not his term) the relationship between <code>Person</code> and </code>Group</code>, that is, treat it as an model object in its own right, then we can use <span class="caps">CRUD</span> conventions to manage the relationship itself. In this example, a class <code>Membership</code> could encapsulate membership of people in groups. The <span class="caps">CRUD</span> creation operation would add a <code>Person</code> to a <code>Group</code>, deletion of memberships would remove the relationship, <i>etc.</i></p>
<p>Perhaps the most interesting thing about his keynote was how it demonstrated his thorough commitment to pushing design principles to their logically limit in Rails. Where most of us would have been satisfied with the current design, <span class="caps">DHH</span> sees that it can be made even more consistent to the <span class="caps">CRUD</span> vision, and thereby further increase the use of common (and automated) <i>conventions</i>. No wonder Rails is so good!</p>
<h3>Rails Application Optimization Techniques and Tools</h3>
<b>Stefan Kaes</b>
<p>Stefan has done an extensive analysis of Rails performance issues. His detailed talk listed some of his findings. He is working on a book that is due next year, published by Wiley, that promises to be valuable for developers concerned about optimizing performance.</p>
<p>In a nutshell, he listed the following as the top performance problems:</p>
<ul>
<li>slow helper methods,</li>
<li>complicated routes,</li>
<li>associations, especially when loading one object retrieves all associated objects automatically,</li>
<li>retrieving too much data from the database (related to the previous point), and</li>
<li>slow storage of session information.</li>
</ul>
<p>For more details about his findings and recommendation, see Stefan’s <a href="http://railsexpress.de/blog/">blog</a> and his recent <a href="http://www.infoq.com/articles/Rails-Performance">InfoQ article</a>.</p>
<h3>MetaRails</h3>
There were many more interesting talks, but since I’ve taken over a week to get this blog done, I’ll finish with a comment on the excellent <i>MetaRails</i> talk by Stuart Halloway, with an assist from his Relevance partner, Justin Gehtland.</p>
<p>Stuart discussed some interesting uses of metaprogramming within the Rails core that make Rails the amazing environment that it is. Rails is a treasure trove of patterns and idioms that are well worth learning. As neither Stuart nor Justin are members of the core team, they provided an outsider’s perspective.</p>
<p>Stuart mostly praised the quality of the Rails code, but he pointed out one area where he felt it isn’t <span class="caps">DRY</span> enough, the way many <code>ActiveRecord</code> methods are aliased and then replaced with methods that add support for transactions, <i>etc.</i> There are apparently several different areas where the same methods are aliased this way, where each alias provides a different “enhancement.” As these alias statements are not co-located, it would be easy for one such modification to stomp on another. Also, how do you ensure that one alias takes “precedence” (<i>i.e.,</i> gets applied first) over another? For example, you might always want authentication and authorization to happen first. (Note that Stuart’s follow-up <a href="http://blogs.relevancellc.com/articles/2006/06/26/fixing-metarails">blog</a> mentions that the <span class="caps">DRY</span> problem has been partially solved since he started his analysis.)</p>
<p>In fact, he described a classic case that motivates <a href="http://www.aspectprogramming.com/home/aosd">Aspect-Oriented Programming</a>. Even in dynamic languages like Ruby, where metaprogramming facilities are easy to use, <span class="caps">AOP</span> provides a <i>conceptual</i> framework for thinking about certain design issues, like adding transactional behavior to persistent objects or invocation of authentication and authorization challenges before executing otherwise normal-looking methods. Yes, Ruby metaprogramming facilities allow you to implement <span class="caps">AOP</span>-like behavior, but you have to “switch paradigms” to do so. I don’t know how Ruby implements <i>Object</i>-Oriented behavior, but you could image that similar metaprogramming approaches are used or could be used if no OO support were provided. So, yes, you could do <span class="caps">OOP</span>, in this case, but isn’t it nicer to <i>think</i> in objects when you are writing OO code, rather than have to switch gears mentally and think in meta-object protocols? The same argument can be made about providing <span class="caps">AOP</span> facilities in a language, even if those facilities are relatively small additions. For example, <a href="http://aspectr.sourceforge.net/">AspectR</a>, an <a href="http://www.aspectj.org">AspectJ-like</a> Ruby clone, is <a href="http://www.codecomments.com/archive327-2005-5-507143.html">only about 200 lines of Ruby code.</a></p>
<p>I’m going to blog about the role of <span class="caps">AOP</span> in dynamic languages like Ruby in the next few days, so please check back. Also, I’ll be doing a talk on <span class="caps">AOP</span> in Ruby and Python at the <a href="">Dr. Dobbs Architecture and Design World</a> in Chicago, July 17-20. I hope to see you there!</p>
<h3>RailsConf 2007</h3>
Finally, it was announced that <a href="http://live.oregoncc.org/iebms/coe/coe_p2_details.aspx?eventid=7202&cc=OCCCOE&oc=10&dict=27">next year’s conference</a> will be May 17-20 in Portland, Oregon.