<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Merbist</title>
	<atom:link href="http://merbist.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://merbist.com</link>
	<description>Random thoughts of a software developer</description>
	<lastBuildDate>Mon, 19 Nov 2012 01:10:34 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Point of view on career development</title>
		<link>http://merbist.com/2012/11/18/point-of-view-on-career-development/</link>
		<comments>http://merbist.com/2012/11/18/point-of-view-on-career-development/#comments</comments>
		<pubDate>Mon, 19 Nov 2012 01:10:34 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1392</guid>
		<description><![CDATA[Last week I wrote a blog post that turned out to be my most popular blog post of the year with 40,000 unique visitors mainly due to the article being featured on the front page of Hacker News for almost 24 hours. The article focuses on our difficulties as engineers to build a career and [...]]]></description>
				<content:encoded><![CDATA[<p>Last week I wrote a blog post that turned out to be <a href="http://matt.aimonetti.net/posts/2012/11/14/engineers-suck-at-finding-right-jobs/">my most popular blog post</a> of the year with 40,000 unique visitors mainly due to the article being featured on the front page of Hacker News for almost 24 hours.</p>
<p>The article focuses on <a href="http://matt.aimonetti.net/posts/2012/11/14/engineers-suck-at-finding-right-jobs/">our difficulties as engineers to build a career and my own experience dealing with it</a>.</p>
<p style="text-align: center;"><a href="http://matt.aimonetti.net/posts/2012/11/14/engineers-suck-at-finding-right-jobs/"><img class="aligncenter" title="Cliff" src="http://matt.aimonetti.net/images/cliff-dip.jpg" alt="" width="384" height="367" /></a></p>
<p>&nbsp;</p>
<p>Here are some Twitter responses:</p>
<p>&nbsp;</p>
<blockquote class="twitter-tweet" width="500"><p>Some really good points in here on how to think about your career: Engineers suck at finding the right jobs <a href="http://t.co/HjByU8nC" title="http://bit.ly/WdiXuk">bit.ly/WdiXuk</a></p>
<p>&mdash; Larry Wright (@larrywright) <a href="https://twitter.com/larrywright/status/270226080764424192" data-datetime="2012-11-18T18:04:52+00:00">November 18, 2012</a></p></blockquote>
<p><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<blockquote class="twitter-tweet" width="500"><p>I strongly disagree with the man behind it on some topics but <a href="http://t.co/xmGZXaTW" title="http://matt.aimonetti.net/posts/2012/11/14/engineers-suck-at-finding-right-jobs/">matt.aimonetti.net/posts/2012/11/…</a> by @<a href="https://twitter.com/merbist">merbist</a> is an very important post [and initiative]</p>
<p>&mdash; Michael Klishin (@michaelklishin) <a href="https://twitter.com/michaelklishin/status/269210340041056257" data-datetime="2012-11-15T22:48:41+00:00">November 15, 2012</a></p></blockquote>
<p><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<blockquote class="twitter-tweet" width="500"><p>“Most engineers have no idea how their talent and dedication converts into real monetary value” imprescindible lectura <a href="http://t.co/MxQuLZSe" title="http://matt.aimonetti.net/posts/2012/11/14/engineers-suck-at-finding-right-jobs/">matt.aimonetti.net/posts/2012/11/…</a></p>
<p>&mdash; ecamacho (@ecamacho) <a href="https://twitter.com/ecamacho/status/269132540688867328" data-datetime="2012-11-15T17:39:32+00:00">November 15, 2012</a></p></blockquote>
<p><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<blockquote class="twitter-tweet" width="500"><p>&#8220;Engineers are good at solving technical problems&#8230; but when it comes to our jobs and future, we seem to struggle.&#8221; <a href="http://t.co/1VsaCfK6" title="http://matt.aimonetti.net/posts/2012/11/14/engineers-suck-at-finding-right-jobs/">matt.aimonetti.net/posts/2012/11/…</a></p>
<p>&mdash; John Hunter (@curiouscat_com) <a href="https://twitter.com/curiouscat_com/status/269217829558034433" data-datetime="2012-11-15T23:18:27+00:00">November 15, 2012</a></p></blockquote>
<p><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<blockquote class="twitter-tweet" width="500"><p>Fantastic article by @<a href="https://twitter.com/merbist">merbist</a> &#8211; it&#8217;s a great time to be a Software Engineer&#8230;are you taking advantage of it? <a href="http://t.co/Q0cFM00R" title="http://ow.ly/fknt0">ow.ly/fknt0</a></p>
<p>&mdash; Ryan Bennett (@rnbennett) <a href="https://twitter.com/rnbennett/status/269195581904269312" data-datetime="2012-11-15T21:50:02+00:00">November 15, 2012</a></p></blockquote>
<p><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<p>&nbsp;</p>
<p>I inbox almost exploded and days later I&#8217;m still trying to reply to all the people who contacted me for advice. Once manage to collect my thoughts I&#8217;ll probably write a follow up article based on what I learned from the various emails I received.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/11/18/point-of-view-on-career-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rethinking web API design</title>
		<link>http://merbist.com/2012/06/13/rethinking-web-api-design/</link>
		<comments>http://merbist.com/2012/06/13/rethinking-web-api-design/#comments</comments>
		<pubDate>Wed, 13 Jun 2012 17:47:25 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1384</guid>
		<description><![CDATA[I wrote an article talking about the need to rethink the way we approach web service/API design, you can read it there.]]></description>
				<content:encoded><![CDATA[<p>I wrote an <a href="http://matt.aimonetti.net/posts/2012/06/13/rethinking-web-service-development/">article </a>talking about the need to rethink the way we approach web service/API design, you can read it <a href="http://matt.aimonetti.net/posts/2012/06/13/rethinking-web-service-development/">there</a>.</p>
<p><a href="http://matt.aimonetti.net/posts/2012/06/13/rethinking-web-service-development/"><img class="aligncenter size-medium wp-image-1385" title="Matt Aimonetti - Rethinking web service development" src="http://merbist.com/wp-content/uploads/2012/06/Matt-Aimonetti-Rethinking-web-service-development-Matt-Aimonetti-300x294.jpg" alt="Matt Aimonetti - Rethinking web service development" width="300" height="294" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/06/13/rethinking-web-api-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacRuby on iOS &#8211; RubyMotion review</title>
		<link>http://merbist.com/2012/05/04/macruby-on-ios-rubymotion-review/</link>
		<comments>http://merbist.com/2012/05/04/macruby-on-ios-rubymotion-review/#comments</comments>
		<pubDate>Fri, 04 May 2012 15:17:47 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[RubyMotion]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1363</guid>
		<description><![CDATA[Yesterday, RubyMotion was released and let&#8217;s be honest, it is one the best alternatives to Objective-C out there (if not the best). RubyMotion is a commercial, proprietary fork of MacRuby that targets iOS. This is not a small achievement, MacRuby relies on Objective C&#8217;s Garbage Collector (libauto) which is not available on iOS. Static compilation and [...]]]></description>
				<content:encoded><![CDATA[<p>Yesterday, <a href="http://www.rubymotion.com/" target="_blank">RubyMotion</a> was released and let&#8217;s be honest, it is one the best alternatives to Objective-C out there (if not the best).</p>
<p>RubyMotion is a commercial, proprietary fork of MacRuby that targets iOS. This is not a small achievement, MacRuby relies on Objective C&#8217;s Garbage Collector (libauto) which is not available on iOS. Static compilation and new memory management solution was required to target the iOS platform . The new runtime had to be small and efficient. Furthermore, being able to run code on iOS isn&#8217;t enough, you need tools to interact with the compiler, to debug, to packages applications etc&#8230;</p>
<p>I don&#8217;t think anyone will contest the fact that RubyMotion is a well done product. The question however is, &#8220;<strong>is it worth for you to invest some money, time and energy in this product instead of using Apple&#8217;s language and tools</strong>&#8220;. In this article, I&#8217;ll try to balance the pros and cons of RubyMotion so you can have a better understanding of what RubyMotion could mean for you. As a disclaimer I should say that I was beta testing RubyMotion, that they are strong ties between RubyMotion and the MacRuby project I&#8217;m part of and finally that having MacRuby on iOS has been something I&#8217;ve been looking forward for a very long time.</p>
<p>Over the last few months I&#8217;ve seen RubyMotion take shape and finally hit the big 1.0. As you can see from <a href="http://twitter.com/#!/search/rubymotion?q=rubymotion" target="_blank">Twitter</a> and <a href="http://news.ycombinator.com/item?id=3924657" target="_blank">HackerNews</a>, the Ruby community is excited about being able to use their language to write statically compiled, native iOS apps. Spoiler alert, they are right, it&#8217;s a lot of fun.</p>
<p>&nbsp;</p>
<hr />
<p>&nbsp;</p>
<h2>What I like about RubyMotion:</h2>
<h3>Ruby Language</h3>
<p>I don&#8217;t mind Objective-C, I think it&#8217;s a fine superset of C, with the arrival of blocks, new literals and automatic memory management via ARC, Objective-C is actually getting better over time. But frankly, it&#8217;s not Ruby. You still have to deal with headers, you always have to compile your code via some weird Xcode voodoo settings, testing is a pain, the language, even with the new literals is quite verbose. On the other hand, using Ruby syntax I can get much more flexibility, reuse my code via mixins, easily reopen existing classes etc&#8230; At the end of the day, I end up with some code that seems cleaner, easier to understand and maintain even though I&#8217;m calling the same underlying APIs. Ruby&#8217;s flexibility also allows developers to make their own higher level APIs, take a look at some of the <a href="https://github.com/mattetti/BubbleWrap" target="_blank">wrappers/helpers</a> I wrote while playing with RubyMotion.</p>
<p style="text-align: center;"><a href="http://www.ruby-lang.org/en/"><img class="aligncenter  wp-image-1367" title="matt_aimonetti-Ruby_logo" src="http://merbist.com/wp-content/uploads/2012/05/matt_aimonetti-Ruby_logo-150x150.jpg" alt="Matt Aimonetti - Ruby Logo" width="90" height="90" /></a></p>
<h3>MacRuby</h3>
<p>RubyMotion is based on MacRuby, meaning that all the time and energy invested in the project will benefit RubyMotion&#8217;s users. All the concepts I explain in my <a href="http://shop.oreilly.com/product/0636920000723.do" target="_blank">MacRuby book</a> apply to RubyMotion. You don&#8217;t have to find workarounds to work with native APIs, Ruby objects are Objective-C objects and performance is great. I do regret Apple didn&#8217;t decide to embrace MacRuby for iOS but at the same time, even though we lost the Open Source aspect of the project and Apple&#8217;s backing, we gained much more flexibility and freedom on Laurent&#8217;s part.</p>
<p style="text-align: center;"><a href="https://www.amazon.com/dp/1449380379?tag=merbist-20&amp;camp=213381&amp;creative=390973&amp;linkCode=as4&amp;creativeASIN=1449380379&amp;adid=1SKHT7ABMG1YJZ3136WQ&amp;"><img class="aligncenter" title="MacRuby book" src="http://merbist.com/wp-content/uploads/matt_aimonetti/matt_aimonetti_macruby_book.gif" alt="" width="108" height="142" /></a></p>
<h3>REPL/Interactive shell</h3>
<p>RubyMotion doesn&#8217;t currently have a debugger, but it does have something Objective-C developers don&#8217;t have, a <a href="http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop" target="_blank">REPL</a> working with the simulator. This feature is quite handy when debugging your application or learning the Cocoa APIs. You can click on a visual element in the simulator and start modifying the objects in real time in a terminal window and see the modifications in the simulator. It reminds me of the first time I used firebug to edit the html/css of a web page and saw the changes in real time.</p>
<p><a href="http://www.youtube.com/watch?feature=player_embedded&amp;v=rejYKzLglSE#!"><img class="aligncenter size-thumbnail wp-image-1368" title="matt aimonetti - RubyMotion REPL" src="http://merbist.com/wp-content/uploads/2012/05/matt_aimonetti-RubyMotion-REPL-150x150.jpg" alt="Matt Aimonetti - RubyMotion REPL" width="150" height="150" /></a></p>
<h3>Not dependent on Xcode</h3>
<p>Xcode is fine when you write Objective-C code, but it crashes often, it has a complicated UI and never really worked well for MacRuby due to the fact that Objective-C and Ruby have different requirements and the that Xcode is not open source. It&#8217;s also fully controlled by Apple and doesn&#8217;t provide APIs for 3rd party developers. (That said, the Xcode team has often helped out when a new released of Xcode broke MacRuby, so thank you guys).</p>
<p>Being able to use simple rake tasks to compile, simulate and deploy applications is just really really nice. I&#8217;m sure we&#8217;ll end up with better IDE integration, nice GUIs for some who like that, but in the meantime, as a &#8220;hacker&#8221;, I really enjoy the simplicity of the Rake tasks and not being forced in using a specific IDE.</p>
<p>&nbsp;</p>
<h3>Memory management</h3>
<p>Even though ARC made memory management much easier for Objective-C developers, when using RubyMotion you don&#8217;t have to worry about memory (well at least not explicitly, don&#8217;t be dumb and create a bazillion objects and hold references to them either). This includes the CoreFoundation objects that you still have to manually manage in Objective-C. Memory management is transparent and in most cases it&#8217;s really nice.</p>
<p>&nbsp;</p>
<hr />
<p>&nbsp;</p>
<h2>What I like less about RubyMotion</h2>
<p>Here is a list of things that are cons to using RubyMotion, note that while the list is longer than my list of &#8220;pros&#8221;, I listed a lot of small things. I also think that most of these issues will get solved in the next few months.</p>
<p>&nbsp;</p>
<h3>Ruby language</h3>
<p>There are some cases where Ruby just isn&#8217;t that great or is not an option. Examples include dealing with API relying heavily on pointers, when using some of the lower level APIs or when you have to interact with C++ (video game engines for instance). The good news is that within the same project, you can write part of your code in Objective-C and the rest in RubyMotion. The other thing that bothers me a little bit with writing Ruby code for iOS is that you can&#8217;t easily enforce argument types and therefore you are losing a lot of the features provided by Clang to the Objective-C developers. I dream of an optionally typed Ruby &#8212; but that&#8217;s a different topic.</p>
<p>Another downside of using Ruby is that Ruby developers will assume all standard libraries and gems will be compatible with RubyMotion. This isn&#8217;t the case. You need to think of RubyMotion as only offering the Ruby syntax (modulo a few differences). To be honest, most of the std libs and gems aren&#8217;t that useful when writing iOS apps. Even when I write MacRuby apps, I rarely rely on them and pick libraries designed to work in a non-blocking, multi-threaded environment (usually ObjC libs that I wrap).</p>
<p>&nbsp;</p>
<h3>Cocoa Touch</h3>
<p>If you&#8217;re already an iOS/OS X developer, you know that most of the hurdles aren&#8217;t the language syntax but the Cocoa APIs. These APIs are what you need to interact with to create your application. Cocoa APIs are usually much lower-level compared to what you usually see in Python, Ruby or even Java. While they are quite consistent, the APIs still have a stiff learning curve and currently,  if you want to write iOS applications, even if you know Ruby, you still have to learn Cocoa.</p>
<p>However, I do think that with RubyMotion now building a userbase, we will start seeing more and more <a href="https://github.com/mattetti/BubbleWrap" target="_blank">wrappers</a> around these sometimes <a href="https://github.com/HipByte/RubyMotionSamples/blob/master/GestureTable/app/gesture_recognizer.rb" target="_blank">hideous APIs</a>.</p>
<p>&nbsp;</p>
<h3>No Xcode/IDE</h3>
<p>There are cases where an IDE is really practical, especially when learning new APIs. Being able to have code completion, quick access to the documentation, instrumentation, debugging, interface builder, refactoring tools are things that Objective-C developers might have a hard time with when switching to RubyMotion. If you don&#8217;t know either Ruby or Cocoa, getting started with RubyMotion might be quite hard and you are probably not currently in the target audience.</p>
<p>&nbsp;</p>
<h3>Writing UI code by hand</h3>
<p>In some cases, it makes sense, in other, it should be much easier. I know that Laurent is working on a DSL to make that easier and I&#8217;m looking forward to it. But in the mean time, this is quite a painful exercise, especially due to the complexity of the Cocoa UI APIs. Using Xcode&#8217;s interface builder and Storyboards is something I know a lot of us wish we could do with RubyMotion when developing specific types of applications.</p>
<p><a href="http://kurrytran.blogspot.fr/2011/07/simple-ios-5-tutorial-using-storyboard.html"><img class="aligncenter size-full wp-image-1366" title="matt aimonetti storyboard" src="http://merbist.com/wp-content/uploads/2012/05/matt_aimonetti_storyboard-1.jpg" alt="Matt Aimonetti - Xcode iOS storyboard" width="600" height="384" /></a></p>
<h3>No debugger</h3>
<p>Again, this is eventually coming but the current lack of debugger can be problematic at times, especially when the problem isn&#8217;t obvious.</p>
<p>&nbsp;</p>
<h3>Lack of clear target audience</h3>
<p>It&#8217;s hard to blame a brand new product for not having clearly defined a target audience. But as a developer I find myself wondering &#8220;when should I use RubyMotion and for what kinds of problems?&#8221; Is RubyMotion great for quick prototypes I can then turn into production code? Or is good for throw away prototypes? Is it reserved for &#8220;fart and flash light&#8221; applications? Is it ready for prime time and should I invest and write my new awesome apps using it? Should I convert over my existing code base over from Titanium (or whatever other alternatives you used)? Should I use RubyMotion every time I would use Objective-C?</p>
<p>I guess we will see when the first applications start hitting the app store and people start reporting on their experience.</p>
<h3>Documentation</h3>
<p>I&#8217;m partially to blame here since I could have moved my butt and start writing a book but the point is nonetheless valid. All the iOS documentation out there is for Objective-C, all the APIs and samples provided by Apple are obviously only for Objective-C. Thankfully, you can use the 2 MacRuby books available out there to understand how to convert this existing documentation into something useful, but RubyMotion will need to provide better and more adapted documentation for beginners. I have no doubt that this is coming sooner than later.</p>
<p>&nbsp;</p>
<h3>Proprietary solution</h3>
<p>RubyMotion isn&#8217;t open source and currently fully relies on the shoulders of a single man. If unfortunately, Laurent goes out of business or decides to do something else then we will have to rewrite our apps in Objective-C.  Using RubyMotion for a professional product represents a significant business risk, which is exactly the same as using proprietary technology from any vendor. Apple could also decide to switch to JavaScript or rewrite iOS in Java and deprecate Objective-C. Let&#8217;s just say that it is unlikely.</p>
<p>I usually favor open source solutions, from the programming language I use to the OS I deploy on. This isn&#8217;t always possible and if you want to write iOS applications, you don&#8217;t currently have a choice. I do wish Laurent had found a way to make money while keeping the source code open. But who knows &#8212; after he makes his first million(s), he might change his mind.</p>
<p><a href="http://merbist.com/wp-content/uploads/2012/05/matt_aimonetti-rms.jpg"><img class="aligncenter size-thumbnail wp-image-1369" title="matt aimonetti - rms" src="http://merbist.com/wp-content/uploads/2012/05/matt_aimonetti-rms-150x150.jpg" alt="Matt Aimonetti - RMS" width="150" height="150" /></a></p>
<h2>Conclusion</h2>
<p>I would strongly suggest you consider giving RubyMotion a try. I can assure you that it will provide at least a few hours of &#8216;hacking fun&#8217; (and you will be able to brag about havng written your own iPhone app).  It will also help support financially someone who&#8217;s taking a risk in trying to push mobile development to the next level.</p>
<p>RubyMotion is, by far, my favorite alternative to Objective-C. But it is hard to tell, just 48 hours after its release, what people will do with it. Can it transcend the programming language barriers and attract Python, PHP, Java, ObjC and JavaScript developers? What is the sweet spot for RubyMotion applications? Will it affect the native vs web app battle? Can it make iOS development more accessible to the masses? Only time will tell.</p>
<p>What do you think?</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/05/04/macruby-on-ios-rubymotion-review/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Introduction to mruby</title>
		<link>http://merbist.com/2012/04/27/introduction-to-mruby/</link>
		<comments>http://merbist.com/2012/04/27/introduction-to-mruby/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 10:07:16 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[mruby]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1357</guid>
		<description><![CDATA[A couple days ago, I wrote an introduction article to help developers getting started with mruby (aka mrb). Besides explaining the difference between mrb and the other implementations, the article shows concrete examples to embed Ruby inside a C software application. The article doesn&#8217;t mention a few nice tricks such as mruby allowing you replace double [...]]]></description>
				<content:encoded><![CDATA[<p>A couple days ago, I wrote an introduction article to help developers <a title="how to mruby" href="http://matt.aimonetti.net/posts/2012/04/25/getting-started-with-mruby/" target="_blank">getting started with mruby</a> (aka mrb).</p>
<p><a href="matt.aimonetti.net/posts/2012/04/25/getting-started-with-mruby/"><img class="aligncenter size-full wp-image-1361" title="matt aimonetti - getting started with mruby" src="http://merbist.com/wp-content/uploads/2012/04/matt-aimonetti-getting-started-with-mruby.jpg" alt="matt aimonetti - getting started with mruby" width="860" height="687" /></a></p>
<p>Besides explaining the difference between mrb and the other implementations, the article shows concrete examples to embed Ruby inside a C software application. The article doesn&#8217;t mention a few nice tricks such as mruby allowing you replace <a title="mruby commit" href="https://github.com/mruby/mruby/commit/ee30c5a4a44fc26a8b5b8d6a0e35a7a4b6a6be50#diff-0" target="_blank">double by float</a> (though still imperfect), the possibility to replace the memory allocator and it was even reported to me that mruby can run on the <a href="http://en.wikipedia.org/wiki/Lego_Mindstorms" target="_blank">Lego Mindstorms</a> platform which only has 250K of memory!</p>
<p>mruby is still in alpha stage but it&#8217;s getting more interesting every day and at this rate it will soon become a real alternative to Lua.</p>
<p>Learn <a title="getting started with mruby" href="http://matt.aimonetti.net/posts/2012/04/25/getting-started-with-mruby/" target="_blank">how to get started with mruby</a> now.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/04/27/introduction-to-mruby/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>new Ruby: mruby and mobiruby Ruby for iOS/Android</title>
		<link>http://merbist.com/2012/04/23/new-ruby-mruby-and-mobiruby-for-ios-android/</link>
		<comments>http://merbist.com/2012/04/23/new-ruby-mruby-and-mobiruby-for-ios-android/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 09:13:02 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1351</guid>
		<description><![CDATA[A few days ago, I wrote an article covering Ruby creator Matz&#8217; new Ruby implementation: mruby and its first related project: MobiRuby which aims to let Ruby developers write iOS and Android applications using their favorite language. &#160;]]></description>
				<content:encoded><![CDATA[<p>A few days ago, <a title="mruby and MobiRuby" href="http://matt.aimonetti.net/posts/2012/04/20/mruby-and-mobiruby/" target="_blank">I wrote an article</a> covering Ruby creator Matz&#8217; <a href="https://github.com/mruby/mruby" target="_blank">new Ruby implementation: mruby</a> and its first related project: <a href="http://mobiruby.org" target="_blank">MobiRuby</a> which aims to let Ruby developers write iOS and Android applications using their favorite language.</p>
<p>&nbsp;</p>
<p style="text-align: center;"><a href="http://matt.aimonetti.net/posts/2012/04/20/mruby-and-mobiruby/"><img class="aligncenter size-full wp-image-1352" title="Matt Aimonetti - mruby and MobiRuby" src="http://merbist.com/wp-content/uploads/2012/04/Matt-Aimonetti-mruby-and-MobiRuby.jpg" alt="Matt Aimonetti article on mruby and MobiRuby" width="600" height="412" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/04/23/new-ruby-mruby-and-mobiruby-for-ios-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building and implementing a Single Sign-On solution</title>
		<link>http://merbist.com/2012/04/04/building-and-implementing-a-single-sign-on-solution/</link>
		<comments>http://merbist.com/2012/04/04/building-and-implementing-a-single-sign-on-solution/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 15:29:16 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Software Design]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[crypto]]></category>
		<category><![CDATA[SSO]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1301</guid>
		<description><![CDATA[Most modern web applications start as a monolithic code base and, as complexity increases, the once small app gets split apart into many &#8220;modules&#8221;. In other cases, engineers opt for a SOA design approach from the beginning. One way or another, we start running multiple separate applications that need to interact seamlessly. My goal will be [...]]]></description>
				<content:encoded><![CDATA[<p>Most modern web applications start as a monolithic code base and, as complexity increases, the once small app gets split apart into many &#8220;modules&#8221;. In other cases, engineers opt for a <a href="http://en.wikipedia.org/wiki/Service-oriented_architecture" target="_blank">SOA</a> design approach from the beginning. One way or another, we start running multiple separate applications that need to interact seamlessly. My goal will be to describe some of the high-level challenges and solutions found in implementing a Single-Sign-On service.</p>
<h2>Authentication vs Authorization</h2>
<p>I wish these two words didn&#8217;t share the same root because it surely confuses a lot of people. My most frequently-discussed example is <a title="OAuth" href="http://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth</a>. Every time I start talking about implementing a centralized/unified authentication system, someone jumps in and suggests that we use <a title="OAuth" href="http://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth</a>. The challenge is that <a title="OAuth" href="http://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth</a> is an authorization system, not an authentication system.</p>
<p>It&#8217;s tricky, because you might actually be &#8220;authenticating&#8221; yourself to website X using OAuth. What you are really doing is allowing website X to use your information stored by the OAuth provider. It is true that OAuth offers a pseudo-authentication approach via its provider but that is not the main goal of <a title="OAuth" href="http://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth</a>: the Auth in OAuth stands for Authorization, not Authentication.</p>
<p>Here is how we could briefly describe each role:</p>
<ul>
<li><strong>Authentication</strong>: recognizes who you are.</li>
<li><strong>Authorization</strong>: know what you are allowed to do, or what you allow others to do.</li>
</ul>
<p>If you are feel stuck in your design and something seems wrong, ask yourself if you might be confused by the 2 auth words. This article will only focus on <strong>authentication</strong>.</p>
<h2>A Common Scenario</h2>
<p style="text-align: center;"><a href="http://merbist.com/wp-content/uploads/2012/04/SSO-simplescenario.png"><img class="aligncenter  wp-image-1302" title="SSO simple scenario" src="http://merbist.com/wp-content/uploads/2012/04/SSO-simplescenario.png" alt="SSO diagram with 3 top applications connecting to an authorization service." width="611" height="428" /></a></p>
<p>This is probably the most common structure, though I made it slightly more complex by drawing the three main apps in different programming languages. We have three web applications running on different subdomains and sharing account data via a centralized authentication service.</p>
<p><strong>Goals:</strong></p>
<ul>
<li>Keep authentication and basic account data isolated.</li>
<li>Allow users to stay logged in while browsing different apps.</li>
</ul>
<p>Implementing such a system should be easy. That said, if you migrate an existing app to an architecture like that, you will spend 80% of your time decoupling your legacy code from authentication and wondering what data should be centralized and what should be distributed. Unfortunately, I can&#8217;t tell you what to do there since this is very domain specific. Instead, let&#8217;s see how to do the &#8220;easy part.&#8221;</p>
<h2>Centralizing and Isolating Shared Account Data</h2>
<p>At this point, you more than likely have each of your apps talk directly to shared database tables that contain user account data. The first step is to migrate away from doing that. We need a single interface that is the only entry point to create or update shared account data. Some of the data we have in the database might be app specific and therefore should stay within each app, anything that is shared across apps should be moved behind the new interface.</p>
<p>Often your centralized authentication system will store the following information:</p>
<ul>
<li>ID</li>
<li>first name</li>
<li>last name</li>
<li>login/nickname</li>
<li>email</li>
<li>hashed password</li>
<li>salt</li>
<li>creation timestamp</li>
<li>update timestamp</li>
<li>account state (verified, disabled &#8230;)</li>
</ul>
<p>Do not duplicate this data in each app, instead have each app rely on the account ID to query data that is specific to a given account in the app. Technically that means that instead of using SQL joins, you will query your database using the ID as part of the condition.</p>
<p>My suggestion is to do things slowly but surely. Migrate your database schema piece by piece assuring that everything works fine. Once the other pieces will be in place, you can migrate one code API a time until your entire code base is moved over. You might want to change your DB credentials to only have read access, then no access at all.</p>
<h2>Login workflow</h2>
<p>Each of our apps already has a way for users to login. We don&#8217;t want to change the user experience, instead we want to make a transparent modification so the authentication check is done in a centralized way instead of a local way. To do that, the easiest way is to keep your current login forms but instead of POSTing them to your local apps, we&#8217;ll POST them to a centralized authentication API. (SSL is strongly recommended)</p>
<p style="text-align: center;"><a href="http://merbist.com/wp-content/uploads/2012/04/SSO-login.png"><img class="aligncenter  wp-image-1305" title="SSO login workflow" src="http://merbist.com/wp-content/uploads/2012/04/SSO-login.png" alt="diagram showing the login workflow" width="533" height="470" /></a></p>
<p>As shown above, the login form now submits to an endpoint in the authentication application. The form will more than likely include a login or email and a clear text password as well as a hidden callback/redirect url so that the authentication API can redirect the user&#8217;s browser to the original app. For security reasons, you might want to white list the domains you allow your authentication app to redirect to.</p>
<p>Internally, the Authentication app will validate the identifier (email or login) using a hashed version of the clear password against the matching record in the account data. If the verification is successful, a token will be generated containing some user data (for instance: id, first name, last name, email, created date, authentication timestamp). If the verification failed, the token isn&#8217;t generated. Finally the user&#8217;s browser is redirected to the callback/redirect URL provided in the request with the token being passed.</p>
<p>You might want to safely encrypt the data in a way that allows the clients to verify and trust that the token comes from a trusted source. A great solution for that would be to use <a title="RSA encryption" href="http://en.wikipedia.org/wiki/RSA_(algorithm)" target="_blank">RSA encryption</a> with the public key available in all your client apps but the private key only available on the auth server(s). Other strong encryption solutions would also work. For instance, another appropriate approach would be to add a signature to the params sent back. This way the clients could check the authenticity of the params. <a href="http://en.wikipedia.org/wiki/HMAC" target="_blank">HMAC</a> or <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm" target="_blank">DSA</a> signature are great for that but in some cases, you don&#8217;t want people to see the content of the data you send back. That&#8217;s especially true if you are sending back a &#8216;mobile&#8217; token for instance. But that&#8217;s a different story. What&#8217;s important to consider is that we need a way to ensure that the data sent back to the client can&#8217;t be tampered with. You might also make sure you prevent replay attacks.</p>
<p>On the other side, the application receives a GET request with a token param. If the token is empty or can&#8217;t be decrypted, authentication failed. At that point, we need to show the user the login page again and let him/her try again. If on the other hand, the token can be decrypted, the content should be saved in the session so future requests can reuse the data.</p>
<p>We described the authentication workflow, but if a user logins in application X, (s)he won&#8217;t be logged-in in application Y or Z. The trick here, is to set a top level domain cookie that can be seen by all applications running on subdomains. Certainly, this solution only works for apps being on the same domain, but we&#8217;ll see later how to handle apps on different domains.</p>
<p style="text-align: center;"><a href="http://merbist.com/wp-content/uploads/2012/04/SSO-login-cookie.png"><img class="aligncenter  wp-image-1306" title="SSO- login cookie" src="http://merbist.com/wp-content/uploads/2012/04/SSO-login-cookie.png" alt="" width="522" height="379" /></a></p>
<p>The cookie doesn&#8217;t need to contain a lot of data, its value can contain the account id, a timestamp (to know when authentication happened and a trusted signature) and a signature. The signature is critical here since this cookie will allow users to be automatically logged in other sites. I&#8217;d recommend the  <a href="http://en.wikipedia.org/wiki/HMAC" target="_blank">HMAC</a> or <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm" target="_blank">DSA</a> encryptions to generate the signature. The DSA encryption, very much like the RSA encryption is an asymmetrical encryption relying on a public/private key. This approach offers more security than having something based a shared secret like HMAC does. But that&#8217;s really up to you.</p>
<p>Finally, we need to set a filter in your application. This auto-login filter will check the presence of an auth cookie on the top level domain and the absence of local session. If that&#8217;s the case, a session is automatically created using the user id from the cookie value after the cookie integrity is verified. We could also share the session between all our apps, but in most cases, the data stored by each app is very specific and it&#8217;s safer/cleaner to keep the sessions isolated. The integration with an app running on a different service will also be easier if the sessions are isolated.</p>
<p>&nbsp;</p>
<h2>Registration</h2>
<p>For registration, as for login, we can take one of two approaches: point the user&#8217;s browser to the auth API or make S2S (server to server) calls from within our apps to the Authentication app. POSTing a form directly to the API is a great way to reduce duplicated logic and traffic on each client app so I&#8217;ll demonstrate this approach.</p>
<p style="text-align: center;"><a href="http://merbist.com/wp-content/uploads/2012/04/CopyofSSO-register.png"><img class="aligncenter  wp-image-1308" title="SSO register" src="http://merbist.com/wp-content/uploads/2012/04/CopyofSSO-register.png" alt="" width="599" height="529" /></a></p>
<p>As you can see, the approach is the same we used to login. The difference is that instead of returning a token, we just return some params (id, email and potential errors). The redirect/callback url will also obviously be different than for login. You could decide to encrypt the data you send back, but in this scenario, what I would do is set an auth cookie at the .domain.com level when the account is created so the &#8220;client&#8221; application can auto-login the user. The information sent back in the redirect is used to re-display the register form with the error information and the email entered by the user.</p>
<p>At this point, our implementation is almost complete. We can create an account and login using the defined credentials. Users can switch from one app to another without having to re login because we are using a shared signed cookie that can only be created by the authentication app and can be verified by all &#8220;client&#8221; apps. Our code is simple, safe and efficient.</p>
<h2>Updating or deleting an account</h2>
<p>The next thing we will need is to update or delete an account. In this case, this is something that needs to be done between a &#8220;client&#8221; app and the authentication/accounts app. We&#8217;ll make S2S (server to server) calls. To ensure the security of our apps and to offer a nice way to log requests, API tokens/keys will be used by each client to communicate with the authentication/accounts app. The API key can be passed using a <a href="http://en.wikipedia.org/wiki/List_of_HTTP_header_fields" target="_blank">X-header</a> so this concern stays out of the request params and our code can process separately the authentication via X-header and the actual service implementation. S2S services should have a filter verifying and logging the API requests based on the key sent with the request. The rest is straight forward.</p>
<h2>Using different domains</h2>
<p>Until now, we assumed all our apps were on the same top domain. In reality, you will often find yourself with apps on different domains. This means that you can&#8217;t use the shared signed cookie approach anymore. However, there is a simple trick that will allow you to avoid requiring your users to re-login as they switch apps.</p>
<p style="text-align: center;"><a href="http://merbist.com/wp-content/uploads/2012/04/SSO-differentdomains-1.png"><img class="aligncenter  wp-image-1309" title="SSO different domains" src="http://merbist.com/wp-content/uploads/2012/04/SSO-differentdomains-1.png" alt="" width="608" height="433" /></a></p>
<p>&nbsp;</p>
<p>The trick consists, when a local session isn&#8217;t present, of using an iframe in the application using the different domain. The iframe loads a page from the authentication/accounts app which verifies that a valid cookie was set on the main top domain. If that is the case, we can tell the application that the user is already globally logged in and we can tell the iframe host to redirect to an application end point passing an auth token the same way we did during the authentication. The app would then create a session and redirect the user back to where (s)he started. The next requests will see the local session and this process will be ignored.</p>
<p>If the authentication application doesn&#8217;t find a signed cookie, the iframe can display a login form or redirect the iframe host to a login form depending on the required behavior.</p>
<p>Something to keep in mind when using multiple apps and domains is that you need to keep the shared cookies/sessions in sync, meaning that if you log out from an app, you need to also delete the auth cookie to ensure that users are globally logged out. (It also means that you might always want to use an iframe to check the login status and auto-logoff users).</p>
<p>&nbsp;</p>
<h2>Mobile clients</h2>
<p>Another part of implementing a SSO solution is to handle mobile clients. Mobile clients need to be able to register/login and update accounts. However, unlike S2S service clients, mobile clients should only allow calls to modify data on the behalf of a given user. To do that, I recommend providing opaque mobile tokens during the login process. This token can then be sent with each request in a X-header so the service can authenticate the user making the request. Again, SSL is strongly recommended.</p>
<p>In this approach, we don&#8217;t use a cookie and we actually don&#8217;t need a SSO solution, but an unified authentication system.</p>
<p>&nbsp;</p>
<h2>Writing web services</h2>
<p>Our Authentication/Accounts application turns out to be a pure web API app.</p>
<p>We also have 3 sets of APIs:</p>
<ul>
<li>Public APIs: can be accessed from anywhere, no authentication required</li>
<li>S2S APIs: authenticated via API keys and only available to trusted clients</li>
<li>Mobile APIs: authenticated via a mobile token and limited in scope.</li>
</ul>
<p>We don&#8217;t need dynamic HTML views, just simple web service related code. While this is a little bit off topic, I&#8217;d like to take a minute to show you how I personally like writing web service applications.</p>
<p>Something that I care a lot about when I implement web APIs is to validate incoming params. This is an opinionated approach that I picked up while at Sony and that I think should be used every time you implement a web API. As a matter of fact, I wrote a Ruby <a title="Weasel Diesel" href="https://github.com/mattetti/Weasel-Diesel" target="_blank">DSL library (Weasel Diesel)</a> allowing you <a href="https://github.com/mattetti/sinatra-web-api-example/blob/master/api/hello_world.rb" target="_blank">describe a given service</a>, its <a href="https://github.com/mattetti/sinatra-web-api-example/blob/master/api/hello_world.rb#L7" target="_blank">incoming params</a>, and the <a href="https://github.com/mattetti/sinatra-web-api-example/blob/master/api/hello_world.rb#L10-15" target="_blank">expected output</a>. This DSL is hooked into a web backend so you can implement services using a web engine such as <a title="Sinatra" href="http://www.sinatrarb.com/" target="_blank">Sinatra</a> or maybe Rails3. Based on the DSL usage, incoming parameters are be verified before being processed. The other advantage is that you can generate documentation based on the API description as well as automated tests.</p>
<p>You might be familiar with <a href="https://github.com/intridea/grape" target="_blank">Grape</a>, another DSL for web services. Besides the obvious style difference <a href="https://github.com/mattetti/Weasel-Diesel" target="_blank">Weasel Diesel </a>offers the following advantages:</p>
<ul>
<li>input validation/sanitization</li>
<li>service isolation</li>
<li>generated documentation</li>
<li>contract based design</li>
</ul>
<div>Here is a hello world webservice being implemented using Weasel Diesel and Sinatra:</div>
<div id="gist2300131" class="gist">
      <div class="gist-file">
        <div class="gist-data gist-syntax">



  <div class="file-data">
    <table cellpadding="0" cellspacing="0" class="lines highlight">
      <tr>
        <td class="line-numbers">
          <span class="line-number" id="file-hello_world-rb-L1" rel="file-hello_world-rb-L1">1</span>
          <span class="line-number" id="file-hello_world-rb-L2" rel="file-hello_world-rb-L2">2</span>
          <span class="line-number" id="file-hello_world-rb-L3" rel="file-hello_world-rb-L3">3</span>
          <span class="line-number" id="file-hello_world-rb-L4" rel="file-hello_world-rb-L4">4</span>
          <span class="line-number" id="file-hello_world-rb-L5" rel="file-hello_world-rb-L5">5</span>
          <span class="line-number" id="file-hello_world-rb-L6" rel="file-hello_world-rb-L6">6</span>
          <span class="line-number" id="file-hello_world-rb-L7" rel="file-hello_world-rb-L7">7</span>
          <span class="line-number" id="file-hello_world-rb-L8" rel="file-hello_world-rb-L8">8</span>
          <span class="line-number" id="file-hello_world-rb-L9" rel="file-hello_world-rb-L9">9</span>
          <span class="line-number" id="file-hello_world-rb-L10" rel="file-hello_world-rb-L10">10</span>
          <span class="line-number" id="file-hello_world-rb-L11" rel="file-hello_world-rb-L11">11</span>
          <span class="line-number" id="file-hello_world-rb-L12" rel="file-hello_world-rb-L12">12</span>
          <span class="line-number" id="file-hello_world-rb-L13" rel="file-hello_world-rb-L13">13</span>
          <span class="line-number" id="file-hello_world-rb-L14" rel="file-hello_world-rb-L14">14</span>
          <span class="line-number" id="file-hello_world-rb-L15" rel="file-hello_world-rb-L15">15</span>
          <span class="line-number" id="file-hello_world-rb-L16" rel="file-hello_world-rb-L16">16</span>
          <span class="line-number" id="file-hello_world-rb-L17" rel="file-hello_world-rb-L17">17</span>
          <span class="line-number" id="file-hello_world-rb-L18" rel="file-hello_world-rb-L18">18</span>
          <span class="line-number" id="file-hello_world-rb-L19" rel="file-hello_world-rb-L19">19</span>
          <span class="line-number" id="file-hello_world-rb-L20" rel="file-hello_world-rb-L20">20</span>
          <span class="line-number" id="file-hello_world-rb-L21" rel="file-hello_world-rb-L21">21</span>
          <span class="line-number" id="file-hello_world-rb-L22" rel="file-hello_world-rb-L22">22</span>
          <span class="line-number" id="file-hello_world-rb-L23" rel="file-hello_world-rb-L23">23</span>
          <span class="line-number" id="file-hello_world-rb-L24" rel="file-hello_world-rb-L24">24</span>
          <span class="line-number" id="file-hello_world-rb-L25" rel="file-hello_world-rb-L25">25</span>
          <span class="line-number" id="file-hello_world-rb-L26" rel="file-hello_world-rb-L26">26</span>
          <span class="line-number" id="file-hello_world-rb-L27" rel="file-hello_world-rb-L27">27</span>
          <span class="line-number" id="file-hello_world-rb-L28" rel="file-hello_world-rb-L28">28</span>
          <span class="line-number" id="file-hello_world-rb-L29" rel="file-hello_world-rb-L29">29</span>
        </td>
        <td class="line-data">
          <pre class="line-pre"><div class="line" id="file-hello_world-rb-LC1"><span class="n">describe_service</span> <span class="s2">&quot;hello_world&quot;</span> <span class="k">do</span> <span class="o">|</span><span class="n">service</span><span class="o">|</span></div><div class="line" id="file-hello_world-rb-LC2">  <span class="n">service</span><span class="o">.</span><span class="n">formats</span>   <span class="ss">:json</span></div><div class="line" id="file-hello_world-rb-LC3">  <span class="n">service</span><span class="o">.</span><span class="n">http_verb</span> <span class="ss">:get</span></div><div class="line" id="file-hello_world-rb-LC4">  <span class="n">service</span><span class="o">.</span><span class="n">disable_auth</span> <span class="c1"># on by default</span></div><div class="line" id="file-hello_world-rb-LC5">&nbsp;</div><div class="line" id="file-hello_world-rb-LC6">  <span class="c1"># INPUT</span></div><div class="line" id="file-hello_world-rb-LC7">  <span class="n">service</span><span class="o">.</span><span class="n">param</span><span class="o">.</span><span class="n">string</span>  <span class="ss">:name</span><span class="p">,</span> <span class="ss">:default</span> <span class="o">=&gt;</span> <span class="s1">&#39;World&#39;</span></div><div class="line" id="file-hello_world-rb-LC8">&nbsp;</div><div class="line" id="file-hello_world-rb-LC9">  <span class="c1"># OUTPUT</span></div><div class="line" id="file-hello_world-rb-LC10">  <span class="n">service</span><span class="o">.</span><span class="n">response</span> <span class="k">do</span> <span class="o">|</span><span class="n">response</span><span class="o">|</span></div><div class="line" id="file-hello_world-rb-LC11">    <span class="n">response</span><span class="o">.</span><span class="n">object</span> <span class="k">do</span> <span class="o">|</span><span class="n">obj</span><span class="o">|</span></div><div class="line" id="file-hello_world-rb-LC12">        <span class="n">obj</span><span class="o">.</span><span class="n">string</span> <span class="ss">:message</span><span class="p">,</span> <span class="ss">:doc</span> <span class="o">=&gt;</span> <span class="s2">&quot;The greeting message sent back. Defaults to &#39;World&#39;&quot;</span></div><div class="line" id="file-hello_world-rb-LC13">      <span class="n">obj</span><span class="o">.</span><span class="n">datetime</span> <span class="ss">:at</span><span class="p">,</span> <span class="ss">:doc</span> <span class="o">=&gt;</span> <span class="s2">&quot;The timestamp of when the message was dispatched&quot;</span></div><div class="line" id="file-hello_world-rb-LC14">      <span class="k">end</span></div><div class="line" id="file-hello_world-rb-LC15">  <span class="k">end</span></div><div class="line" id="file-hello_world-rb-LC16">&nbsp;</div><div class="line" id="file-hello_world-rb-LC17">  <span class="c1"># DOCUMENTATION</span></div><div class="line" id="file-hello_world-rb-LC18">  <span class="n">service</span><span class="o">.</span><span class="n">documentation</span> <span class="k">do</span> <span class="o">|</span><span class="n">doc</span><span class="o">|</span></div><div class="line" id="file-hello_world-rb-LC19">    <span class="n">doc</span><span class="o">.</span><span class="n">overall</span> <span class="s2">&quot;This service provides a simple hello world implementation example.&quot;</span></div><div class="line" id="file-hello_world-rb-LC20">    <span class="n">doc</span><span class="o">.</span><span class="n">param</span> <span class="ss">:name</span><span class="p">,</span> <span class="s2">&quot;The name of the person to greet.&quot;</span></div><div class="line" id="file-hello_world-rb-LC21">    <span class="n">doc</span><span class="o">.</span><span class="n">example</span> <span class="s2">&quot;&lt;code&gt;curl -I &#39;http://localhost:9292/hello_world?name=Matt&#39;&lt;/code&gt;&quot;</span></div><div class="line" id="file-hello_world-rb-LC22"> <span class="k">end</span></div><div class="line" id="file-hello_world-rb-LC23">&nbsp;</div><div class="line" id="file-hello_world-rb-LC24">  <span class="c1"># ACTION/IMPLEMENTATION</span></div><div class="line" id="file-hello_world-rb-LC25">  <span class="n">service</span><span class="o">.</span><span class="n">implementation</span> <span class="k">do</span></div><div class="line" id="file-hello_world-rb-LC26">    <span class="p">{</span><span class="ss">:message</span> <span class="o">=&gt;</span> <span class="s2">&quot;Hello </span><span class="si">#{</span><span class="n">params</span><span class="o">[</span><span class="ss">:name</span><span class="o">]</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="ss">:at</span> <span class="o">=&gt;</span> <span class="no">Time</span><span class="o">.</span><span class="n">now</span><span class="p">}</span><span class="o">.</span><span class="n">to_json</span></div><div class="line" id="file-hello_world-rb-LC27">  <span class="k">end</span></div><div class="line" id="file-hello_world-rb-LC28">&nbsp;</div><div class="line" id="file-hello_world-rb-LC29"><span class="k">end</span></div></pre>
        </td>
      </tr>
    </table>
  </div>

        </div>

        <div class="gist-meta">
          <a href="https://gist.github.com/mattetti/2300131/raw/4fbbeb1f76fbc667c0e33213ea153236fbdcbdb5/hello_world.rb" style="float:right">view raw</a>
          <a href="https://gist.github.com/mattetti/2300131#file-hello_world-rb" style="float:right; margin-right:10px; color:#666;">hello_world.rb</a>
          <a href="https://gist.github.com/mattetti/2300131">This Gist</a> brought to you by <a href="https://github.com">GitHub</a>.
        </div>
      </div>
</div>

<p>Basis test validating the contract defined in the DSL and the actual output when the service is called:</p>
<div id="gist2300440" class="gist">
      <div class="gist-file">
        <div class="gist-data gist-syntax">



  <div class="file-data">
    <table cellpadding="0" cellspacing="0" class="lines highlight">
      <tr>
        <td class="line-numbers">
          <span class="line-number" id="file-gistfile1-rb-L1" rel="file-gistfile1-rb-L1">1</span>
          <span class="line-number" id="file-gistfile1-rb-L2" rel="file-gistfile1-rb-L2">2</span>
          <span class="line-number" id="file-gistfile1-rb-L3" rel="file-gistfile1-rb-L3">3</span>
          <span class="line-number" id="file-gistfile1-rb-L4" rel="file-gistfile1-rb-L4">4</span>
          <span class="line-number" id="file-gistfile1-rb-L5" rel="file-gistfile1-rb-L5">5</span>
          <span class="line-number" id="file-gistfile1-rb-L6" rel="file-gistfile1-rb-L6">6</span>
          <span class="line-number" id="file-gistfile1-rb-L7" rel="file-gistfile1-rb-L7">7</span>
          <span class="line-number" id="file-gistfile1-rb-L8" rel="file-gistfile1-rb-L8">8</span>
        </td>
        <td class="line-data">
          <pre class="line-pre"><div class="line" id="file-gistfile1-rb-LC1"><span class="k">class</span> <span class="nc">HelloWorldTest</span> <span class="o">&lt;</span> <span class="ss">MiniTest</span><span class="p">:</span><span class="ss">:Unit</span><span class="o">::</span><span class="no">TestCase</span></div><div class="line" id="file-gistfile1-rb-LC2">&nbsp;</div><div class="line" id="file-gistfile1-rb-LC3">  <span class="k">def</span> <span class="nf">test_response</span></div><div class="line" id="file-gistfile1-rb-LC4">    <span class="no">TestApi</span><span class="o">.</span><span class="n">get</span> <span class="s2">&quot;/hello_world&quot;</span><span class="p">,</span> <span class="ss">:name</span> <span class="o">=&gt;</span> <span class="s1">&#39;Matt&#39;</span></div><div class="line" id="file-gistfile1-rb-LC5">    <span class="n">assert_api_response</span></div><div class="line" id="file-gistfile1-rb-LC6">  <span class="k">end</span></div><div class="line" id="file-gistfile1-rb-LC7">&nbsp;</div><div class="line" id="file-gistfile1-rb-LC8"><span class="k">end</span></div></pre>
        </td>
      </tr>
    </table>
  </div>

        </div>

        <div class="gist-meta">
          <a href="https://gist.github.com/mattetti/2300440/raw/fe65b1800ebd3efd2445941976913c8a0e803d8d/gistfile1.rb" style="float:right">view raw</a>
          <a href="https://gist.github.com/mattetti/2300440#file-gistfile1-rb" style="float:right; margin-right:10px; color:#666;">gistfile1.rb</a>
          <a href="https://gist.github.com/mattetti/2300440">This Gist</a> brought to you by <a href="https://github.com">GitHub</a>.
        </div>
      </div>
</div>

<p>Generated documentation:</p>
<p style="text-align: center;"><img class="aligncenter" title="Weasel Diesel generated documentation for a web service" src="https://img.skitch.com/20120404-t1j93b73tef5pmd5idfqqa61td.jpg" alt="" width="597" height="500" /></p>
<p>If the DSL and its features seem appealing to you and you are interested in digging more into it, the easiest way is to fork <a href="https://github.com/mattetti/sinatra-web-api-example/" target="_blank">this demo repo</a> and start writing your own services.</p>
<p>The DSL has been used in production for more than a year, but there certainly are tweaks and small changes that can make the user experience even better. Feel free to fork the <a href="https://github.com/mattetti/Weasel-Diesel" target="_blank">DSL repo</a> and send me Pull Requests.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/04/04/building-and-implementing-a-single-sign-on-solution/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Learning from Rails&#8217; failures</title>
		<link>http://merbist.com/2012/02/29/learning-from-rails-failures/</link>
		<comments>http://merbist.com/2012/02/29/learning-from-rails-failures/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 15:48:08 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Software Design]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[migration]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1251</guid>
		<description><![CDATA[Ruby on Rails undisputedly changed the way web frameworks are designed. Rails became a reference when it comes to leveraging conventions, easy baked in feature set and a rich ecosystem. However, I think that Rails did and still does a lot of things pretty poorly.  By writing this post, I&#8217;m not trying to denigrate Rails, [...]]]></description>
				<content:encoded><![CDATA[<p>Ruby on Rails undisputedly changed the way web frameworks are designed. Rails became a reference when it comes to leveraging conventions, easy baked in feature set and a rich ecosystem. However, I think that Rails did and still does a lot of things pretty poorly.  By writing this post, I&#8217;m not trying to denigrate Rails, there are many other people out there already doing that. My hope is that by listing what I think didn&#8217;t and still doesn&#8217;t go well, we can learn from our mistakes and improve existing solutions or create better new ones.</p>
<p><a href="http://merbist.com/2012/02/29/learning-from-rails-failures/train_fail/" rel="attachment wp-att-1253"><img class="aligncenter size-medium wp-image-1253" title="train fail" src="http://merbist.com/wp-content/uploads/2012/02/train_fail-300x188.jpg" alt="" width="300" height="188" /></a></p>
<h2>Migration/upgrades</h2>
<p>Migrating a Rails App from a version to the other is very much like playing the lottery, you are almost sure you will lose. To be more correct, you know things will break, you just don&#8217;t know what, when and how. The Rails team seems to think that everybody is always running on the cutting edge version and don&#8217;t consider people who prefer to stay a few version behind for stability reasons. What&#8217;s worse is that plugins/gems might or might not compatible with the version you are updating to, but you will only know that by trying yourself and letting others try and report potential issues.</p>
<p>This is for me, by far, the biggest issue with Rails and something that should have been fixed a long time ago. If you&#8217;re using the WordPress blog engine, you know how easy and safe it is to upgrade the engine or the plugins. Granted WordPress isn&#8217;t a web dev framework, but it gives you an idea of what kind of experience we should be striving for.</p>
<p>&nbsp;</p>
<h2>Stability vs playground zone</h2>
<p>New features are cool and they help make the platform more appealing to new comers. They also help shape the future of a framework. But from my perspective, that shouldn&#8217;t come to the cost of stability. Rails 3&#8242;s new asset pipeline is a good example of a half-baked solution shoved in a release at the last minute and creating a nightmare for a lot of us trying to upgrade. I know, I know, you can turn off the asset pipeline and it got better since it was first released. But shouldn&#8217;t that be the other way around? Shouldn&#8217;t fun new ideas risking the stability of an app or making migration harder, be off by default and turned on only by people wanting to experiment? When your framework is young, it&#8217;s normal that you move fast and sometimes break, but once it matures, these things shouldn&#8217;t happen.</p>
<p>&nbsp;</p>
<h2>Public/private/plugin APIs</h2>
<p>This is more of a recommendation than anything else. When you write a framework in a very dynamic language like Ruby, people will &#8220;monkey patch&#8221; your code to inject features. Sometimes it is due to software design challenges, sometimes it&#8217;s because people don&#8217;t know better. However,  by not explicitly specifying what APIs are private (they can change at anytime, don&#8217;t touch), what APIs are public (stable, will be slowly deprecated when they need to be changed) and which ones are for plugin devs only (APIs meant for instrumentation, extension etc..), you are making migration to newer versions much harder. You see, if you have a small, clean public API, then it&#8217;s easy to see what could break, warn developers and avoid migration nightmares. However, you need to start doing that early on in your project, otherwise you will end up like Rails where all code can potentially change anytime.</p>
<p>&nbsp;</p>
<h2>Rails/Merb merge was a mistake</h2>
<p>This is my personal opinion and well, feel free to disagree, nobody will ever be able to know to for sure. Without explaining what happened behind closed doors and the various personal motivations, looking at the end result, I agree with the group of people thinking that the merge didn&#8217;t turn up to be a good thing. For me, Rails 3 isn&#8217;t significantly better than Rails 2 and it took forever to be released. You still can&#8217;t really run a mini Rails stack like promised. I did hear that Strobe (company who was hiring Carl Lerche, Yehuda Katz and contracted Jose Valim) used to have an ActionPack based, mini stack but it was never released and apparently only Rails core members really knew what was going on there. Performance in vanilla Rails 3 are only now getting close to what you had with Rails 2 (and therefore far from the perf you were getting with Merb). Thread-safety is still OFF by default meaning that by default your app uses a giant lock only allowing a process to handle 1 request at a time. For me, the flexibility and performance focus of Merb were mainly lost in the merge with Rails. (Granted, some important things such as ActiveModel, cleaner internals and others have made their way into Rails 3)</p>
<p>But what&#8217;s worse than everything listed so far is that the lack of competition and the internal rewrites made Rails lose its headstart.  Rails is very much HTML/view focused, its primarily strength is to make server side views trivial and it does an amazing job at that. But let&#8217;s be honest, that&#8217;s not the future for web dev. The future is more and more logic pushed to run on the client side (in JS) and the server side being used as an API serving data for the view layer. I&#8217;m sorry but adding support for CoffeeScript doesn&#8217;t really do much to making Rails evolve ahead of what it currently is. Don&#8217;t get me wrong, I&#8217;m a big fan of CoffeeScript, that said I still find that Rails is far from being optimized to developer web APIs in Rails. You can certainly do it, but you are basically using a tool that wasn&#8217;t designed to write APIs and you pay the overhead for that. If there is one thing I wish Rails will get better at is to make writing pure web APIs better (thankfully there is Sinatra). But at the end of the day, I think that two projects with different philosophies and different approaches are really hard to merge, especially in the open source world. I wouldn&#8217;t go as far as saying like others that Rails lost its sexiness to node.js because of the wasted time, but I do think that things would have been better for all if that didn&#8217;t happen. However, I also have to admit that I&#8217;m not sure how much of a big deal that is. I prefer to leave the past behind, learn from my own mistake and move on.</p>
<p>&nbsp;</p>
<h2>Technical debts</h2>
<p>Here I&#8217;d like to stop to give a huge props to Aaron &#8220;<a href="http://twitter.com/tenderlove" target="_blank">@tenderlove</a>&#8221; Patterson, the man who&#8217;s actively working to reduce the <a href="http://en.wikipedia.org/wiki/Technical_debt" target="_blank">technical debts</a> in the Rails code base. This is a really hard job and definitely not a very glamorous one. He&#8217;s been working on various parts of Rails including its router and its ORM (ActiveRecord). Technical debts are unfortunately normal in most project, but sometimes they are overwhelming to the point that nobody dares touching the code base to clean it up. This is a hard problem, especially when projects move fast like Rails did. But looking back, I think that you want to start tackling technical debts on the side as you move on so you avoid getting to the point that you need a hero to come up and clean the piled errors made in the past. But don&#8217;t pause your entire project to clean things up otherwise you will lose market, momentum and excitement. I feel that this is also very much true for any legacy project you might pick up as a developer.</p>
<p>&nbsp;</p>
<h2>Keep the cost of entry level low</h2>
<p>Getting started with Rails used to be easier. This can obviously argued since it&#8217;s very subjective, but from my perspective I think we forgot where we come from and we involuntary expect new comers to come with unrealistic knowledge. Sure, Rails does much more than it used to do, but it&#8217;s also much harder to get started. I&#8217;m not going to argue how harder  it is now or why we got there. Let&#8217;s just keep in mind that it is a critical thing that should always be re-evaluated. Sure, it&#8217;s harder when you have an open source project, but it&#8217;s also up to the leadership to show that they care and to encourage and mentor volunteers to  focus on this important part of a project.</p>
<p>&nbsp;</p>
<h2>Documentation</h2>
<p>Rails documentation isn&#8217;t bad, but it&#8217;s far from being great. Documentation certainly isn&#8217;t one of the Ruby&#8217;s community strength, especially compared with the Python community, but what saddens me is to see the state of <a href="http://guides.rubyonrails.org/" target="_blank">the official documentation</a> which, should, in theory be the reference. Note that the Rails guides are usually well written and provide value, but they too often seem too light and not useful when you try to do something not totally basic (for instance use an ActiveModel compliant object). That&#8217;s probably why most people don&#8217;t refer to them or don&#8217;t spend too much time there. I&#8217;m not trying to blame anyone there. I think that the people who contributed theses guides did an amazing job, but if you want to build a strong and easy to access community, great documentation is key. Look at the <a title="Django docs" href="https://docs.djangoproject.com/en/1.3/" target="_blank">Django</a> documentation as a good example. That said, I also need to acknowledge the amazing job done by many community members such as <a href="http://railscasts.com/" target="_blank">Ryan Bates</a> and <a href="http://ruby.railstutorial.org/" target="_blank">Michael Hartl</a> consistently providing high value external documentation via the <a href="http://railscasts.com/" target="_blank">railscasts</a> and the intro to <a href="http://ruby.railstutorial.org/" target="_blank">Rails tutorial</a> available for free.</p>
<p>&nbsp;</p>
<p>In conclusion, I think that there is a lot to learn from Rails, lots of great things as well as lots of things you would want to avoid. We can certainly argue on Hacker News or via comments about whether or not I&#8217;m right about Rails failures, my point will still be that the mentioned issues should be avoided in any projects, Rails here is just an example. Many of these issues are currently being addressed by the Rails team but wouldn&#8217;t it be great if new projects learn from older ones and avoid making the same mistakes? So what other mistakes do you think I forgot to mention and that one should be very careful of avoiding?</p>
<p>&nbsp;</p>
<h3>Updates:</h3>
<ol>
<li>Rails 4 had an API centric app generator but it <a href="https://github.com/rails/rails/commit/6db930cb5bbff9ad824590b5844e04768de240b1">was quickly reverted</a> and will live as gem until it&#8217;s mature enough.</li>
<li>Rails 4 improved the ActiveModel API to be simpler to get started with. See <a href="http://blog.plataformatec.com.br/2012/03/barebone-models-to-use-with-actionpack-in-rails-4-0/">this blog</a> post for more info.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/02/29/learning-from-rails-failures/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Quick dive into Ruby ORM object initialization</title>
		<link>http://merbist.com/2012/02/23/quick-dive-into-ruby-orm-object-initialization/</link>
		<comments>http://merbist.com/2012/02/23/quick-dive-into-ruby-orm-object-initialization/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 17:46:49 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[Software Design]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[profiling]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1225</guid>
		<description><![CDATA[Yesterday I did some quick digging into how ORM objects are initialized and the performance cost associated to that. In other words, I wanted to see what&#8217;s going on when you initialize an ActiveRecord object. Before I show you the benchmark numbers and you jump to conclusions, it&#8217;s important to realize that in the grand [...]]]></description>
				<content:encoded><![CDATA[<p>Yesterday I did some quick digging into how ORM objects are initialized and the performance cost associated to that. In other words, I wanted to see what&#8217;s going on when you initialize an ActiveRecord object.</p>
<p>Before I show you the benchmark numbers and you jump to conclusions, it&#8217;s important to realize that in the grand scheme of things, the performance cost we are talking is small enough that it is certainly not the main reason why your application is slow. Spoiler alert: ActiveRecord is slow but the cost of initialization isn&#8217;t by far the worse part of ActiveRecord. Also, even though this article doesn&#8217;t make activeRecord look good, and I&#8217;m not trying to diss it. It&#8217;s a decent ORM that does a great job in most cases.</p>
<p>Let&#8217;s get started by the benchmarks number to give us an idea of the damage (using Ruby 1.9.3 p125):</p>
<p>&nbsp;</p>
<pre>                                                             | Class | Hash  | AR 3.2.1 | AR no protection | Datamapper | Sequel |
--------------------------------------------------------------------------------------------------------------------------------------
.new() x100000                                               | 0.037 | 0.049 | 1.557    | 1.536            | 0.027      | 0.209  |
.new({:id=&gt;1, :title=&gt;"Foo", :text=&gt;"Bar"}) x100000          | 0.327 | 0.038 | 6.784    | 5.972            | 4.226      | 1.986  |</pre>
<p>&nbsp;</p>
<p>You can see that I am comparing the allocation of a Class instance, a Hash and some ORM models. The benchmark suite tests the allocation of an empty object and one with passed attributes. The benchmark in question is available <a title="object initialization benchmark" href="https://github.com/mattetti/benchmarks/blob/master/init_objects.rb" target="_blank">here</a>.</p>
<p>As you can see there seems to be a huge performance difference between allocating a basic class and an ORM class. Instantiating an ActiveRecord class is 20x slower than instantiating a normal class, while ActiveRecord offers some extra features, why is it so much slower, especially at initialization time?</p>
<p>The best way to figure it out is to profile the initialization. For that, I used <a href="https://github.com/tmm1/perftools.rb" target="_blank">perftools.rb</a> and I generated a graph of the call stack.</p>
<p>Here is what Ruby does (and spends its time) when you initialize a new Model instance (click to download the PDF version):</p>
<p>&nbsp;</p>
<p><a href="http://github.com/mattetti/benchmarks/blob/master/ar_init_profile.pdf?raw=true"><img class="aligncenter size-full wp-image-1329" title="AR model instantiation diagram by Matt Aimonetti" src="http://merbist.com/wp-content/uploads/2012/02/AR-model-instantation-by-Matt-Aimonetti.jpg" alt="Profiler diagram of AR model instantiation by Matt Aimonetti" width="600" height="395" /></a></p>
<p>&nbsp;</p>
<p>This is quite a scary graph but it shows nicely the features you are getting and their cost associated. For instance, the option of having the before and after initialization callback cost you 14% of your CPU time per instantiation, even though you probably almost never use these callbacks. I&#8217;m reading that by interpreting the node called ActiveSupport::Callback#run_callbacks, 3rd level from the top. So 14.1% of the CPU time is spent trying to run callbacks. As a quick note, note that 90.1% of the CPU time is spent initializing objects, the rest is spent in the loop and in the garbage collection (because the profiler runs many loops). You can then follow the code and see how the code works, creating a dynamic class callback method on the fly (the one with the long name) and then recreating the name of this callback to call it each time the object is allocated. It sounds like that&#8217;s a good place for some micro optimizations which could yield up to 14% performance increase in some cases.</p>
<p>Another major part of the CPU time is spent in ActiveModel&#8217;s sanitization. This is the piece of code that allows you to block some model attributes to be mass assigned. This is useful when you don&#8217;t want to sanitize your incoming params but want to create or update a model instance by using all the passed user params. To avoid malicious users to modify some specific params that might be in your model but not in your form, you can protect these attributes. A good example would be an admin flag on a User object. That said, if you manually initialize an instance, you don&#8217;t need this extra protection, that&#8217;s why in the benchmark above, I tested and without the protection. As you can see, it makes quite a big difference. The profiler graph of the same initialization without the mass assignment protection logically ends up looking quite different:</p>
<p>&nbsp;</p>
<p><a href="https://github.com/mattetti/benchmarks/blob/master/ar_init_no_protection.pdf?raw=true"><br />
</a><a href="https://github.com/mattetti/benchmarks/blob/master/ar_init_no_protection.pdf?raw=true"><img class="aligncenter size-full wp-image-1330" title="AR model instantiation without mass assignment - by Matt Aimonetti" src="http://merbist.com/wp-content/uploads/2012/02/AR-model-instantiation-without-mass-assignment-by-Matt-Aimonetti.jpg" alt="Matt Aimonetti shows the stack trace generated by the instantiation of an Active Record model" width="599" height="406" /></a></p>
<p>&nbsp;</p>
<p><strong>Update:</strong> My colleague <a title="Glenn's Twitter" href="https://twitter.com/#!/glv" target="_blank">Glenn Vanderburg</a> pointed out that some people might assuming that the shown code path is called for each record loaded from the database. This isn&#8217;t correct, the graph represents instances allocated by calling #new. See the addition at the bottom of the post for more details about what&#8217;s going on when you fetch data from the DB.</p>
<p>I then decided to look at the graphs for the two other popular Ruby ORMs:</p>
<p><a title="Datamapper" href="http://datamapper.org/" target="_blank">Datamapper</a></p>
<p><a href="https://github.com/mattetti/benchmarks/blob/master/dm_init_profile.pdf?raw=true"><img class="aligncenter" title="DataMapper object init Graph" src="http://img.skitch.com/20120223-txs4wa7b5rdpg45aj6354xg1wt.jpg" alt="" width="524" height="705" /></a></p>
<p>&nbsp;</p>
<p>and <a title="Sequel ORM" href="http://sequel.rubyforge.org/" target="_blank">Sequel</a></p>
<p style="text-align: center;"><a href="https://github.com/mattetti/benchmarks/blob/master/sequel_init_profile.pdf?raw=true"><img class="aligncenter" title="Sequel graph" src="http://img.skitch.com/20120223-p2jx6ypk35ucsgtx7p1tcabpes.jpg" alt="" width="531" height="656" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>While I didn&#8217;t give you much insight in ORM code, I hope that this post will motivate you to sometimes take a look under the cover and profile your code to see what&#8217;s going on and why it might be slow. <strong>Never assume, always measure</strong>. Tools such as perftools are a great way to get a visual feedback and get a better understanding of how the Ruby interpreter is handling your code.</p>
<h2>UPDATE:</h2>
<p>I heard you liked graphs so I added some more, here is what&#8217;s going on when you do Model.first:</p>
<p><a href="https://github.com/mattetti/benchmarks/blob/master/ar_first_profile.pdf?raw=true"><img class="aligncenter" title="ActiveRecord first" src="http://img.skitch.com/20120224-f23s8xctghi8mj6ax3cdw9aq25.jpg" alt="" width="539" height="884" /></a></p>
<p>&nbsp;</p>
<p>Model.all</p>
<p><a href="https://github.com/mattetti/benchmarks/blob/master/ar_all_profile.pdf?raw=true"><img class="aligncenter" title="Model.all profile graph" src="https://img.skitch.com/20120224-q29q4n7bj3i96erk1enxdqxb5e.jpg" alt="" width="834" height="884" /></a></p>
<p>&nbsp;</p>
<p>And finally this is the code graph for a call to Model.instantiate which is called after a record was retrieved from the database to convert into an Object. (You can see the #instantiate call referenced in the graph above).</p>
<p>&nbsp;</p>
<p><a href="https://github.com/mattetti/benchmarks/blob/master/ar_instantiate_profile.pdf?raw=true"><img class="aligncenter" title="Model.instantiate" src="http://img.skitch.com/20120224-8scmun9n1c9ufdnxa8rq2961bq.jpg" alt="" width="787" height="666" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2012/02/23/quick-dive-into-ruby-orm-object-initialization/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Books to read in 2012 &#8211; recommended to me by Twitter</title>
		<link>http://merbist.com/2011/12/30/books-to-read-in-2012-recommended-to-me-by-twitter/</link>
		<comments>http://merbist.com/2011/12/30/books-to-read-in-2012-recommended-to-me-by-twitter/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 23:28:13 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1215</guid>
		<description><![CDATA[Today, I asked on Twitter what non-technical books I should read in 2012. I was nicely surprised to see so many of my followers send recommendations. Here is a list of 25 books that like-minded people suggested I read. Hopefully you will find a book or two to read too. Feel free to send more recommendations [...]]]></description>
				<content:encoded><![CDATA[<p>Today, I asked on Twitter what non-technical books I should read in 2012.</p>
<p>I was nicely surprised to see so many of my followers send recommendations. Here is a list of 25 books that like-minded people suggested I read. Hopefully you will find a book or two to read too. Feel free to send more recommendations via the comments.</p>
<p>&nbsp;</p>
<table>
<tbody>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307593312/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307593312"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307593312&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307593312" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307593312/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307593312" target="_blank">1Q84 by Haruki Murakami</a></td>
<td>suggested by <a title="@mrb_bk" href="https://twitter.com/#!/mrb_bk" target="_blank">@mrb_bk</a> and <a href="https://twitter.com/#!/chadfowler" target="_blank">@chadfowler</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0385240899/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0385240899"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0385240899&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0385240899" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0385240899/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0385240899">The Floating Opera and The End of the Road by John Barth</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0385240899" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@chadfowler" href="https://twitter.com/#!/chadfowler" target="_blank">@chadfowler</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0613663616/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0613663616"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0613663616&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0613663616" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0613663616/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0613663616">Into Thin Air by Jon Krakauer</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0613663616" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@bradly" href="https://twitter.com/#!/bradly" target="_blank">@bradly</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0375714367/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375714367"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0375714367&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375714367" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0375714367/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375714367">Cutting for Stone by Abraham Verghese</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375714367" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@bradly" href="https://twitter.com/#!/bradly" target="_blank">@bradly</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0452011876/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0452011876"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0452011876&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0452011876" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0452011876/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0452011876">Atlas Shrugged by Ayn Rand</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0452011876" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@bradly" href="https://twitter.com/#!/bradly" target="_blank">@bradly</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307474720/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307474720"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307474720&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307474720" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307474720/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307474720">Cien años de soledad by Gabriel Garcia Marquez</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307474720" alt="" width="1" height="1" border="0" /> (es)</td>
<td>suggested by <a title="@romanandreg" href="https://twitter.com/#!/romanandreg" target="_blank">@romanandreg</a> &amp; <a href="https://twitter.com/#!/jrfernandez" target="_blank">@jrfernandez</a> &amp; <a href="https://twitter.com/#!/edgarschmidt" data-user-id="15151306">@edgarschmidt</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0060883286/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060883286"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0060883286&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0060883286" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0060883286/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0060883286">One Hundred Years of Solitude by Gabriel García Marquez</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0060883286" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@romanandreg" href="https://twitter.com/#!/romanandreg" target="_blank">@romanandreg</a> &amp; <a href="https://twitter.com/#!/jrfernandez" target="_blank">@jrfernandez</a> &amp; <a href="https://twitter.com/#!/edgarschmidt" data-user-id="15151306">@edgarschmidt</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0553348981/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0553348981"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0553348981&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0553348981" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0553348981/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0553348981">Jitterbug Perfume by Tom Robbins</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0553348981" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@supaspoida" href="https://twitter.com/#!/supaspoida" target="_blank">@supaspoida</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0062041266/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0062041266"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0062041266&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0062041266" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0062041266/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0062041266">The Sisters Brothers by Patrick deWitt</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0062041266" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@dennismajor1" href="https://twitter.com/#!/dennismajor1" target="_blank">@dennismajor1</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0312278497/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0312278497"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0312278497&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0312278497" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0312278497/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0312278497">The Glass Bead Game by Hermann Hesse</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0312278497" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@dj2sincl" href="https://twitter.com/#!/dj2sincl" target="_blank">@dj2sincl</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0679775439/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0679775439"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0679775439&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0679775439" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0679775439/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0679775439">The Wind-Up Bird Chronicle by Haruki Murakami</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0679775439" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@chadfowler" href="https://twitter.com/#!/chadfowler" target="_blank">@chadfowler</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0983873100/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0983873100"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0983873100&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0983873100" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0983873100/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0983873100">Mindfire by Scott Berkun</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0983873100" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@lucasdicioccio" href="https://twitter.com/#!/lucasdicioccio" target="_blank">@lucasdicioccio</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/2226052577/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=2226052577"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=2226052577&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=2226052577" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/2226052577/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=2226052577">Les Fourmis by Bernard Werber</a> (fr)</td>
<td>suggested by <a title="@twitty_tim" href="https://twitter.com/#!/twitty_tim" target="_blank">@twitty_tim</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0375725849/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375725849"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0375725849&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375725849" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0375725849/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0375725849">Perfume: The Story of a Murderer by Patrick Suskind</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0375725849" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@twitty_tim" href="https://twitter.com/#!/twitty_tim" target="_blank">@twitty_tim</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/1613820259/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1613820259"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=1613820259&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1613820259" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/1613820259/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1613820259">Les Miserables by Victor Hugo</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1613820259" alt="" width="1" height="1" border="0" /> (en, free ebook)</td>
<td>suggested by <a title="@tutec" href="https://twitter.com/#!/tutec" target="_blank">@tutec</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307292134/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307292134"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307292134&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307292134" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307292134/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307292134">Song Of Ice and Fire by George R.R. Martin</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307292134" alt="" width="1" height="1" border="0" /> (Game of Thrones saga)</td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a> &amp; <a href="http://twitter.com/jarin" target="_blank">@jarin</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0765329468/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0765329468"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0765329468&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0765329468" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0765329468/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0765329468">Clockwork Century by Cherie Priest</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0765329468" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/1590201183/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590201183"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=1590201183&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1590201183" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/1590201183/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590201183">The Darkness that Comes Before by R. Scott Bakker</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1590201183" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/B003GAN3VE/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B003GAN3VE"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=B003GAN3VE&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B003GAN3VE" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/B003GAN3VE/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B003GAN3VE">Drood by Dan Simmons</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B003GAN3VE" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@eeppa" href="https://twitter.com/#!/eeppa" target="_blank">@eeppa</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0316068225/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0316068225"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0316068225&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0316068225" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0316068225/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0316068225">This Is Water by David Foster Wallace</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0316068225" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@atduskgreg" href="https://twitter.com/#!/atduskgreg" target="_blank">@atduskgreg</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/B005DI71QA/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B005DI71QA"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=B005DI71QA&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B005DI71QA" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/B005DI71QA/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B005DI71QA">Anathem by Neal Stephenson</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=B005DI71QA" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@jarin" href="https://twitter.com/#!/jarin" target="_blank">@jarin</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0812550706/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0812550706"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0812550706&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0812550706" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0812550706/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0812550706">Ender&#8217;s Game by Orson Scott Card</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0812550706" alt="" width="1" height="1" border="0" /> (entire saga)</td>
<td>suggested by <a title="@jarin" href="https://twitter.com/#!/jarin" target="_blank">@jarin</a> &amp; <a href="https://twitter.com/#!/edgarschmidt" target="_blank" data-user-id="15151306">@edgarschmidt</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/344245302X/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=344245302X"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=344245302X&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=344245302X" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/344245302X/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=344245302X">Snow Crash by Neal Stephenson</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=344245302X" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@jarin" href="https://twitter.com/#!/jarin" target="_blank">@jarin</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/1422171647/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1422171647"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=1422171647&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1422171647" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/1422171647/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1422171647">Fixing the Game by Roger L. Martin</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=1422171647" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@jarkko" href="https://twitter.com/#!/jarkko" target="_blank">@jarkko</a></td>
</tr>
<tr>
<td><a href="http://www.amazon.com/gp/product/0307387895/ref=as_li_ss_il?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307387895"><img src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&amp;Format=_SL110_&amp;ASIN=0307387895&amp;MarketPlace=US&amp;ID=AsinImage&amp;WS=1&amp;tag=merbist-20&amp;ServiceVersion=20070822" alt="" border="0" /></a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307387895" alt="" width="1" height="1" border="0" /></td>
<td><a href="http://www.amazon.com/gp/product/0307387895/ref=as_li_ss_tl?ie=UTF8&amp;tag=merbist-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0307387895">The Road by Cormac McCarthy</a><img style="border: none !important; margin: 0px !important;" src="http://www.assoc-amazon.com/e/ir?t=merbist-20&amp;l=as2&amp;o=1&amp;a=0307387895" alt="" width="1" height="1" border="0" /></td>
<td>suggested by <a title="@mrreynolds" href="https://twitter.com/#!/mrreynolds" target="_blank">@mrreynolds</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/12/30/books-to-read-in-2012-recommended-to-me-by-twitter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Developing a Curriculum</title>
		<link>http://merbist.com/2011/12/21/developing-a-curriculum/</link>
		<comments>http://merbist.com/2011/12/21/developing-a-curriculum/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 14:57:27 +0000</pubDate>
		<dc:creator>Matt Aimonetti</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[education]]></category>

		<guid isPermaLink="false">http://merbist.com/?p=1207</guid>
		<description><![CDATA[Recently I asked a friend of mine to give me pointers on how to develop a curriculum (he used to teach an education PHD program), after discussing his response on Twitter, people asked me to put it somewhere, so here it is: Process to develop a curriculum: Purpose. Know why you&#8217;re doing what you&#8217;re doing. [...]]]></description>
				<content:encoded><![CDATA[<p>Recently I asked a friend of mine to give me pointers on how to develop a curriculum (he used to teach an education PHD program), after discussing his response on Twitter, people asked me to put it somewhere, so here it is:</p>
<p>Process to develop a curriculum:</p>
<p><span style="text-decoration: underline;"><strong>Purpose</strong></span>. <em>Know why you&#8217;re doing what you&#8217;re doing.</em></p>
<ul>
<li>You know how to do this.</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Product</strong></span>. <em>Start with the end in mind.</em></p>
<ul>
<li>What does the student look like when they walk out the door at the end of the training.</li>
<li>Usually, we break these down into <strong>Knowledge</strong>, <strong>Skills</strong>, or <strong>Attitudes</strong>.</li>
<li>Sometimes it&#8217;s helpful to see a photograph or drawing of a someone who finished the program and just talk about what they can do that makes them successful.</li>
<li>This &#8220;product&#8221; should be connected and help you accomplish your mission</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Practices</strong></span>. <em>Then ask yourself, &#8220;How do people become like this?&#8221;</em></p>
<ul>
<li>If you can break down your Product into 3-5 bit-sized chunks, then see how people learn each one of those skills, gain each one of those knowledge points, and how to they gain the attitudes you want them to have.</li>
<li>This one is much easier the more experience you have in seeing people develop the &#8220;Product.&#8221;</li>
<li>This is also easier to determine when you understand <a href="http://en.wikipedia.org/wiki/Learning_theory_(education)" target="_blank">Learning Theory</a>.</li>
<li>The results from this section will result in a list of:</li>
<ul>
<li>       Activities or experiences</li>
<li>       Resources. What books, website, teachers, software, etc. will help them learn more effectively and efficiently</li>
<li>       Assessments. How you would know if the activity was helpful?</li>
</ul>
</ul>
<p><span style="text-decoration: underline;"><strong>Plans</strong></span>. <em>Make your plans based on the practices you&#8217;ve determined you&#8217;ve needed.</em></p>
<p>&nbsp;</p>
<p>On a related topic, Chad Fowler posted an interesting <a href="http://chadfowler.com/2011/12/21/re-thinking-software-development-education" target="_blank">blog post about what LivingSocial is doing to change the software development education</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://merbist.com/2011/12/21/developing-a-curriculum/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
