<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <link>http://persumi.com/u/fredwu/tech/e/blog/t/ruby</link>
    <generator>Persumi - Level up your writing and blogging with AI</generator>
    <category>Blog</category>
    <category>Tech</category>
    <pubDate>Mon, 25 May 2026 15:08:52 +0000</pubDate>
    <description/>
    <title>Blog (ruby) - Fred Wu&apos;s Tech</title>
    <atom:link type="application/rss+xml" rel="self" href="http://persumi.com/u/fredwu/tech/e/blog/t/ruby/feed/rss"></atom:link>
    <item>
      <pubDate>Sat, 14 Sep 2019 08:05:09 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/conference-talk-adaptable-human-rubyconf-china-2019</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/conference-talk-adaptable-human-rubyconf-china-2019</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
Seven years ago in 2012 I spoke at &lt;a href=&quot;http://2012.rubyconfchina.org/&quot;&gt;RubyConf China 2012&lt;/a&gt;. It was a technical talk on how to become a better developer, if you’re interested you can check out &lt;a href=&quot;https://www.youtube.com/watch?v=DeBsmdDmB9A&quot;&gt;the video recording&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Seven years later in August 2019, I headed back to Shanghai again to speak at this year’s &lt;a href=&quot;http://rubyconfchina.org/&quot;&gt;RubyConf China&lt;/a&gt;. And this time around, it was a non-technical talk on how to develop one’s career. Check out the video recording below:&lt;/p&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;video: https://www.youtube.com/watch?v=MBczdO7RgNo&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;
And, here are &lt;a href=&quot;https://photos.app.goo.gl/VavY5PgBGezZaqMr6&quot;&gt;some photos&lt;/a&gt; of yours truly. :)&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/5WAF3kG7lcjoHBJyW1cZXjyfQ50CtiAFtE9jDZQNVxqv3Vx8poJ2pkJ0gN-iRy8Xll0WmQLbnNdu8ackq5QIyNi4U6pP8YLSOjeD99azl4Id_nQZ6-ZDIEF5yg7NWdoKinEKZP9umzdhPsDP4E9eilxOctHWG9BZ5oWS0NcYoGyWCx6wgv0zV2VQxX_ND49YkAz7VLe0RvoGkqVBBsGiqaNXMePFVp3yiS9QkVkp866duSJk1o8kBd3eUgP54znSoFG3G7zKgPmsyRcPkJiR4TjFQX_EcLY4EhGPPhJBy371E_h3jdA88Y_W2Y-qQLqmrTtRzx_c6zVJonVLSOZRPg3H4ZZU3ZpwbeWq09wzv6XgI_obzvRX9uWThj43TXbJGbAym_pwagzurao08D5i0-EfM0P2StjJ72Fl2pissiMsxlKm5m3j5SBmKiO_mp5hXIVuOe0W81sTIv7DB4yKGC-_meQgrKZDV2jFObdAIJ0pLR8TbsLYra2ljl9JBKi_1m0Q2kNhN3EX9eqxV4-i1yabOkl132DzVHg81MXBHt58oi2byfqmtv5Nzibf2UdGWku7up_71N4jl-hP9ZiRE5vxjvpx1FMuX_g9JSXAjQpbFIOxoYNG98TuP6i1zUwy-ItUfdK-KpTgd6tvtR0eU7tVnbdfGF4uQgpgTWMYxsRHT98xflCS0twqnoDxMH1UhTLMbjyVbBFlTihtl5dvMRWiwB8v6if74HA5b3jcmJTLjN0CWQ=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/MqS8YsePpXrxE1x6ZdUTexS_YkFXV3ivU5deks73l-hdXjrNsg3qu6dU8ykdjnfrIGI5o9aScbHNDe6soOF3tp8-k7ho340cj0kU9tbQSxr7A45WdF0Vc1DjiGlTOeTq8m0pDdCW_FsE5hejK0Ojv9Gmmv6AE9jfv-9ny1xtD3aYc-TE26x8RMZImPWVcASX-Q4j7vxwL7QkCXGSJqxk__fsJBST4_DAm9SAJckJURRsSLrxMELejTIgklg89Ku57n8ErpPyQLZeII1qtMzP71D_IZpYw4IbkXnRdEkmgtAoKlnkbhfm9dTeNaLA3cbbQH7MdhyjCA1BHV4Pb-GS0WmlJz0UznC97240N7NYwc9eydZIRl7XIWSIpQa422MjYexp9HaXE_0kigj4im6r1F1yyXUa4nZZl27IX4dSDNUuDeswXOHjlhZ6LwPzCU38ybsP3N-D5DmAwBfxZ4HceiC4TIw0h-TASjdO9GiFT5L0kQWdlYCyodG_PTiRcH66C8eKMbFpNRo4kHyC9xv9cpCitpuo1zpK71iG0qGted8RqKumc1IUmOVmixLUGMBn4N8fLzH9bHWI5-QgIFcAwjX-KpBF66bOQ8KFu80AfYvrjj_-uuLiJMAslQrdTH4Emke_GTiB33TqO-Sg_PlVtlxIY02apmukpgvA6g_zr8UBSNCeZBEGXFR55JuIXt6sQJyuqKJf5kwWiUNTB3dGK_VUxz8zQQ6OvZO2hAIkOzYnh1TwSA=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/GwcPQdQwUj4EZ5phpPq7oQSrsxz5xMPCNHzrcHx9NDTGsVvFJigPPgH_9Nomo3dfSnMjgZvVNWiOUA6schD2N_yiEYU9jVBDitTQjop3OLCTjOGgU-9Q_JFP6YWwW4qvcKr4E_WkUR2ncZXicpMlVTF9vDHteCUK03-h-0SQQklQRSyP4CZsm7CJUqPAieV5TlsGspbIaZ0HncXp1IHCcsA9hcsZszDLwI5XclX2ZYHWpccbYc8EngNP61wDDL6Jj8USkxlPBN_J2fjkpexA_RU16GN_PzP_mHcWOrX20Qo_U1ftx1O2BR47C_EMk_7eQBYFeyISV6Njvc7_rmoTFme01SK8rvpJhpaY2FjhmwaiwnTG_QxaPOezLq20N4LbNGJjJAspkjHoGmB_VRl2WzGTGv-sizvRHltpcZBhLFI2NaKBkjxbdCbGbmW-fwa192jx5SW_rqDxMRuGf0F9GDAWPNzI46-gfLIeMUbKZiq6D5FRqU1LBnhyK0BKX6QxtWiqY_cIHk1BThjMUuMCAUBvVJKaRz3-k7de-JH0YV8Wg6d-yHMU0nclpShtnHKKH-ZABLxF8S_6GC6lsGyObm8BwxA-eZesp4I3_pM2-GSn5YYbYxp5cf5mS34TcrnHbWBORYENVddDX9RVZBf6J9Hn42rO0z8lKEK4O3K7xkLXh3ntmfeJikM6RB-xXx-VZYMdLx_IZkjKP1NhnpSWaJhrBiXeAk9pdNRzbzz7JBxrAOFTRA=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/o629eWYguKoS9bjBAWpeQ05j2I_ulKDUDx7mBoigOaQAumd7ALULmPJ0rMDmkeSJOjm17lj4s_HPM2Xdz5aS8IqCDqDPHfIBOaVD2xw-5TwWMN3WrKMWC3sPArh2R5HHmw8XApO3SpgNCoLPJirwg-WsJaVzqdWKoJmLZIfPMf-aT-z0jJFTAUyLJzmxxJ_GNUtiX0BBuKLaS6ae7J-kWGLeeJ3Wodli7jWzOwdTQi0inem5ro9inHfS-HcOsOUn2bofObday9QGVnDmG4h5cuc7jwvUUUNtx1tw__HHvaPs5wF_lPSitwhBGmUlvR_DWe-o_ZIphXPtUE3N5rA_GitUxI_BAYpMG_AYq4GYUXwoyTotrtZdqn4cD1Vc9DE3bWfGeIEWV4Rk3XkMSFfLCGIta6LWoPYYtU0onJPNERgTgog4blAmoLPNotUFH_JRLji3VOAl3dwksL4FPVHH6huqDyYfcBKGZ8714_-8qvOZjs5D-vuTWMjZ5ggxeHceORfHROZK8uBGAF0Dfwd8ySZi1ZQMkU0fTjGpUu6Vw0HX91xpoyTuDimDkdpfHD5KSIS4EaWsvfsDh1bScFi3wb0fZNTDbNeXTM2gbLE5kzcXkLC_bB27UggVXNJHcgyjEvKrO6WohKVUyk0S3TMhuQzebBNA-cKAwjg6uNjAc7iw9dunJy9o685Pn4i9C0Th1V6hT-ECp__QkDLnP4EMPsQmhtCVdKad8NFTJljl82Wnm71vyg=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/0-9oruOGEu8TI9ziGr7Wjyu3p6i_yct3-cpoUAaUEcRXcVOD0g4M0Wi23eGsYJaG-JclUVm8gSEvbZRmIOrV2ypJ_dbfp7ew6BNThn5XXYz8is3whtfsF0us0Aoyge3HKppHGPFbHelWLPCw4mx2DuW5JYFMC0LyP4GxSj0s0rd08BmYrWQ82UY87gpGCUV1NrrS5PqasdUceXu0kJkQZ2zrnFyTIe0fgR74y1wPwJCFjEBZ-trO1trCztMyOdGvYjimSYSJ7NC4c-MaBcKfGVt96wdqm91FBmPW65msShxW_qJclHwxbJnHYbJ27vEbl6LxF2Cq67zb4X5zQlxxPVaYUJDiEE98e1cInOAFa0p3DGey8kiefhJJLLXBz4hss-IjyruuyC5O4l9uWdpkJ4oSGMp4wQlTli6DHrx08BRxW-JbBsjxxFjl5DoG4wViNNRhz2aCP1F4Vi2Y9-2O8RWHZvZr1wPOwzItrlV8yWSd1R2piOCbsz5I86mC7JcdhAAcOHjz-x8WkBW2l48hWDyArUmF3GQJXPs-c7LOMusb7dFSkDNfMQbpz9gMX-MGPHKXBU4D0F79kpK2IlucKXqJ0dwNnv3tJHaxA3CO1GNlvl0CbfnZ75SbewmnJ8p-hh4laRWsprzYEa8lzV5BpdUT2irF2hol370SIAyfYPo_YXI-FWJtxjQqPm37AodQFAEiVknbsLb7gHGSPwJXbVXkbkikmgGoo2izpmHNN1qmSNJCmQ=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/QWWFWmgn9SI9hc-F9xM9xydgPCiSW2VWVmDjRg435ajhVogEiAoB9PX-1RKaVUjDiKRyhc0mj2qkbA4PLt-zwjFZJv4NdisLfrTkrq5nIJNyF3tCbqnSCbccv7Z5RVTDS9Mooq7NuB81pvvF-S9JTXkJSwsXBv6VNY3x-dJy0Dhv_GM7rglLs3z5wqQNExtoMLaNZ7nly0ZXUom1AD-bGMOk1e0HXNe6YPiROS5FS6fvkZpNq4mPJXOYrAO7TYNpxGJ_8lL5-cWEWz881u4dtqC00V9jjYmB3Zv3GIcg_BNzJ-chAeVxYVNWtSbjSbVrIDv3c6-2toJy3q7RZsIlnJIzEsq2qo9zhAxVrBDMt4kJ50rqLvIJp4aYKDIbKH_YrYjWKXG3Nz9h1pkqyYw93J6oRq_8JS2W8k8aFzbKM4ASBCcCSvOHrfQLW4F9Jda743roruGOP7O0vMS-9gUZEGwWY-l-KM1pye7Mk93heJFgO38LVTxbHprsqAoxJ3YsegKVK3iHR54Roh4Ad8DZT_3egIsoM4RDas3a58nb8u3i7v9knNRMcXcdRiAHXVjDOLDEcQ1uxWYZehG9sUhfXHB85bvkbzPruTsMJRNJNUHv-XxDy4qN4Mp-KMiWXa5yQcajZ18znq8T5Fh8MwNvZ-n7V7fmR12NzIs6P4QFU7pV21W6dIFLMftdVMHg5Tyb7cgnhrPFA9xIllzC6uU5LpwpQ-F8Mul0zj4NuX_eQdgM4CRa9g=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/gmv02CzGXpgNFo9j7TSxNJSBPQ1SHS0ezY6KLnKVcOMuSY0BciIr00Q9eQovmNZsKn8k_7c6BZZKdKd42hIutQEY9LWOW0eiHrI6ZaKLB5S5QBkvTfUR1MGWlWPO_04EeRNi5dE8SLc-1gjjpS3eAv0HiHVyDWc2P3SEslkFX94-qXB_5HjQgny8H-wIdpdYOzjwfjIqnVaePN-MOVCZooQUNRSu760DSegdU2gdSAisAVoQqMzejevk3XkiAHXNgCeQMwUCt33qMh9BhQWjPLP6r1DRFUAQ9SWKFodVe_pTxAIgxky4KS5dfGC9uhE6A5wefxiXFLJLtyJJT7uG3-v0Bp7fCxt_8SWqK0F7iqTUlv_qjIcaDt6DtBdDTFX96A2QZYArAUH9f9boiQO-TmERuc4faN6g2o0d9JgAD5DsLFmO_O6i6hgD1ONP-vzoKd0ZFQHMeVX9xhPIMV40uqUr0w72_S9LFlSIKnHmEM0JyHM_v-e4n2EnkQwKWt5W4IgQdmSDiBmnxX1KTjAoo9ddkPhXoXmzhezma0z8uRAO2M3aM_jr67sAhfSZMvPBUkwTwS7h0_KLqjJoVKmXGcNBVM9zxVWipSiu1Ny07wNdixDkS27oGY2aejzudYp2L2dNrQJuN16cesP97oodYCSOs6Qy1CF4N_7i6wrCtd9bMEK7CxEljc7gGrV9hhP-3PNDLePt3Lcb8B8RNgRdsOhTJIs5v8hsQj_VzyOTxfqzTrmy6g=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://lh3.googleusercontent.com/22Jb93H__Xpik_DJBWm1ulTks-BG0v0jwpmZj3rQzWG_cvmjZfrFrGA9y-XhddG5-9l7pe0lMLRK8UsX3eBr7wKb8ShNX73S_kCGdMSsJ1JvL4hEatyOQ7-0RhRCkZ0jot9KPJV2zJRM764kT2KR_IicD_EhTzXgoA-RoGu9C3NcQ9rAX5uWF3pleHLJ1LNmu0DEeBxF3XuoF3IVW9dbkfioyBMF-kn82RDe1f9RIIRabJSOWXl_QIYI47aE07XrCU7SRlf9jnF-W0-YxiMYHmElDKoD7HP8ySLx6QCkjQNF5lMC7dF6R25jcwrK4co7rCU20gsMBb2vkalwHvfFxcsIgShugRDzjUjdqzoZ3GT_4WFA9MoYBAShvNAn0L-eWMrAhv-XOXpkjfeeS-BVP2SwusFHK0wLkCzsmH5FD7d0J44QpkgvFojZX0zj6x-KbIsGD-yl2cEqsUkzYGZufBlo2tRobAyNOv89E9aT1BeQs76cvwykybO5AMWCsV6ikr_fExZQMPwqMTg-8FoOhpff6mTUyKVqMXlbk0-8JP-IkaCr8V8rqUUpDtDrZLNVXxIDj0rEXp9MzIZgiSe7MDViHKnEpOGY6vP_GGGpvWkZY8mAEpTTyRH0cJFAZ4jVV6hQmzqMvREmZcOLUDKIFdG_fM-bJOO-bGMx1Bi3371GJch81K273_pdJka7AUB391dOPv0wZCp3y_qRWeabrhfhpYSD_87ncMY7pgvMqtJMMmwDaQ=w800-no&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/conference-talk-adaptable-human-rubyconf-china-2019</link>
      <title>Conference Talk: Adaptable Human @ RubyConf China 2019</title>
    </item>
    <item>
      <pubDate>Sat, 23 Jul 2016 18:33:29 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/i-accidentally-some-machine-learning-my-story-of-a-month-of-learning-elixir</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/i-accidentally-some-machine-learning-my-story-of-a-month-of-learning-elixir</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
About a month ago I was in-between jobs - I had two weeks to rest up, recharge and get ready for my new job. So I thought,&amp;nbsp;I should use those two weeks to learn something new.&lt;/p&gt;
&lt;p&gt;
Years ago I briefly looked into &lt;a href=&quot;http://elixir-lang.org/&quot;&gt;Elixir&lt;/a&gt; when it was first released to the wild, at the time I wasn’t interested in picking it up due to its syntax similarity to Ruby, despite their vastly different underlying semantics. I love Ruby, and it’s been my weapon of choice for the past 6-7 years, so when it came time for me to learn something &lt;em&gt;new&lt;/em&gt;, I naturally wanted to learn something a bit more different than Ruby, syntax-wise.&lt;/p&gt;
&lt;p&gt;
Fast-forward a few years, I am more mature and open-minded, and are now in a position to welcome Elixir and to embrace the Ruby-like syntax as well as the functional programming mindset with open arms.&lt;/p&gt;
&lt;h2&gt;
Learning Elixir&lt;/h2&gt;
&lt;p&gt;
Given the strong influence of Ruby in Elixir, I can’t help but get nostalgic about learning it by reading another great book by Dave Thomas: &lt;a href=&quot;https://pragprog.com/book/elixir12/programming-elixir-1-2&quot;&gt;Programming Elixir&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Dave Thomas’ original &lt;a href=&quot;https://pragprog.com/book/ruby/programming-ruby&quot;&gt;Programming Ruby&lt;/a&gt; was instrumental in the success of the Ruby programming language and its communities in the west, and it certainly has helped me to greatly widen my exposure to not only the wonderful world of Ruby but object-oriented programming in general as a PHP developer.&lt;/p&gt;
&lt;p&gt;
Learning Elixir has been really fun, not only does it share the same developer-friendliness championed by Ruby, it also does so with remarkable strength in concurrency thanks to BEAM (Erlang’s VM).&lt;/p&gt;
&lt;p&gt;
Many people are drawn to Elixir due to its Ruby influence, its functional and immutability nature, and its &lt;a href=&quot;https://en.wikipedia.org/wiki/Actor_model&quot;&gt;Actor-based concurrency model&lt;/a&gt;. I would however like to call out one of my favourite features of Elixir that sometimes gets overlooked, and that is how you could write unit tests using &lt;a href=&quot;http://elixir-lang.org/docs/stable/ex_unit/ExUnit.DocTest.html&quot;&gt;&lt;code class=&quot;inline&quot;&gt;ExUnit.DocTest&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
Elixir Makes Writing Unit Tests Effortless&lt;/h3&gt;
&lt;p&gt;
Python programmers have been writing doctests for years, but Ruby due to not having an equivalent standard library, has never had writing doctests taken off in its community. I’m glad Elixir has.&lt;/p&gt;
&lt;p&gt;
Take a look at the code snippet below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;defmodule Stemmer.Step0 do
  @doc &quot;&quot;&quot;
  ## Examples

      iex&gt; Stemmer.Step0.trim_apostrophes(&quot;&apos;ok&quot;)
      &quot;ok&quot;

      iex&gt; Stemmer.Step0.trim_apostrophes(&quot;o&apos;k&quot;)
      &quot;o&apos;k&quot;

      iex&gt; Stemmer.Step0.trim_apostrophes(&quot;&apos;o&apos;k&apos;&quot;)
      &quot;o&apos;k&quot;
  &quot;&quot;&quot;
  def trim_apostrophes(word) do
    word
    |&gt; String.replace_prefix(&quot;&apos;&quot;, &quot;&quot;)
    |&gt; String.replace_suffix(&quot;&apos;&quot;, &quot;&quot;)
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The three test cases given will actually be tested by ExUnit, provided you ask it to do so as below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;defmodule Stemmer.Step0Test do
  use ExUnit.Case, async: true

  doctest Stemmer.Step0
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
You may think having doctests is not a big deal, what I can say is that I am really enjoying the fact that &lt;strong&gt;unit tests can be written with minimal friction and high visibility&lt;/strong&gt; (as they sit with the implementation, rather than within a big test suite with a sea of files). Besides, not all of us practice TDD religiously or 100% of the time, and when I don’t or can’t do TDD, having doctests ensures I don’t forget adding test cases. :)&lt;/p&gt;
&lt;h3&gt;
Toy Robot in Elixir&lt;/h3&gt;
&lt;p&gt;
The best way to learn something new is to practice it as you learn it. Instead of diving straight into a complicated system, or to write a &lt;code class=&quot;inline&quot;&gt;hello world&lt;/code&gt; program, I thought I would dig out a code test and re-implement it in Elixir.&lt;/p&gt;
&lt;p&gt;
The code test is the rather infamous &lt;a href=&quot;https://github.com/search?q=toy+robot&quot;&gt;Toy Robot&lt;/a&gt; test. As an interviewer, I must have reviewed a few hundreds of these tests, most of which in Ruby. I know what a good OO solution looks like, so naturally I was looking forward to “rethink” the problem and have a crack at it using Elixir.&lt;/p&gt;
&lt;p&gt;
Here is the result: &lt;a href=&quot;https://github.com/fredwu/toy-robot-elixir&quot;&gt;https://github.com/fredwu/toy-robot-elixir&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
As a learner, I wanted to practice as many language features as possible, so included in the Toy Robot test code I tried:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Different data structures such as Struct and List  &lt;/li&gt;
  &lt;li&gt;
Pattern matching  &lt;/li&gt;
  &lt;li&gt;
Data piping (&lt;code class=&quot;inline&quot;&gt;|&gt;&lt;/code&gt;)  &lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;inline&quot;&gt;Agent&lt;/code&gt; for managing states  &lt;/li&gt;
  &lt;li&gt;
Macros for validation rules  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I kept the test code small and nimble on purpose to illustrate the readability of a highly expressive language. I may not have exercised all the language features (such as supervisors and protocols), but at that point I felt I could start the Elixir journey with a big smile on my face already.&lt;/p&gt;
&lt;h2&gt;
Learning Phoenix&lt;/h2&gt;
&lt;p&gt;
I have to admit, a big part of the reason that got me started on learning Elixir is to build a side project. Initially I wanted to simply use Ruby and Rails because I can be very productive using them, but in the end I decided on learning Elixir and &lt;a href=&quot;http://www.phoenixframework.org/&quot;&gt;Phoenix&lt;/a&gt;, because &lt;strong&gt;most side projects fail, and when they do, how much learning can you extract out of those experiences?&lt;/strong&gt; My answer to this question, is to learn a new language, a new framework and most importantly a new programming paradigm to drastically increase the amount of learning I could gain.&lt;/p&gt;
&lt;p&gt;
But please, before you jump on Phoenix, learn Elixir properly first! Over the years I’ve seen far too many cases of people jumping on Rails without understanding the language features of Ruby…&lt;/p&gt;
&lt;p&gt;
To learn Phoenix, the &lt;a href=&quot;https://pragprog.com/book/phoenix/programming-phoenix&quot;&gt;Programming Phoenix&lt;/a&gt; book is pretty much the bible on this subject aside from the official guide, and it is written by Chris McCord, the author of Phoenix, Bruce Tate, and Jose Valim, the author of Elixir.&lt;/p&gt;
&lt;p&gt;
As an experienced Rails developer, it only took me a day or two to go through the book (I largely skimmed the chapters on &lt;code class=&quot;inline&quot;&gt;Channels&lt;/code&gt; as I don’t intend to build a real-time app).&lt;/p&gt;
&lt;p&gt;
Now, as a Ruby developer, the biggest pain point when working on Rails or other sizeable Ruby MVC projects for me, is ActiveRecord. I got so frustrated to the status quo I even &lt;a href=&quot;https://github.com/fredwu/datamappify&quot;&gt;attempted to fix it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Fortunately, in Elixir and Phoenix we have &lt;a href=&quot;https://github.com/elixir-ecto/ecto&quot;&gt;Ecto&lt;/a&gt;. One of my favourite features of Ecto is the concept of &lt;a href=&quot;https://hexdocs.pm/ecto/Ecto.Changeset.html&quot;&gt;Changeset&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Take a look at the code snippet below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;defmodule MySecretApp.User do
  use MySecretApp.Web, :model

  schema &quot;users&quot; do
    field :username, :string
    field :email, :string
    field :password, :string, virtual: true
    field :encrypted_password, :string

    has_one :profile, MySecretApp.Profile

    timestamps()
  end

  def changeset(struct, params \\ %{}) do
    struct
    |&gt; cast(params, [:username, :email])
    |&gt; validate_required([:username, :email])
    |&gt; validate_length(:username, min: 3, max: 20)
    |&gt; validate_format(:username, ~r/\A[a-zA-Z0-9_]+\z/, message: &quot;alphanumeric and underscores only&quot;)
    |&gt; validate_format(:email, ~r/@/)
    |&gt; unique_constraint(:username)
    |&gt; unique_constraint(:email)
  end

  def creation_changeset(struct, params \\ %{}) do
    struct
    |&gt; changeset(params)
    |&gt; password_changeset(params)
  end


  defp password_changeset(struct, params) do
    struct
    |&gt; cast(params, [:password])
    |&gt; validate_required([:password])
    |&gt; validate_length(:password, min: 8, max: 200)
    |&gt; encrypt_password
  end

  defp encrypt_password(changeset) do
    case changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: password}} -&gt;
        put_change(changeset, :encrypted_password, Comeonin.Bcrypt.hashpwsalt(password))
      _ -&gt;
        changeset
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The &lt;code class=&quot;inline&quot;&gt;changset/2&lt;/code&gt; function can be used when a user needs to be updated, whereas the &lt;code class=&quot;inline&quot;&gt;creation_changeset/2&lt;/code&gt; is to be used only when a user is first created. Sure, you can achieve similar result in Rails by using custom validators, but the fact that this practice is enforced by the library and the framework, is encouraging.&lt;/p&gt;
&lt;p&gt;
One other thing that I’ve seen in larger Rails apps, is the leaky abstraction of view-level logic, they typically sit in controllers, helpers (which are globally available) or worse, models. Phoenix in this case follows what &lt;a href=&quot;http://hanamirb.org/&quot;&gt;Hanami&lt;/a&gt;, &lt;a href=&quot;http://trailblazer.to/&quot;&gt;Trailblazer&lt;/a&gt; and many other frameworks do: it introduces a “view model” layer.&lt;/p&gt;
&lt;p&gt;
Something along the lines of:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;defmodule MySecretApp.UserView do
  use MySecretApp.Web, :view

  def full_name do
    &quot;#{title} #{first_name} #{last_name}&quot;
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
In a nutshell, Phoenix is just like Rails, but less magical (in a good way) and faster. :) Like the Elixir eco-system, most libraries and concepts feel like their ruby/rails counterparts, but more refined.&lt;/p&gt;
&lt;p&gt;
There are a few popular &lt;a href=&quot;https://hex.pm/&quot;&gt;Hex&lt;/a&gt; packages if you’re familiar with their ruby counterparts:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left;&quot;&gt;
      &lt;/th&gt;
      &lt;th style=&quot;text-align: left;&quot;&gt;
Elixir      &lt;/th&gt;
      &lt;th style=&quot;text-align: left;&quot;&gt;
Ruby      &lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
Code analysis      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://hex.pm/packages/credo&quot;&gt;credo&lt;/a&gt;      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://rubygems.org/gems/rubocop&quot;&gt;rubocop&lt;/a&gt;      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
Testing      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://hex.pm/packages/espec&quot;&gt;espec&lt;/a&gt;      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://rubygems.org/gems/rspec&quot;&gt;rspec&lt;/a&gt;      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
Browser testing      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://hex.pm/packages/wallaby&quot;&gt;wallaby&lt;/a&gt;      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://rubygems.org/gems/capybara&quot;&gt;capybara&lt;/a&gt;      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
Test coverage      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://hex.pm/packages/excoveralls&quot;&gt;excoveralls&lt;/a&gt;      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://rubygems.org/gems/simplecov&quot;&gt;simplecov&lt;/a&gt;      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
Test factory      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://hex.pm/packages/ex_machina&quot;&gt;ex_machina&lt;/a&gt;      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://rubygems.org/gems/factory_girl&quot;&gt;factory_girl&lt;/a&gt;      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
Authentication      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://hex.pm/packages/guardian&quot;&gt;guardian&lt;/a&gt;      &lt;/td&gt;
      &lt;td style=&quot;text-align: left;&quot;&gt;
&lt;a href=&quot;https://rubygems.org/gems/devise&quot;&gt;devise&lt;/a&gt;      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
And the list goes on and on… Be sure to check out &lt;a href=&quot;https://github.com/h4cc/awesome-elixir/&quot;&gt;Awesome Elixir&lt;/a&gt; for more community curated Elixir libraries.&lt;/p&gt;
&lt;h2&gt;
Learning Machine Learning&lt;/h2&gt;
&lt;p&gt;
As I started building the foundation of my side project, you know, the usual user management and session management, etc, etc, by chance I came across mentions of &lt;a href=&quot;https://en.wikipedia.org/wiki/Bayesian_inference&quot;&gt;Bayesian inference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
One thing led to another, very soon I started looking into varies different machine learning algorithms such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Naive_Bayes_classifier&quot;&gt;Naive Bayes&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Random_forest&quot;&gt;Random Forest&lt;/a&gt;. These are all subjects I had never come across or even heard of before, as I have no strong mathematics, statistics or computer science background. I was however, intrigued and inspired nonetheless, and wanted to employ some machine learning in my side project.&lt;/p&gt;
&lt;p&gt;
And the best way to understand and learn about machine learning algorithms? You guessed, is to write one! After some research, I came to the conclusion that Naive Bayes is one of the simplest to implement, is great for text classification which is useful for my side project, and has good accuracy given its simplicity and fast speed.&lt;/p&gt;
&lt;h3&gt;
Introducing &lt;a href=&quot;https://github.com/fredwu/simple_bayes&quot;&gt;Simple Bayes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
So, after a few train rides to and from work, on my newly purchased Macbook (yes, the one with only a single USB-C port), I built a Naive Bayes library: &lt;a href=&quot;https://github.com/fredwu/simple_bayes&quot;&gt;Simple Bayes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
As of writing, this is the only Naive Bayes library in Elixir that supports the following features:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Naive Bayes algorithm with different models    &lt;ul&gt;
      &lt;li&gt;
Multinomial      &lt;/li&gt;
      &lt;li&gt;
Binarized (boolean) multinomial      &lt;/li&gt;
      &lt;li&gt;
Bernoulli      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
No external dependencies  &lt;/li&gt;
  &lt;li&gt;
Ignores stop words  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Additive_smoothing&quot;&gt;Additive smoothing&lt;/a&gt;  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Tf-idf&quot;&gt;TF-IDF&lt;/a&gt;  &lt;/li&gt;
  &lt;li&gt;
Optional keywords weighting  &lt;/li&gt;
  &lt;li&gt;
Optional word stemming via &lt;a href=&quot;https://github.com/fredwu/stemmer&quot;&gt;Stemmer&lt;/a&gt;  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Let’s see it in action shall we? :)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;SimpleBayes.init
|&gt; SimpleBayes.train(:ruby, &quot;I enjoyed using Rails and ActiveRecord for the most part.&quot;)
|&gt; SimpleBayes.train(:ruby, &quot;The Ruby community is awesome.&quot;)
|&gt; SimpleBayes.train(:ruby, &quot;There is a new framework called Hanami that&apos;s promising.&quot;)
|&gt; SimpleBayes.train(:ruby, &quot;Please learn Ruby before you learn Rails.&quot;)
|&gt; SimpleBayes.train(:ruby, &quot;We use Rails at work.&quot;)
|&gt; SimpleBayes.train(:elixir, &quot;It has Phoenix which is a Rails-like framework.&quot;)
|&gt; SimpleBayes.train(:elixir, &quot;Its author is a Rails core member, Jose Valim.&quot;)
|&gt; SimpleBayes.train(:elixir, &quot;Phoenix and Rails are on many levels, comparable.&quot;)
|&gt; SimpleBayes.train(:elixir, &quot;Phoenix has great performance.&quot;)
|&gt; SimpleBayes.train(:elixir, &quot;I love Elixir.&quot;)
|&gt; SimpleBayes.train(:php, &quot;I haven&apos;t written any PHP in years.&quot;)
|&gt; SimpleBayes.train(:php, &quot;The PHP framework Laravel is inspired by Rails.&quot;)
|&gt; SimpleBayes.classify(&quot;I wrote some Rails code at work today.&quot;)
# =&gt; [
# ruby: 0.20761437345986136,
# elixir: 0.08101868169313056,
# php: 0.019047884912605735
# ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can see, provided with reasonable training data, Naive Bayes can work extremely well.&lt;/p&gt;
&lt;h3&gt;
Introducing &lt;a href=&quot;https://github.com/fredwu/stemmer&quot;&gt;Stemmer&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
Something I discovered as I was building Simple Bayes, is something called &lt;a href=&quot;https://en.wikipedia.org/wiki/Stemming&quot;&gt;stemming&lt;/a&gt;. Let’s see another example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;SimpleBayes.init(stem: false)
|&gt; SimpleBayes.train(:apple, &quot;buying apple&quot;)
|&gt; SimpleBayes.train(:banana, &quot;buy banana&quot;)
|&gt; SimpleBayes.classify(&quot;buy apple&quot;)
# =&gt; [
# banana: 0.057143654737817205,
# apple: 0.057143654737817205
# ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Oops, the probabilities of the sentence “buy apple” of being &lt;code class=&quot;inline&quot;&gt;apple&lt;/code&gt; and &lt;code class=&quot;inline&quot;&gt;banana&lt;/code&gt; are the same, that’s not good, as we know “buying” and “buy” should mean the same thing. This is where stemming comes in handy. Let’s enable stemming and run the example again:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;elixir language-elixir&quot;&gt;SimpleBayes.init(stem: true)
|&gt; SimpleBayes.train(:apple, &quot;buying apple&quot;)
|&gt; SimpleBayes.train(:banana, &quot;buy banana&quot;)
|&gt; SimpleBayes.classify(&quot;buy apple&quot;)
# =&gt; [
# apple: 0.18096114003107086,
# banana: 0.1505149978319906
# ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Stemming in this case correctly identified “buy” and “buying” as the same thing (they both have the stemmed root of “buy”).&lt;/p&gt;
&lt;p&gt;
How did I include stemming in Simple Bayes you wonder? Let me introduce you to &lt;a href=&quot;https://github.com/fredwu/stemmer&quot;&gt;Stemmer&lt;/a&gt; - as of writing this is the only Porter2 stemmer available in Elixir. :)&lt;/p&gt;
&lt;p&gt;
Elixir and BEAM may not be known for their raw performance, but compared to a similar Porter2 stemmer implemented in pure ruby, my Elixir version runs about five times faster (under &lt;code class=&quot;inline&quot;&gt;5&lt;/code&gt;s to stem 29000+ words, compared to &lt;code class=&quot;inline&quot;&gt;25&lt;/code&gt;s with the ruby version).&lt;/p&gt;
&lt;h2&gt;
The Learning Continues…&lt;/h2&gt;
&lt;p&gt;
I’ve only been writing Elixir for a month, and there are still heaps to learn and to practice. So far though, I have to say my experience with both Elixir and Phoenix has been fantastic - I get the same satisfying and pumped feeling I got when I was learning Ruby and Rails years ago.&lt;/p&gt;
&lt;p&gt;
If you haven’t checked out Elixir, I strongly encourage you to do so, after all, the world seems to be moving in the concurrency direction at an increasingly rapid speed, including &lt;a href=&quot;http://engineering.appfolio.com/appfolio-engineering/2015/11/18/ruby-3x3&quot;&gt;Ruby 3x3&lt;/a&gt;. :)&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/i-accidentally-some-machine-learning-my-story-of-a-month-of-learning-elixir</link>
      <title>I Accidentally Some Machine Learning - My Story of A Month of Learning Elixir</title>
    </item>
    <item>
      <pubDate>Wed, 18 Sep 2013 06:50:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/protip-faster-ruby-tests-with-databasecleaner-and-databaserewinder</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/protip-faster-ruby-tests-with-databasecleaner-and-databaserewinder</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
&lt;em&gt;Please also see &lt;a href=&quot;/blog/2013-09-06-protip-ruby-devs-please-tweak-your-gc-settings/&quot;&gt;this blog post on tweaking your ruby GC settings&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
I use and love &lt;a href=&quot;https://github.com/bmabey/database_cleaner&quot;&gt;DatabaseCleaner&lt;/a&gt;, although historically I had never paid too much attention on the performance of its varies cleaning strategies - I’d always used &lt;code class=&quot;inline&quot;&gt;truncation&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
We use Postgres, and after digging around and finding out &lt;a href=&quot;http://stackoverflow.com/questions/11419536/postgresql-truncation-speed/11423886#11423886&quot;&gt;the difference between DELETE and TRUNCATE&lt;/a&gt;, I ended up improving our test suite speed by about 30-40% simply by tweaking the cleaning strategies.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;RSpec.configure do |config|
  config.before :suite do
    DatabaseCleaner.clean_with :truncation
    DatabaseCleaner.strategy = :transaction
  end

  config.before do
    if example.metadata[:js] || example.metadata[:type] == :feature
      DatabaseCleaner.strategy = :deletion
    else
      DatabaseCleaner.strategy = :transaction
      DatabaseCleaner.start
    end
  end

  config.after do
    DatabaseCleaner.clean
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Essentially, we want to &lt;code class=&quot;inline&quot;&gt;truncate&lt;/code&gt; the DB only once before the whole suite runs to ensure a clean slate DB, then we only want to use &lt;code class=&quot;inline&quot;&gt;deletion&lt;/code&gt; on Capybara tests, everything else should just use &lt;code class=&quot;inline&quot;&gt;transaction&lt;/code&gt; which is the fastest strategy.&lt;/p&gt;
&lt;p&gt;
Now, as a bonus, I have just discovered @amatsuda’s &lt;a href=&quot;https://github.com/amatsuda/database_rewinder&quot;&gt;DatabaseRewinder&lt;/a&gt; which is a lightweight alternative that supports only ActiveRecord. It offers comparable performance with a much similar API.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;RSpec.configure do |config|
  config.before :suite do
    DatabaseRewinder.clean_all
  end

  config.after do
    DatabaseRewinder.clean
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
By the way, we also use &lt;a href=&quot;https://github.com/grosser/parallel_tests&quot;&gt;parallel_tests&lt;/a&gt; to scale our test suite to multiple processes, even on Travis CI and Wercker.&lt;/p&gt;
&lt;p&gt;
Hooray to faster tests! :)&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/protip-faster-ruby-tests-with-databasecleaner-and-databaserewinder</link>
      <title>Protip: Faster Ruby Tests with DatabaseCleaner and DatabaseRewinder</title>
    </item>
    <item>
      <pubDate>Fri, 06 Sep 2013 11:13:37 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/protip-ruby-devs-please-tweak-your-gc-settings-for-tests</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/protip-ruby-devs-please-tweak-your-gc-settings-for-tests</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
It was made apparent to me that many ruby devs either aren’t aware or couldn’t be bothered to tweak their ruby garbage collector settings.&lt;/p&gt;
&lt;p&gt;
Well, if you are using MRI, please start tweaking your GC settings. Here’s what I use (on my 15” Macbook Pro Retina):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;shell language-shell&quot;&gt;export RUBY_GC_MALLOC_LIMIT=90000000
export RUBY_FREE_MIN=200000&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Not only can you tweak it for your local dev machine, you can also tweak Jenkins, &lt;a href=&quot;http://travis-ci.com/&quot;&gt;Travis CI&lt;/a&gt;, &lt;a href=&quot;http://wercker.com/&quot;&gt;Wercker&lt;/a&gt; and other CI solutions, making instant speed gain for your test suite!&lt;/p&gt;
&lt;p&gt;
Here’s what we get:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;shell language-shell&quot;&gt;            Before After
Local:      8m22s 5m52s
Travis CI:  10m10s 6m0s
Wercker:    8m45s 6m24s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
YMMV depending on your system and available RAM.&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/protip-ruby-devs-please-tweak-your-gc-settings-for-tests</link>
      <title>Protip: Ruby Devs, Please Tweak Your GC Settings for Tests!</title>
    </item>
    <item>
      <pubDate>Wed, 21 Aug 2013 12:39:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/gotchas-in-the-ruby-sequel-gem</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/gotchas-in-the-ruby-sequel-gem</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
I haven’t really used &lt;a href=&quot;http://sequel.rubyforge.org/&quot;&gt;Sequel&lt;/a&gt; much therefore I am definitely a newbie. However, after days and nights of frustration, endless debugging and some search-fu during the development of &lt;a href=&quot;https://github.com/fredwu/datamappify&quot;&gt;Datamappify&lt;/a&gt;, I have finally arrived at the conclusion that Sequel is a capable library, as long as you are aware of the gotchas.&lt;/p&gt;
&lt;h3&gt;
Gotcha 1: Always use “&lt;code class=&quot;inline&quot;&gt;select&lt;/code&gt;“/“&lt;code class=&quot;inline&quot;&gt;select_all&lt;/code&gt;“, or your data records will mysteriously have wrong IDs!&lt;/h3&gt;
&lt;p&gt;
In ActiveRecord, joining an associated model couldn’t be simpler:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.joins(:author)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
In Sequel, despite having a similar API for models to declare associations and their corresponding primary and foreign keys, you cannot do a &lt;code class=&quot;inline&quot;&gt;join&lt;/code&gt; without specifying the keys:&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Not good:&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.join(:authors)
# or
Post.join(Author)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;em&gt;Better:&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.join(:authors, :id =&gt; :author_id)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
You would think the version above works - it doesn’t. Even worse, the above example &lt;strong&gt;will give you incorrect data&lt;/strong&gt; - the IDs of the Post records will now contain the IDs from their corresponding Author records! This is because upon a &lt;code class=&quot;inline&quot;&gt;join&lt;/code&gt;, Sequel merges attributes from both models into a single hash.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;The correct version:&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.join(:authors, :id =&gt; :author_id).select(:posts __id, :posts__ title, :posts__body)
# or
Post.join(:authors, :id =&gt; :author_id).select_all(:posts)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mrvsa2sBB81qz4rgp.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h3&gt;
Gotcha 2: Always call “&lt;code class=&quot;inline&quot;&gt;all&lt;/code&gt;“ at the end of the chain, or the chain will present data in a different format.&lt;/h3&gt;
&lt;p&gt;
In ActiveRecord, all of the below examples return an &lt;code class=&quot;inline&quot;&gt;ActiveRecord::Relation&lt;/code&gt; collection:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.where(:title =&gt; &apos;Hello world&apos;)
Post.joins(:author)
Post.includes(:author)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
And indeed, calling &lt;code class=&quot;inline&quot;&gt;first&lt;/code&gt; on any of them returns an object of class &lt;code class=&quot;inline&quot;&gt;Post&lt;/code&gt; (assuming the result collection is not empty).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.where(:title =&gt; &apos;Hello world&apos;).first.class #=&gt; Post
Post.joins(:author).first.class #=&gt; Post
Post.includes(:author).first.class #=&gt; Post&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
In Sequel, the below examples all return a &lt;code class=&quot;inline&quot;&gt;Sequel::DataSet&lt;/code&gt; collection:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.where(:title =&gt; &apos;Hello world&apos;)
Post.eager(:author)
Post.eager_graph(:author)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
But let’s see what we get from calling &lt;code class=&quot;inline&quot;&gt;first.class&lt;/code&gt; on them:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.where(:title =&gt; &apos;Hello world&apos;).first.class #=&gt; Post
Post.eager(:author).first.class #=&gt; Post
Post.eager_graph(:author).first.class #=&gt; Hash&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Huh? Last one is a &lt;code class=&quot;inline&quot;&gt;Hash&lt;/code&gt;? It turns out, if you call &lt;code class=&quot;inline&quot;&gt;all&lt;/code&gt; at the end of chains to convert them to &lt;code class=&quot;inline&quot;&gt;Array&lt;/code&gt;s, then the returned collections are consistent:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Post.where(:title =&gt; &apos;Hello world&apos;).all.first.class #=&gt; Post
Post.eager(:author).all.first.class #=&gt; Post
Post.eager_graph(:author).all.first.class #=&gt; Post&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mrvsa2sBB81qz4rgp.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/gotchas-in-the-ruby-sequel-gem</link>
      <title>Gotchas in the Ruby Sequel Gem</title>
    </item>
    <item>
      <pubDate>Sat, 29 Jun 2013 12:04:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/the-future-of-computing-the-future-of-computer-programmers-an-interview-with-yukihiro-matz-matsumoto</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/the-future-of-computing-the-future-of-computer-programmers-an-interview-with-yukihiro-matz-matsumoto</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
A while ago I &lt;a href=&quot;/blog/2012-11-25-an-interview-with-yukihiro-matz-matsumoto/&quot;&gt;translated an interview with Matz&lt;/a&gt; done by a Chinese book publisher. The interview and the translation were well received, so this time I am translating another interview with Matz, done by Ito, the editor-in-chief from Japanese website &lt;a href=&quot;http://engineer.typemag.jp/article/matz&quot;&gt;Engineer Type&lt;/a&gt;. Since I don’t read Japanese, the translation is based on &lt;a href=&quot;http://www.ituring.com.cn/article/45484&quot;&gt;Turing Book’s Chinese translation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
The Chinese translator has done a great job translating the interview, but there are still many words and sentences lack sufficient context and therefore are difficult to grasp. I have put in many hours translating the text as well as doing researches to ensure the final article is readable. I hope you will enjoy it! :)&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x3eZbVc1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Thank you for doing an interview with us, Matz. I have just finished reading your latest book &lt;em&gt;&lt;a href=&quot;http://www.amazon.co.jp/dp/4822234630/&quot;&gt;The Future of Computing&lt;/a&gt;&lt;/em&gt;, could you perhaps talk about the future of programming and software programmers in general?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Hmmm, this is difficult to answer… but thanks for reading my book!  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; In the book you’ve shared your thoughts on the past, present and future of different programming languages and software design patterns. Would you like to talk about the current state of the software industry? And is there going to be another paradigm shift in software development?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; As discussed in my book, to predict the future of a high tech industry such as computing is not particularly difficult. I believe in the foreseeable future the computing industry is still going to advance based on &lt;a href=&quot;http://en.wikipedia.org/wiki/Moore%27s_law&quot;&gt;Moore’s law&lt;/a&gt;. Although, it is possible that in the next year or two &lt;a href=&quot;https://en.wikipedia.org/wiki/Quantum_computer&quot;&gt;quantum computers&lt;/a&gt; become a practical reality, in that case it will change everything! *chuckles* On a serious note, according to Moore’s law, the cost of computing will decrease and the performance and capacity of computing will increase - this basic principle is unlikely to change. One thing I did notice in recent years is that due to the advancement in computer hardware, the software industry is subtly changing too.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Software Development in the Era of Multi-core and Cloud Computing&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; It was about twenty years ago (in 1993) I invented the Ruby programming language, yet it still runs surprisingly well on modern computers.  &lt;/p&gt;
  &lt;p&gt;
What this means is that in the past twenty years the computing environment which the software runs on did not see any fundamental changes. In recent years, we started seeing computing power being shifted from having higher CPU frequencies to being distributed over more CPU cores. And that means software needs to move in that direction too.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x3p6yvF1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Matz: Software has not seen major changes for years.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; And this is covered in the last chapter from the book, right?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Yes. Similarly to multi-core, cloud computing is advancing in the same direction. The future of computing is all about utilise multiple CPUs or computers effectively.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; So, how does that change software development?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; In the past ten years or so we have been seeing more and more things happen on the Internet, and the Internet is an amazing application platform for extension and distribution. Compared to software engineers working on &lt;a href=&quot;http://en.wikipedia.org/wiki/Mainframe_computer&quot;&gt;mainframe computers&lt;/a&gt;, web developers are naturally more familiar with the concepts of multi-core and cloud computing.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; After interviewing many web and mobile startups, we realised that the number of software engineers working in &lt;a href=&quot;http://en.wikipedia.org/wiki/Platform_as_a_service&quot;&gt;PaaS&lt;/a&gt; and cloud computing have been increasing rapidly.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Absolutely. And I do believe that “not needing to purchase and own dedicated hardware” is going to be the mainstream. The idea and thought process of “not owning” is not only important for software development, but also important for business development.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
“Owning” Becoming a Liability, Not Asset&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; In the past, “owning” was seen as the source of vitality of a corporation - those who own high performance mainframe computers were able to do business transactions in high volume whereas those who do not were not able to compete.  &lt;/p&gt;
  &lt;p&gt;
These days the landscape is changing - those corporations who do not “own” expensive hardware have more competitive edge. Let’s say it takes five years to break even from the expensive investment of servers, during that time those machines are being put in use to realise their full potential and to justify their cost. It may appear to have saved the business cost but it is not, simply because the value of the hardware decreases as each day passes by.  &lt;/p&gt;
  &lt;p&gt;
To put simply, we are now entering the era of “owning” being a liability rather than asset. If you had the most advanced hardware, software engineers were able to develop efficiently. On the contrary, if you didn’t, then you might want to get used to the hours-long waiting for the code to compile. *chuckles* The rise of cloud computing platforms like &lt;a href=&quot;http://www.2gocn.com/&quot;&gt;Heroku&lt;/a&gt; is making “owning” a thing of the past.  &lt;/p&gt;
  &lt;p&gt;
Also, “not owning” has several advantages on the development as well as the commercial front. For instance, it allows many startups to rise. In the past, in order to start a new business you would need capital for purchasing servers and/or renting servers in a data centre. These days, to get started on a platform like Heroku couldn’t be easier, for example on Heroku you could start with just one dyno for free. This new way of developing software significantly reduces costs and risks.  &lt;/p&gt;
  &lt;p&gt;
Years ago I read an essay called &lt;a href=&quot;http://www.paulgraham.com/ramenprofitable.html&quot;&gt;Ramen Profitable&lt;/a&gt; by &lt;a href=&quot;http://ycombinator.com/&quot;&gt;Y Combinator&lt;/a&gt;’s founder &lt;a href=&quot;http://en.wikipedia.org/wiki/Paul_Graham_%28computer_programmer%29&quot;&gt;Paul Graham&lt;/a&gt;. “Not owning”’s flexibility and agility contribute a great deal to it. And this trend has now grown beyond just relevant to startups, in fact in the recent years many large corporations have begun adapting this approach too.  &lt;/p&gt;
  &lt;p&gt;
In the United States, corporations like Disney and Best Buy are indeed utilising Ruby, Rails and Heroku to rapidly grow their internal infrastructure in a cost-effective fashion. What was once considered competitive edges to venture capitalists, like “rapid development” and “development flexibility” are now also possible for these giant corporations.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; What about the giant corporations in Japan?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; I have never worked in a big corporation so I can’t tell where they are heading. People have been optimistic, though as an observer I am concerned.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x3tRPEw1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h2&gt;
Real Benefits of Innovation in Cloud Computing Not to Be Overlooked&lt;/h2&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; What makes you concerned about software development?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; The traditional approach of developing software is still the norm. For example, some corporations, even though use Amazon Web Services, still rely on system administrators to handle their infrastructure. It is too common to see a software development team consists of over a dozen people.  &lt;/p&gt;
  &lt;p&gt;
This in my opinion defeats the purpose and forfeits the benefits of “not owning” servers. There are simply too many of these case studies whereby only on the surface of cloud computing is explored and understood.  &lt;/p&gt;
  &lt;p&gt;
I have to say I am disappointed by some of the so-called “private clouds” owned by large corporations. The advantage of cloud computing is to utilise multiple computers in the cloud, but those private clouds are essentially their internal data centres. Isn’t that the same as owning a bunch of servers?  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x3ym1v61qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Matz: Many companies barely scratch the surface of emerging technologies.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Indeed, it is too often to see the real benefits of emerging technologies overlooked or misunderstood. Anything else that makes you concerned about the future?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Nowadays the speed of development has always been a priority from big development projects in &lt;a href=&quot;http://en.wikipedia.org/wiki/Business-to-business&quot;&gt;B2B&lt;/a&gt; to small development projects in many startups. &lt;a href=&quot;http://www.yahoo.co.jp/&quot;&gt;Yahoo! Japan&lt;/a&gt; even coined a term “爆速化” (explosively high speed) to indicate the importance of development speed in the ever more competitive and engaging markets.  &lt;/p&gt;
  &lt;p&gt;
Looking at things this way, those so-called “system integrators” are becoming obsolete. Should they just give up what they do or continue? I don’t know, but I do know that the gap between them and engineers who have the capability and skills to create real value is increasing.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Career Longevity of Software Engineering&lt;/h2&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Who are those engineers who have the capability and skills to create real value?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; The ones who would put in effort to create software or systems from a prototype to a final product. And this has nothing to do with whether they work in web or system integration, or whether it’s consumer oriented or corporate oriented.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x42bl5b1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Matz: Unbalanced skill combination leads to a gloomy future.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Do you mean the engineers who are capable from design to implementation?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Yes. Speaking of which, software developers have to know more than just system design - they cannot survive without knowing how to code. Just like in life, you cannot survive without being down to earth. *chuckles*  &lt;/p&gt;
  &lt;p&gt;
Despite the fact that it is pointless to have someone doing only the system design, and not the development as well, the System Integration industry is still going strong in Japan - and it is in fact an industry with high profit margin.  &lt;/p&gt;
  &lt;p&gt;
Even if the system designers came up with questionable specifications, or if the programmers were sloppy so the software was terrible to use, users would still use it despite whining. Flaws are easily glossed over under high profit margins.  &lt;/p&gt;
  &lt;p&gt;
But just as discussed before, as development speed increases, profit margins would undoubtedly become smaller. Flaws are therefore harder to gloss over.  &lt;/p&gt;
  &lt;p&gt;
In my opinion, if things don’t change, those run-of-the-mill software engineers might not survive in five years. Worse, the junior to mid-level to senior programmer corporate ladder is going to collapse.  &lt;/p&gt;
  &lt;p&gt;
Say, you wouldn’t want to start a VHS rental shop when DVDs were on the rise, would you?  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Difference Between Those Who Control Their Destiny to Those Who Don’t&lt;/h2&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Do you have any advice for those who do not wish to be in a “gloomy future”? What can they do?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; To innovate and to create new things, I suppose.  &lt;/p&gt;
  &lt;p&gt;
It’s not all doom and gloom. Even though many ageing technologies have been or are being replaced by the web, jobs will not disappear overnight. I think many software developers will still be employed in those jobs.  &lt;/p&gt;
  &lt;p&gt;
Having said that, it is always good to create new things or even invent new programming languages.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; What are these “new things”?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; I see three types of new things.  &lt;/p&gt;
  &lt;p&gt;
First of all, new services. If you can create a new service, or a service that offers superior user experience - it would be an innovation.  &lt;/p&gt;
  &lt;p&gt;
Secondly, new technologies. To come up with technologies better than the existing ones - and this is what I have been doing.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;a href=&quot;https://github.com/mruby/mruby&quot;&gt;  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x45MsHv1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;https://github.com/mruby/mruby&quot;&gt;mruby&lt;/a&gt; was released earlier this year on Github.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
Or, another way is to invent new algorithms.  &lt;/p&gt;
  &lt;p&gt;
The three ways I mentioned have different difficulties, but they share the same goal - to create something that hasn’t existed yet. Those who keep working on these kinds of challenges are the true outstanding software engineers.  &lt;/p&gt;
  &lt;p&gt;
The ones who do not challenge themselves to create new things are often falling behind - they learn a hip new language today and try a new web framework tomorrow, but still lack the foresight to invent and to improve.  &lt;/p&gt;
  &lt;p&gt;
Of course, it is important to learn and try new things, but if you see them as your ultimate goal then you will lose control of your destiny. I believe that the ones who do not get boggled down in every new trendy thing will ultimately be happier.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x48UgIX1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h2&gt;
Software Development is a Punch to Deficiency&lt;/h2&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Here is a sharp question: be a follower rather than an inventor is always easier and perhaps makes more money too. What makes you keep inventing?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; My standard answer would be “because writing and running new programs make me happy”. But the real reason is because I don’t like deficiency.  &lt;/p&gt;
  &lt;p&gt;
There are people who have different opinions and thought processes, I would often come up with questions like “why was it done this way” or “this will be too hard to use”.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x4bIpWG1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Matz dislikes deficiency, so he invented the ruby programming language.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; True, but all products more or less reflect their producers’ preferences, right?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Absolutely, and I am not saying that this is bad or anything. I just hate to point fingers at other people’s preferences - if you don’t like something, make your own! This is a basic trait of a good software engineer, and is what makes open source sustainable.  &lt;/p&gt;
  &lt;p&gt;
In open source projects, all the source code is publicly available therefore it is very easy to see how a program is designed. As long as you have ideas on how to improve and optimise the design, you are welcome to do so.  &lt;/p&gt;
  &lt;p&gt;
Now it is an entirely different story for certain things in the society. *chuckles* At least in software development, we can rely on our skills and knowledge to improve and to change. If it’s your own creation, it can be adjusted and adapted to suit the ever changing needs.  &lt;/p&gt;
  &lt;p&gt;
This is same for Ruby - I like programming languages and more importantly I like improving programming languages myself, and that’s why I still work on Ruby till this day.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Software Development, One of the Rare Careers that Could Make a Change on Your Own&lt;/h2&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x4fRpd91qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Matz talking about developer happiness, wearing his “&lt;a&gt;Ruby City MATSUE&lt;/a&gt;“ polo shirt.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; I think I have the right personality for developing software. Only the software industry can tolerate my carefreeness - am I too arrogant for saying that? *chuckles*  &lt;/p&gt;
  &lt;p&gt;
In all honesty, software development is one of the rare careers that could bring positive changes to the society on your own. It’s a wonderful occupation that brings happiness and fulfillment!  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Many people would predict their software future based on theories, but Matz you always use “happiness”.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; That’s right. Because only you can control your own destiny. It doesn’t matter if you were told to do things in a way just becasue “Matz said so” - ultimately, I cannot be responsible for your destiny. You should make your own decisions.  &lt;/p&gt;
  &lt;p&gt;
I would still say things like “the future might look like this”, but these are just my personal opinions.  &lt;/p&gt;
  &lt;p&gt;
And this is the same even for today’s discussion - if someone thinks he does not agree with what Matz has said, he should follow his own decision and the path he chooses.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Exploring the Future: “You” Are the Only Constant&lt;/h2&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Having read &lt;em&gt;The Future of Computing&lt;/em&gt;, I remember you talked about the inception and development of varies programming languages. But we all know that the IT industry is moving in a rapid pace, it is difficult to rely on history to guide us through to the future. If multi-core and cloud computing are only just the beginning of a paradigm shift, why did you write about the things happened in the past?&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp4x4ismcI1qz4rgp.jpg&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
Matz: Technologies progress just like a pendulum clock.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; People see things differently - and I believe the IT industry is progressing in a manner similar to the swing motion of a pendulum clock.  &lt;/p&gt;
  &lt;p&gt;
As more and more new programming languages, techniques and frameworks pop up, software development related technologies are progressing whilst seeking for balance.  &lt;/p&gt;
  &lt;p&gt;
So, how does “the most balanced from the past” become “the most balanced right now”? Think about how pendulum clock swings and in the past how technologies have emerged - you could then predict roughly what would constitute “the most balanced in the future”.  &lt;/p&gt;
  &lt;p&gt;
Use “centralised computing vs distributed computing” as an example, in the past there was usually only one centralised mainframe computer, later on to increase the processing capability commodity server farms were utilised, and now we are moving towards cloud computing.  &lt;/p&gt;
  &lt;p&gt;
There is no point to look at a particular past event. If you wanted to predict a technology in the future, knowing what has contributed to the balance of a past technology’s rise and fall is going to help.  &lt;/p&gt;
  &lt;p&gt;
Human’s ability is one of the factors too, because we have limited capability as a language designer it is useful to look at what others have done to cater for our ability, and therefore improve and evolve the technology.  &lt;/p&gt;
  &lt;p&gt;
In the book I briefly talked about &lt;a href=&quot;http://www.dartlang.org/&quot;&gt;Dart&lt;/a&gt; and &lt;a href=&quot;http://golang.org/&quot;&gt;Go&lt;/a&gt;. As a programming language inventor I find it really fascinating to explore the thought processes behind those language designers. And it has helped me to gain a deeper understanding of human behaviour.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; I was going to ask why it is so important to study the past, now I know.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; I mentioned this in the beginning - computing has not seen major changes for years.  &lt;/p&gt;
  &lt;p&gt;
Programming languages invented over fifty years ago are still in use today, and Ruby has been around for twenty years now. This proves that computing is progressing slower than what a lot of people believe.  &lt;/p&gt;
  &lt;p&gt;
On that note, there are many past cases whereby focuses were put on what was cool and new without understanding why. Compared to those “follower” software developers, the ones who command and understand the principles and theories behind changes and progresses have a much longer career longevity.  &lt;/p&gt;
  &lt;p&gt;
If you are a software developer who wants a longer career longevity, please read &lt;em&gt;The Future of Computing&lt;/em&gt;! *chuckles*  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Ito:&lt;/strong&gt; Thank you Matz for talking to us today!&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/the-future-of-computing-the-future-of-computer-programmers-an-interview-with-yukihiro-matz-matsumoto</link>
      <title>The Future of Computing, The Future of Computer Programmers - An Interview with Yukihiro &quot;Matz&quot; Matsumoto</title>
    </item>
    <item>
      <pubDate>Thu, 27 Jun 2013 12:09:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/datamappify-a-new-take-on-decoupling-domain-form-and-persistence-in-rails</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/datamappify-a-new-take-on-decoupling-domain-form-and-persistence-in-rails</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
&lt;em&gt;This post is about the ruby library we are building - &lt;a href=&quot;https://github.com/fredwu/datamappify&quot;&gt;Datamappify&lt;/a&gt;, please go check it out.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
At &lt;a href=&quot;http://www.locomote.com.au/&quot;&gt;Locomote&lt;/a&gt; we are building a relatively large web application using Rails. Before we began to lay the foundation, we knew very well that if we wanted the project to be maintainable we had to architect the system with extra care and attention. More specifically, we can’t rely on simply using ActiveRecord which combines behaviour and persistence as our domain models.&lt;/p&gt;
&lt;p&gt;
We began our search for something that would help us decouple our application from the domain layer down to the form handling. We’ve found a couple of gems that are close to what we were after - &lt;a href=&quot;https://github.com/braintree/curator&quot;&gt;Curator&lt;/a&gt;, &lt;a href=&quot;https://github.com/joakimk/minimapper&quot;&gt;Minimapper&lt;/a&gt;, &lt;a href=&quot;https://github.com/nulogy/edr&quot;&gt;Edr&lt;/a&gt; and later on &lt;a href=&quot;https://github.com/apotonick/reform&quot;&gt;Reform&lt;/a&gt;. They are all wonderful gems but unfortunately none of them has everything we need.&lt;/p&gt;
&lt;p&gt;
Here are the things we need:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
Decouple domain logic and data persistence.  &lt;/li&gt;
  &lt;li&gt;
Decouple models and forms.  &lt;/li&gt;
  &lt;li&gt;
Support ActiveRecord (or at the very least, ActiveModel) so we can still use many of the awesome gems like &lt;a href=&quot;https://github.com/plataformatec/devise&quot;&gt;Devise&lt;/a&gt;, &lt;a href=&quot;https://github.com/plataformatec/simple_form&quot;&gt;SimpleForm&lt;/a&gt; and &lt;a href=&quot;https://github.com/carrierwaveuploader/carrierwave&quot;&gt;CarrierWave&lt;/a&gt;.  &lt;/li&gt;
  &lt;li&gt;
Support attributes mapped from different data sources (e.g. remote web services from third-party vendors).  &lt;/li&gt;
  &lt;li&gt;
Support lazy loading so that attributes stored on remote data sources will not get triggered upon loading the entities.  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
All things considered, we bit the bullet and started working on &lt;a href=&quot;https://github.com/fredwu/datamappify&quot;&gt;Datamappify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Before I go into details and examples, here is an extremely simplified overview of Datamappify’s architecture:&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/I9GpLds.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
As you can see, Datamappify is loosely based on &lt;a href=&quot;http://martinfowler.com/eaaCatalog/repository.html&quot;&gt;Repository pattern&lt;/a&gt; and &lt;a href=&quot;http://msdn.microsoft.com/en-au/library/ff649505.aspx&quot;&gt;Entity Aggregation pattern&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Datamappify has three main design goals:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
To utilise the powerfulness of existing ORMs so that using Datamappify doesn’t interrupt too much of your current workflow. For example, Devise would still work if you use it with a UserAccount ActiveRecord model that is attached to a User entity managed by Datamappify.  &lt;/li&gt;
  &lt;li&gt;
To have a flexible entity model that works great with dealing with form data. For example, SimpleForm would still work with nested attributes from different ORM models if you map entity attributes smartly in your repositories managed by Datamappify.  &lt;/li&gt;
  &lt;li&gt;
To have a set of data providers to encapsulate the handling of how the data is persisted. This is especially useful for dealing with external data sources such as a web service. For example, by calling UserRepository.save(user), certain attributes of the user entity are now persisted on a remote web service. Better yet, dirty tracking and lazy loading are supported out of the box!  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
You can read more about Datamappify in the project’s &lt;a href=&quot;https://github.com/fredwu/datamappify/blob/master/README.md&quot;&gt;README&lt;/a&gt;. For this blog post I will focus on how we use Datamappify in our Rails application. We are still early days in our application development and Datamappify still has quirks and issues, but I am hoping this post will illustrate some of the key benefits of Datamappify.&lt;/p&gt;
&lt;h3&gt;
Getting Started&lt;/h3&gt;
&lt;p&gt;
Getting started with using Datamappify is really easy. We simply include it in the &lt;code class=&quot;inline&quot;&gt;Gemfile&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;gem &apos;datamappify&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
To keep things organised, we put entities and repositories in their respective directories under &lt;code class=&quot;inline&quot;&gt;app&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://cdn.persumi.com/uploads/images/posts/1ee22517-8bfc-676a-b1f2-ce61dc92750f/imported/img/posts/old/tumblr_inline_mp1vigkh0f1qz4rgp.png&quot; alt=&quot;&quot; /&gt;
&lt;/p&gt;
&lt;h3&gt;
Entities&lt;/h3&gt;
&lt;p&gt;
The reason we wanted Datamappify to utilise existing ORMs like ActiveRecord, is so that we could still use gems like Devise.&lt;/p&gt;
&lt;p&gt;
So, we have a &lt;code class=&quot;inline&quot;&gt;UserAccount&lt;/code&gt; model that handles authentication:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class UserAccount &lt; ActiveRecord::Base
  devise :database_authenticatable,
          :recoverable, :rememberable, :trackable, :validatable
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;UserAccount&lt;/code&gt; has one and only one purpose - user account authentication. Other user behaviours would be contained in either the &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt; entity itself or service objects. Speaking of the &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt; entity, it looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class User
  include Datamappify::Entity

  attr_accessor :user_account

  attribute :account_username, String
  attribute :account_email, String
  attribute :first_name, String
  attribute :last_name, String
  attribute :activated, Boolean, :default =&gt; true

  attributes_from Contact, prefix_with: :work

  validates :first_name, presence: true
  validates :last_name, presence: true

  references :agency

  def full_name
    &quot;#{first_name} #{last_name}&quot;
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
We include &lt;code class=&quot;inline&quot;&gt;Datamappify::Entity&lt;/code&gt; in the &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt; class to make it an entity. We set the &lt;code class=&quot;inline&quot;&gt;:user_account&lt;/code&gt; accessor is so that we could attach the &lt;code class=&quot;inline&quot;&gt;UserAccount&lt;/code&gt; object onto the entity.&lt;/p&gt;
&lt;p&gt;
The &lt;code class=&quot;inline&quot;&gt;attribute&lt;/code&gt; DSL is from &lt;a href=&quot;https://github.com/solnic/virtus&quot;&gt;Virtus&lt;/a&gt; - we get attribute type coercion for free, awesome!&lt;/p&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;attributes_from&lt;/code&gt; is a DSL provided by Datamappify - it essentially “mounts” all the attributes from another entity, in this case the &lt;code class=&quot;inline&quot;&gt;Contact&lt;/code&gt; entity, which looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class Contact
  include Datamappify::Entity

  attribute :email, String
  attribute :phone_number, String
  attribute :fax_number, String

  validates :phone_number, presence: true
  validates :fax_number, presence: true
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
All the attributes and validation rules from &lt;code class=&quot;inline&quot;&gt;Contact&lt;/code&gt; are now “mounted” on &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt;. &lt;code class=&quot;inline&quot;&gt;attributes_from Contact, prefix_with: :work&lt;/code&gt; is equivalent to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;attribute :work_email, String
attribute :work_phone_number, String
attribute :work_fax_number, String

validates :work_phone_number, presence: true
validates :work_fax_number, presence: true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Validation DSL is provided by &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveModel/Validations.html&quot;&gt;ActiveModel::Validations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;references :agency&lt;/code&gt; is a convenient DSL provided by Datamappify. It is equivalent to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;attr_accessor :agency

attribute :agency_id, Integer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Now that we have entities, we need a way to retrieve and store them. For that we need repositories.&lt;/p&gt;
&lt;h3&gt;
Repositories&lt;/h3&gt;
&lt;p&gt;
Here is the user repository:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class UserRepository
  include Datamappify::Repository

  for_entity User

  default_provider :ActiveRecord

  map_attribute :account_username, &apos;ActiveRecord::UserAccount#username&apos;
  map_attribute :account_email, &apos;ActiveRecord::UserAccount#email&apos;

  map_attribute :work_email, &apos;ActiveRecord::Contact#email&apos;
  map_attribute :work_phone_number, &apos;ActiveRecord::Contact#phone_number&apos;
  map_attribute :work_fax_number, &apos;ActiveRecord::Contact#fax_number&apos;
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Similarly to an entity, we include &lt;code class=&quot;inline&quot;&gt;Datamappify::Repository&lt;/code&gt; to make the class a repository. We specify &lt;code class=&quot;inline&quot;&gt;for_entity&lt;/code&gt; to link the repository to an entity, and &lt;code class=&quot;inline&quot;&gt;default_provider&lt;/code&gt; to use a specific data provider for unmapped attributes.&lt;/p&gt;
&lt;p&gt;
Unmapped attributes are the ones not specified in &lt;code class=&quot;inline&quot;&gt;map_attribute&lt;/code&gt;, in this case they are &lt;code class=&quot;inline&quot;&gt;first_name&lt;/code&gt;, &lt;code class=&quot;inline&quot;&gt;last_name&lt;/code&gt; and &lt;code class=&quot;inline&quot;&gt;activated&lt;/code&gt;. Unmapped attributes are actually automatically mapped by Datamappify, so the user repository essentially does this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;map_attribute :first_name, &apos;ActiveRecord::User#first_name&apos;
map_attribute :last_name, &apos;ActiveRecord::User#last_name&apos;
map_attribute :activated, &apos;ActiveRecord::User#activated&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The first argument of &lt;code class=&quot;inline&quot;&gt;map_attribute&lt;/code&gt; is the name of the attribute from the &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt; entity (e.g. &lt;code class=&quot;inline&quot;&gt;:first_name&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;
The second argument is a string containing three things:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
&lt;code class=&quot;inline&quot;&gt;ActiveRecord&lt;/code&gt; is the data provider.  &lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;inline&quot;&gt;::User&lt;/code&gt; is the ActiveRecord model class.  &lt;/li&gt;
  &lt;li&gt;
&lt;code class=&quot;inline&quot;&gt;#first_name&lt;/code&gt; is the ActiveRecord attribute from the model class.  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Even though the &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt; entity is a representation of a user on the domain level, the underlying data structure does not necessary have to be. As you can see from the user repository example, we are mapping &lt;code class=&quot;inline&quot;&gt;:account_username&lt;/code&gt; and &lt;code class=&quot;inline&quot;&gt;:account_email&lt;/code&gt; to the &lt;code class=&quot;inline&quot;&gt;UserAccount&lt;/code&gt; ActiveRecord model we’ve seen before. And we have a bunch of contact details attributes mapped to the &lt;code class=&quot;inline&quot;&gt;Contact&lt;/code&gt; ActiveRecord model.&lt;/p&gt;
&lt;p&gt;
The database schema therefore looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;create_table &quot;contacts&quot;, force: true do |t|
  t.string &quot;email&quot;
  t.string &quot;phone_number&quot;
  t.string &quot;fax_number&quot;
  t.integer &quot;user_id&quot;
end

create_table &quot;user_accounts&quot;, force: true do |t|
  t.string &quot;username&quot;, default: &quot;&quot;, null: false
  t.string &quot;email&quot;, default: &quot;&quot;, null: false
  t.string &quot;encrypted_password&quot;, default: &quot;&quot;, null: false
  t.string &quot;reset_password_token&quot;
  t.datetime &quot;reset_password_sent_at&quot;
  t.datetime &quot;remember_created_at&quot;
  t.integer &quot;sign_in_count&quot;, default: 0
  t.datetime &quot;current_sign_in_at&quot;
  t.datetime &quot;last_sign_in_at&quot;
  t.string &quot;current_sign_in_ip&quot;
  t.string &quot;last_sign_in_ip&quot;
  t.integer &quot;user_id&quot;
  t.datetime &quot;created_at&quot;
  t.datetime &quot;updated_at&quot;
end

create_table &quot;users&quot;, force: true do |t|
  t.string &quot;first_name&quot;
  t.string &quot;last_name&quot;
  t.boolean &quot;activated&quot;
  t.integer &quot;agency_id&quot;
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Note that because the &lt;code class=&quot;inline&quot;&gt;Contact&lt;/code&gt; entity is mounted on the &lt;code class=&quot;inline&quot;&gt;User&lt;/code&gt; entity, we need a foreign key &lt;code class=&quot;inline&quot;&gt;user_id&lt;/code&gt; in the &lt;code class=&quot;inline&quot;&gt;contacts&lt;/code&gt; table to link them.&lt;/p&gt;
&lt;h4&gt;
Data providers&lt;/h4&gt;
&lt;p&gt;
Because we are allowed to specify a data provider (i.e. &lt;code class=&quot;inline&quot;&gt;ActiveRecord&lt;/code&gt;) for each attribute, we can map attributes to entirely different data providers! For instance, we could have:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;map_attribute :first_name, &apos;ActiveRecord::User#first_name&apos;
map_attribute :last_name, &apos;ActiveRecord::User#last_name&apos;
map_attribute :activated, &apos;Sequel::UserActivation#activated&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Now the &lt;code class=&quot;inline&quot;&gt;activated&lt;/code&gt; attribute is mapped to the &lt;code class=&quot;inline&quot;&gt;UserActivation&lt;/code&gt; Sequel model. This powerful feature would allow us to develop data providers that communicate with remote web services. :)&lt;/p&gt;
&lt;h4&gt;
Repository APIs&lt;/h4&gt;
&lt;p&gt;
Datamappify provides a bunch of APIs for retrieving and storing data. These APIs are being developed as needed during our application development.&lt;/p&gt;
&lt;p&gt;
For instance, to find a particular user entity by ID:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;user = UserRepository.find(1)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
To get all the users:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;users = UserRepository.all&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
To search for users:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;users = UserRepository.find(:first_name =&gt; &apos;Fred&apos;, :activated =&gt; true)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
To save a user:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;UserRepository.save(user)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
To delete a user:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;UserRepository.destroy(user)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
There are some limitations for certain APIs, you can &lt;a href=&quot;https://github.com/fredwu/datamappify/blob/master/README.md#repository-apis&quot;&gt;read more about them here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
When saving an entity, because Datamappify has an internal pool for tracking dirty attributes, only those dirty attributes will get saved.&lt;/p&gt;
&lt;p&gt;
Also, Datamappify supports attribute lazy loading, all we have to do is to tell our entity to become lazy aware:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class User
  include Datamappify::Entity
  include Datamappify::Lazy
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Once an entity is lazy aware, a repository will inject the lazy loading mechanism onto the entity when it retrieves such entity (via &lt;code class=&quot;inline&quot;&gt;find&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;
Both repositories and entities support inheritance, again, you may read more about them in the &lt;a href=&quot;https://github.com/fredwu/datamappify/blob/master/README.md&quot;&gt;project’s README&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
Putting Things Together With A Controller&lt;/h3&gt;
&lt;p&gt;
Remember we have the &lt;code class=&quot;inline&quot;&gt;UserAccount&lt;/code&gt; for authentication? So how does that work? Well, here’s the piece of code in our application controller:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class ApplicationController &lt; ActionController::Base
  before_filter :authenticate_user_account!

  private

  def current_user
    unless current_user_account.blank?
      @current_user ||= UserRepository.find(current_user_account.user_id)
    end
  end

  helper_method :current_user
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Not too different from the normal Devise workflow hey? ;)&lt;/p&gt;
&lt;h3&gt;
Forms&lt;/h3&gt;
&lt;p&gt;
Web applications typically have lots of forms - ours is no different. It turns out, Datamappify can help build form objects too!&lt;/p&gt;
&lt;p&gt;
Here’s the view portion of one of our forms (we use &lt;a href=&quot;https://github.com/slim-template/slim&quot;&gt;Slim&lt;/a&gt; templates):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;# our standard form layout

= simple_form_for submission_target, url: submission_path, signed: true do |f|

  = yield(f)

  .form-actions
    .pull-left
      - if archivable? &amp;&amp; resource.persisted?
        = link_to &apos;Archive&apos;, &apos;#&apos;, method: :delete, class: &apos;btn-archive&apos;

    = f.submit &apos;Save&apos;
    = link_to &apos;Cancel&apos;, cancel_path

# actual form content

= render layout: &apos;forms/resource&apos; do |f|
  h3 Account Details
  .row-fluid
    .span4 = f.input :account_type, collection: BankAccount::ACCOUNT_TYPES.invert
    .span4 = f.input :account_code
    .span4 = f.input :account_name
  .row-fluid
    .span4 = f.input :account_number
    .span4 = f.input :bank_name
    .span4 = f.input :bank_branch
  .row-fluid
    .span4 = f.input :bank_bsb, label: &quot;Bank BSB&quot;
    .span4 = f.input :activated, as: :boolean

  h3 Branch Details
  .row-fluid
    .span4 = f.input :branch_address_line_1, label: &quot;Address 1&quot;
    .span4 = f.input :branch_address_line_2, label: &quot;Address 2&quot;
    .span4 = f.input :branch_address_line_3, label: &quot;Address 3&quot;
  .row-fluid
    .span4 = f.input :branch_state, label: &quot;State&quot;
    .span4 = f.input :branch_postcode, label: &quot;Postcode&quot;
    .span4
      = f.input :branch_country_code, label: &quot;Country&quot; do
        = f.country_select :branch_country_code, [&apos;au&apos;, &apos;us&apos;, &apos;gb&apos;], value: &apos;au&apos;
      - f.add_signed_fields :branch_country_code
  .row-fluid
    .span4 = f.input :branch_phone_number, label: &quot;Phone number&quot;
    .span4 = f.input :branch_fax_number, label: &quot;Fax number&quot;

  h3 Merchant Details
  .row-fluid
    .span4 = f.input :merchant_number
    .span4 = f.input :merchant_name
    .span4 = f.input :merchant_address
  .row-fluid
    .span4 = f.input :merchant_biller_code, label: &quot;Biller code&quot;
    .span4 = f.input :merchant_bpay_method, collection: Merchant::BPAY_METHODS.invert, label: &quot;BPAY method&quot;

  h3 Payment Details
  .row-fluid
    .span4 = f.input :payment_number
    .span4 = f.input :payment_merchant, label: &quot;Merchant description&quot;
    .span4 = f.input :payment_reference_type, collection: PaymentAccount::REFERENCE_TYPES.invert, label: &apos;Reference type&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can see, it’s a form containing details from bank account, branch address, branch contact information, merchant and payment. And indeed we do have &lt;code class=&quot;inline&quot;&gt;bank_accounts&lt;/code&gt;, &lt;code class=&quot;inline&quot;&gt;addresses&lt;/code&gt;, &lt;code class=&quot;inline&quot;&gt;contacts&lt;/code&gt;, &lt;code class=&quot;inline&quot;&gt;merchants&lt;/code&gt; and &lt;code class=&quot;inline&quot;&gt;payment_accounts&lt;/code&gt; tables in our database. Yet, the form still remains flat-structured and submits via &lt;code class=&quot;inline&quot;&gt;simple_form_for&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
This is thanks to our &lt;code class=&quot;inline&quot;&gt;BankAccount&lt;/code&gt; entity and &lt;code class=&quot;inline&quot;&gt;BankAccountRepository&lt;/code&gt; repository:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;class BankAccount
  include Datamappify::Entity
  include Concerns::Archivable

  ACCOUNT_TYPES = {
    &apos;general&apos; =&gt; &apos;General&apos;,
    &apos;trust&apos; =&gt; &apos;Trust&apos;
  }

  attribute :account_type, String
  attribute :account_code, String
  attribute :account_name, String
  attribute :account_number, String
  attribute :bank_name, String
  attribute :bank_branch, String
  attribute :bank_bsb, String
  attribute :activated, Boolean, default: true

  attributes_from Address, prefix_with: :branch
  attributes_from Contact, prefix_with: :branch
  attributes_from Merchant, prefix_with: :merchant
  attributes_from PaymentAccount, prefix_with: :payment

  references :agency

  validates :account_type, Mos::Validation.in(ACCOUNT_TYPES)
  validates :account_code, Mos::Validation::STANDARD_TEXT
  validates :account_name, Mos::Validation::STANDARD_TEXT
  validates :account_number, Mos::Validation::STANDARD_TEXT
  validates :bank_name, Mos::Validation::STANDARD_TEXT
  validates :bank_branch, Mos::Validation::STANDARD_TEXT_OPTIONAL
  validates :bank_bsb, Mos::Validation::BSB
  validates :merchant_bpay_method, Mos::Validation.presence_depend_on(:merchant_biller_code)
  validates :payment_reference_type, Mos::Validation.presence_depend_on(:payment_number)
end

class BankAccountRepository
  include Datamappify::Repository

  for_entity BankAccount

  default_provider :ActiveRecord

  map_attribute :branch_address_line_1, &apos;ActiveRecord::Address#address_line_1&apos;
  map_attribute :branch_address_line_2, &apos;ActiveRecord::Address#address_line_2&apos;
  map_attribute :branch_address_line_3, &apos;ActiveRecord::Address#address_line_3&apos;
  map_attribute :branch_state, &apos;ActiveRecord::Address#state&apos;
  map_attribute :branch_postcode, &apos;ActiveRecord::Address#postcode&apos;
  map_attribute :branch_country_code, &apos;ActiveRecord::Address#country_code&apos;

  map_attribute :branch_phone_number, &apos;ActiveRecord::Contact#phone_number&apos;
  map_attribute :branch_fax_number, &apos;ActiveRecord::Contact#fax_number&apos;
  map_attribute :branch_email, &apos;ActiveRecord::Contact#email&apos;
  map_attribute :branch_website, &apos;ActiveRecord::Contact#website&apos;

  map_attribute :merchant_number, &apos;ActiveRecord::Merchant#number&apos;
  map_attribute :merchant_name, &apos;ActiveRecord::Merchant#name&apos;
  map_attribute :merchant_address, &apos;ActiveRecord::Merchant#address&apos;
  map_attribute :merchant_biller_code, &apos;ActiveRecord::Merchant#biller_code&apos;
  map_attribute :merchant_bpay_method, &apos;ActiveRecord::Merchant#bpay_method&apos;

  map_attribute :payment_number, &apos;ActiveRecord::PaymentAccount#number&apos;
  map_attribute :payment_merchant, &apos;ActiveRecord::PaymentAccount#merchant&apos;
  map_attribute :payment_reference_type, &apos;ActiveRecord::PaymentAccount#reference_type&apos;
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Pretty clean and straightforward. What do you think?&lt;/p&gt;
&lt;h3&gt;
Datamappify - Keeping Your Domain Layer Sane&lt;/h3&gt;
&lt;p&gt;
Datamappify’s concept isn’t new, but there simply isn’t anything in the ruby community that solves everything Datamappify tries to solve.&lt;/p&gt;
&lt;p&gt;
I hope that this post has not only introduced you to Datamappify, but has also made you think about how to make &lt;strong&gt;your&lt;/strong&gt; application’s domain layer more decoupled.&lt;/p&gt;
&lt;p&gt;
Thanks for reading, and if you have any feedback for Datamappify please get in touch with me!&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/datamappify-a-new-take-on-decoupling-domain-form-and-persistence-in-rails</link>
      <title>Datamappify - A New Take on Decoupling Domain, Form and Persistence in Rails</title>
    </item>
    <item>
      <pubDate>Wed, 27 Feb 2013 00:12:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/activerecord-and-db-migration-ate-my-model-attributes</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/activerecord-and-db-migration-ate-my-model-attributes</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
&lt;em&gt;Update: You might also want to check out &lt;a href=&quot;/blog/2010-05-25-rails-tip-model-attributes-not-updating/&quot;&gt;&lt;code class=&quot;inline&quot;&gt;reset_column_information&lt;/code&gt;&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
So a few days ago we started seeing the following errors on our Jenkins builds (swapped with fictional model and attribute names):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NoMethodError:
  undefined method `attack_power=&apos; for #&lt;Ironman:0x00000008525d20&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;attack_power&lt;/code&gt; is a new attribute we recently added to the &lt;code class=&quot;inline&quot;&gt;Ironman&lt;/code&gt; ActiveRecord model.&lt;/p&gt;
&lt;p&gt;
I was baffled, as the table column is clearly there but ActiveRecord couldn’t see it.&lt;/p&gt;
&lt;p&gt;
This weird behaviour is confirmed by debugging the model:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Ironman
# =&gt; Ironman(id: integer, created_at: datetime, updated_at: datetime)

Ironman.column_names
# =&gt; [&quot;id&quot;, &quot;created_at&quot;, &quot;updated_at&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
And by debugging the schema:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;ActiveRecord::Base.connection.structure_dump
# =&gt; &quot;CREATE TABLE `ironmans` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `created_at` datetime NOT NULL,\n `updated_at` datetime NOT NULL,\n `attack_power` int(11) NOT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\n&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
So apparently somehow ActiveRecord ate our &lt;code class=&quot;inline&quot;&gt;attack_power&lt;/code&gt; attribute!&lt;/p&gt;
&lt;p&gt;
After some struggling and head-scratching, finally I’ve discovered that during the migration if we call the &lt;code class=&quot;inline&quot;&gt;Ironman&lt;/code&gt; class, then any subsequent attribute changes to the class will not be recognised by ActiveRecord.&lt;/p&gt;
&lt;p&gt;
It turns out, because we run our test suites by invoking rake tasks:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Rake::Task[&apos;spec:something&apos;].invoke
Rake::Task[&apos;spec:something_else&apos;].invoke&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
And we manually reset our database beforehand too within the same &lt;code class=&quot;inline&quot;&gt;Rakefile&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;Rake::Task[&apos;db:reset&apos;].invoke&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
ActiveRecord will cache its attributes as soon as a model class (&lt;code class=&quot;inline&quot;&gt;Ironman&lt;/code&gt;) is called during the migration.&lt;/p&gt;
&lt;p&gt;
The fix? Simple! Simply use another process to run the database reset:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby language-ruby&quot;&gt;system &apos;rake db:reset&apos;&lt;/code&gt;&lt;/pre&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/activerecord-and-db-migration-ate-my-model-attributes</link>
      <title>ActiveRecord and DB Migration Ate My Model Attributes!</title>
    </item>
    <item>
      <pubDate>Mon, 03 Dec 2012 11:44:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/become-a-better-developer-you-can-video-of-my-rubyconf-china-2012-talk</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/become-a-better-developer-you-can-video-of-my-rubyconf-china-2012-talk</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
It was the first time I presented in front of 400+ people so I was really nervous - I blasted through the talk in under 30 minutes even though I was supposed to talk for 45 minutes, oh well. ;)&lt;/p&gt;
&lt;p&gt;
&lt;code class=&quot;inline&quot;&gt;video: https://www.youtube.com/embed/DeBsmdDmB9A&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;
Also, &lt;a href=&quot;/blog/2012-11-25-become-a-better-developer-you-can-slides-of-my/&quot;&gt;my slides are available too&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
P.S. If you’re located in China, you may &lt;a href=&quot;http://railscasts-china.com/episodes/rubyconf-2012-fred-wu&quot;&gt;view the talk at Railscasts China&lt;/a&gt;.&lt;/p&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/become-a-better-developer-you-can-video-of-my-rubyconf-china-2012-talk</link>
      <title>&quot;Become A Better Developer You Can&quot; - Video of My RubyConf China 2012 Talk</title>
    </item>
    <item>
      <pubDate>Sun, 25 Nov 2012 06:45:00 +0000</pubDate>
      <guid>http://persumi.com/u/fredwu/tech/e/blog/p/an-interview-with-yukihiro-matz-matsumoto</guid>
      <comments>http://persumi.com/u/fredwu/tech/e/blog/p/an-interview-with-yukihiro-matz-matsumoto</comments>
      <category>Blog</category>
      <category>Tech</category>
      <author>ifredwu@gmail.com (Fred Wu)</author>
      <description>&lt;![CDATA[&lt;p&gt;
&lt;em&gt;Update: Please check out &lt;a href=&quot;/blog/2013-06-29-the-future-of-computing-the-future-of-computer/&quot;&gt;this new interview with Matz&lt;/a&gt;, done by Engineer Type.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
A week ago I went to Shanghai, China to attend and to give a talk at &lt;a href=&quot;http://rubyconfchina.org/&quot;&gt;RubyConf China&lt;/a&gt;. The day before the conference’s first day a bunch of us were invited to a VIP dinner where we &lt;a href=&quot;http://www.flickr.com/photos/76172385@N07/8212328817/in/set-72157632083056277/lightbox/&quot;&gt;met with Matz&lt;/a&gt; and got to play with &lt;a href=&quot;http://www.flickr.com/photos/76172385@N07/8213422808/in/set-72157632083056277/lightbox/&quot;&gt;a device running MRuby&lt;/a&gt;. And I heard that earlier on that day Matz was ‘adopted’ by a book publisher to do an interview.&lt;/p&gt;
&lt;p&gt;
I have found the interview (&lt;a href=&quot;http://www.ituring.com.cn/article/17487&quot;&gt;in Chinese&lt;/a&gt;), and found it to be really useful. So I translated it to English. Hope more people will like it. :)&lt;/p&gt;
&lt;p&gt;
On November 16th, 2012 - a day before &lt;a href=&quot;http://rubyconfchina.org/&quot;&gt;RubyConf China&lt;/a&gt;, a Chinese book publisher &lt;a href=&quot;http://www.ituring.com.cn/&quot;&gt;Turing Book&lt;/a&gt; has done an interview with Matz on his new book &lt;em&gt;&lt;a href=&quot;http://www.amazon.co.jp/dp/4822234630/&quot;&gt;The Future of Computing&lt;/a&gt;&lt;/em&gt; as well as about a few topics interested to Chinese readers. &lt;a href=&quot;http://www.ituring.com.cn/article/17487&quot;&gt;The interview&lt;/a&gt; was conducted by &lt;em&gt;The Future of Computing&lt;/em&gt;’s Chinese translator &lt;a href=&quot;http://www.ituring.com.cn/users/86141&quot;&gt;Zi Heng Zhou&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Mr. Matsumoto’s new book &lt;em&gt;The Future of Computing&lt;/em&gt; is published earlier this year and the Chinese version is being translated by yours truly, and that is going to be released some time next year in China. Your last book &lt;em&gt;&lt;a href=&quot;http://www.amazon.co.jp/dp/4822234312/&quot;&gt;The World of Code&lt;/a&gt;&lt;/em&gt; has received high praises amongst the readers in China, so what are the differences between the last and the new book?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; &lt;em&gt;The World of Code&lt;/em&gt; has 14 topics in total, and each topic covers the basics - they covered more breadth than depth. The new book on the other hand has one set topic - thoughts on the emerging technologies in the future, therefore the ground covered would be narrower and more in depth than the last book. On top of that, the new book discusses several things by timescale, such as the history and the changes since the invention of computing, and computing’s impact on our future lives. Therefore it’s the thoughts of both the past and the future. The computing world is changing rapidly, and this book’s purpose is to discuss the direction of computing heading into the future.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Speaking of the history of computing, you have touched on a few things about Moore’s law in the book?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Moore’s law describes the rule of changes over the history of computing hardware. The book discusses not only the changes on computing itself, but also the changes on its surrounding environment.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; On the topic of the evolution of programming languages, Paul Graham said in &lt;em&gt;&lt;a href=&quot;http://paulgraham.com/hundred.html&quot;&gt;The Hundred-Year Language&lt;/a&gt;&lt;/em&gt; that &lt;em&gt;the main branches of the evolutionary tree pass through the languages that have the smallest, cleanest cores&lt;/em&gt;. In the new book you seem to hold a different opinion, can you tell us why? And what’s your take on the evolution of programming languages?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Paul loves Lisp, and Lisp perfectly matches the characteristics of the programming languages described in his essay, and so Paul reckons the programming languages in a hundred years from now will look like Lisp. In reality though, Lisp has been around for over 50 years, and to be honest it isn’t one of the mainstream programming languages. In my opinion this may have been because most programmers don’t find Lisp charming enough. In other words, there is a gap between the so-called “smallest, cleanest cores”, “beautiful” languages and the expectation of programmers. It would be understandable if Lisp’s charm had not been accepted by everyone in a year or two, but for 50+ years it hasn’t reached the mainstream, could it be because it fundamentally does not match our expectation? There is a huge difference between &lt;strong&gt;human friendly&lt;/strong&gt; languages and languages that have &lt;strong&gt;smallest, cleanest cores&lt;/strong&gt; , and I am afraid the gap between them might not close even in a hundred years. As for what future programming languages should look like, I think they should have a runtime model similar to that of Lisp &lt;strong&gt;and&lt;/strong&gt; be easily understandable by humans. All of a sudden, Ruby looks a lot closer to that, doesn’t it?  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Mr. Matsumoto you are the father of Ruby. We know that during the design of a programming language there might be a lot of different choices to be made, e.g. dynamically typed vs statically typed, prototype based vs class based, etc. When you were designing Ruby, what was the most difficult choice you made?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Before Ruby I actually have designed another language when I was in university, and that language was statically typed, similar to Eiffel. I liked statically typed languages, but the language I designed during university was more for academic purposes. Several years later, when I wanted to design a language as a tool I could use, I preferred to have it dynamically typed as I think they were more practical. So I designed Ruby. And I think it was the correct decision - it might not have been the most difficult decision, but it certainly was the biggest decision. Now that the decision of being a dynamic language is made, languages such as Smalltalk, Lisp and to an extent Perl have all had influences on Ruby. One of the features of Ruby is “mixins”, and mixins were not very common at the time Ruby was created. But because I don’t like multiple inheritance, I always believed that there must be an easier way to achieve similar results, so I designed mixins in Ruby.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Looking back, is there anything in Ruby you wish you did differently?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; In the beginning my goal was to replace Perl as my tool therefore I have borrowed many ideas from Perl, such as using the dollar sign ($) to indicate special variables. Looking at it now it seems to be a little bit too much and too similar to Perl. There are a few other things but mainly I think it is too similar to Perl. Back then before the ruby idioms were formed, there were many things that were borrowed from Perl - nowadays I think many of them weren’t necessary thanks to the ruby and rails idioms.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Many believe Ruby’s popularity was because of Ruby on Rails, and you agreed with this in the book. So what do you think made Rails so successful?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; The first and foremost, it benefitted from the rapid growth of the web - almost every software development platform is eyeing on the web field. What was developed using the traditional Client-Server architecture can now be implemented on the web. The number of applications that can be developed for the web has grown, and that’s important. Secondly, Ruby is optimised for easier development and higher development productivity. I think these two reasons combined, is what made Rails so successful.  &lt;/p&gt;
  &lt;p&gt;
Also, Ruby has many powerful features such as meta-programming and extendability via monkey patching. Through these features, basic classes can be enhanced, and DHH created Rails using these powerful features of Ruby. For people who have never touched Ruby, for example those Java programmers who like “inflexible” languages, they will be like, “Huh? You can do that?” - and I think that’s also one of the reasons why Rails is so popular.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; It is said that DHH was going to create a web framework using PHP, but eventually moved to Ruby?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Yes, and I think the reason for that might be the limitation of meta-programming in PHP. After Rails was released there were a bunch of PHP frameworks came out that are inspired by Rails, such as Symfony and CakePHP. PHP however does not have many of the powerful features found in Ruby, and purely from the development perspective I still believe Rails is the more powerful one out of the bunch. By the way, I actually met with DHH before, in Denmark. Back then he hadn’t started learning Ruby yet, perhaps that had a small impact on him too.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Ruby is being used widely for the web, but one hot topic amongst Chinese readers is the development direction of Ruby outside of the web. Any thoughts?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; True, many web based projects use Ruby, for instance web frameworks like Rails and Sinatra, etc. The world of programming however is far beyond simply web, and I have always wanted Ruby to break out from the web to other areas. In the near future, I would like to see Ruby being used in three fields:  &lt;/p&gt;
  &lt;p&gt;
1.  &lt;/p&gt;
  &lt;p&gt;
Scientific computing. In this field, languages like Python, R and Matlab are popular choices. I hope Ruby will soon be one of them. In fact, we are developing a project called SciRuby, and we hope it will help us with the adoption in scientific computing.  &lt;/p&gt;
  &lt;p&gt;
2.  &lt;/p&gt;
  &lt;p&gt;
High performance computing. This is somewhat related to scientific computing - to use super computers for doing computational work. Compared to C++, Ruby indeed is very slow, and that’s why people think Ruby isn’t suitable for doing high performance computing. In University of Tokyo a research student is working on an academic research project that compiles Ruby code to C code before compiling the binary code. The process involves techniques such as type inference, and in optimal scenarios the speed could reach up to 90% of typical hand-written C code. So far there is only a paper published, no open source code yet, but I’m hoping next year everything will be revealed.  &lt;/p&gt;
  &lt;p&gt;
3.  &lt;/p&gt;
  &lt;p&gt;
Embedded systems. For micro devices such as cell phones, medical equipment and robots, Ruby isn’t really suitable due to its memory use and APIs. Therefore we need something that’s more suitable for these embedded systems where memory consumption has to be low and APIs have to be optimised. And that’s what MRuby is designed for.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Twitter is mainly built using Rails, but I read a news recently about the traffic surge during the US president election period and Twitter is now migrating to other platforms to help with the scaling. What’s your view on this?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; There are many reasons I believe. First of all, nobody could have predicted Twitter’s huge success - who would’ve thought a service that essentially provides 140 characters of text for blogging to become one of the largest social networks. During their rapid growth they have added a lot of new features, and I think Ruby has contributed to that - it allowed many new features to be thought and implemented in very short amount of time. Twitter could not have anticipated the traffic it is now handling, so it’s fair to say that they have now hit the limit of their architecture designed from way back.  &lt;/p&gt;
  &lt;p&gt;
To solve the issue, Twitter needs to design a new architecture from the ground up in order to handle the ever increasing traffic. Although, Ruby can still be used for rewriting the architecture (chuckles). More seriously though, when a platform hits its limit, there are a few ways of solving it such as rewriting the architecture and changing to another language/platform, etc. I believe the most effective way is to rewrite the architecture, and this is exactly what Twitter’s been doing. During the rewriting process the Twitter engineers wanted to take on more challenges so they picked Scala. Because Scala is a compiled language it has great performance, so it is a fine choice for the new architecture.  &lt;/p&gt;
  &lt;p&gt;
My opinion is that when your system is still in its growing stage, it is far more important to have the ability to react quickly to changes, and that’s what a highly flexible language such as Ruby offers. Once your system reaches to a point of maturity, stability and success, then to have a new architecture that saves on resources makes sense. Twitter only chose to use Scala for its core components, the web front-end and many of their internal tools are still using Ruby. As a matter of fact, I paid Twitter a visit last month and talked to many of their engineers there - Ruby is still in great use (chuckles).  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Mobile platforms become hotter and hotter in recent years due the increased use of smartphones, tablets and other mobile devices. As far as programming language is concerned, Android uses Java and iOS uses Objective-C. What about scripting languages like Ruby, how do you see them fit in this picture?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; It is no doubt that so far in order to develop for Android you use Java, and for iOS you use Objective-C. But that also creates a huge barrier because you would need to rewrite your application if you wanted to port from one platform to another. Projects like PhoneGap and Titanium try to solve this very issue, via languages such as JavaScript and Lua to offer cross-platform compatibility. For Ruby, there is a project called Rhodes - you can use Ruby to write applications that will run on iOS, Android and Blackberry.  &lt;/p&gt;
  &lt;p&gt;
In the old days, mobile devices are much less powerful than PCs, and if applications can’t run in full speed then they are useless. Nowadays though, mobile devices have gotten significantly faster, and the use of cross-platform frameworks becomes far more practical than ever before. I think this way of developing for mobile platforms will become more and more popular. And by the way, we spoke about MRuby before, and using MRuby for iOS and Android is already underway, hopefully more applications will get developed using MRuby in the near future.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; You mentioned MRuby, and the topic of your keynote presentation tomorrow is Ruby 2.0. Could you talk about MRuby and Ruby 2.0’s highlights a little bit?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; As we discussed earlier, MRuby is designed to run on embedded devices, it does not have everything from Ruby. As a result, many devices which traditionally can’t use Ruby, such as vendor machines, controllers and robots can soon utilise MRuby. Perhaps in a few years time, we could see Ruby used in televisions and cars.  &lt;/p&gt;
  &lt;p&gt;
Ruby 2.0 indicates two messages. Firstly, by next year it will be 20 years since the development of Ruby started. What better version number can there be to celebrate this special moment! Contrary to what it might seem like, in terms of the changes, from 1.9 to 2.0 is not as big as from 1.8 to 1.9. In fact, our goal for 2.0 is to be fully backward compatible with 1.9. Your 1.9 applications should run just fine on 2.0.  &lt;/p&gt;
  &lt;p&gt;
Secondly, Ruby 2.0 does offer a few new features. For instance, use monkey patching to add new or replace features has global effects and it might cause conflicts and bugs. In order to avoid situations like this, Ruby 2.0 limits the scope of monkey patching via Refinements. As bigger teams and bigger projects are adopting Ruby, scoped monkey patching will increasingly show its importance. There are many other features in Ruby 2.0 that are designed to cater for bigger teams and projects.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; As far as I know most of the mainstream programming languages are from America and Europe - though there are Lua from Brazil and Ruby from Japan. You too mentioned this in your book and you said this feels “lonely”. So what is the cause of this, and what can we do about it?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; Well, for Lua you can include it in Europe/America too because Brazil is part of South America (chuckles). In the south eastern Asia region though there is only Ruby, and it is lonely. Europe and America still remain the most powerful regions as far as programming languages go. Asia, although has massive population, does not compete in this regard, that indeed feels lonely.  &lt;/p&gt;
  &lt;p&gt;
I am not sure about other countries, but at least in Japan there are many people working on programming languages, unfortunately other than Ruby none of them are well known. If more people are interested in programming and designing programming languages, there bound to be one or two that’ll break out, right? There is another hurdle in Japan - language. Most Japanese people only speak Japanese and they cannot speak English well. Funnily enough there are programming languages written entirely in Japanese. ( &lt;strong&gt;Zhou:&lt;/strong&gt; In China there also are programming languages written entirely in Chinese.) In China too? I knew it! No matter how interesting these programming languages are, they will never influence anyone beyond the ones in their own country.  &lt;/p&gt;
  &lt;p&gt;
On a side note, I once received an email from an American. He said that you are Japanese, but Ruby looks like English because it’s written in English, why isn’t there any Japanese-written languages? I replied saying that there are, you just don’t know them, and even if you did, you wouldn’t be able to use them.  &lt;/p&gt;
  &lt;p&gt;
In Japan, more and more people are interested in programming, maybe because both online and in my books I always talk about how fun programming can be. Many people are now taking on the challenge of designing new programming languages. Out of these new languages, even only 0.1% of them ever get any success, I think it’s a win. I don’t know how many people want to take on the same challenge in China, Korea and other countries in Asia, but if people could look beyond &lt;em&gt;programming languages are created for us, we just passively accept them&lt;/em&gt;, and think &lt;em&gt;to create a new programming language can also be fun&lt;/em&gt;, then I am sure some of them will succeed.  &lt;/p&gt;
  &lt;p&gt;
Talking about open source projects, not many of them are from Japan, China and Korea, and I think this could be an entry point for many. There are many reasons why this is the case though, for example English is hard to learn… ( &lt;strong&gt;Zhou:&lt;/strong&gt; And GitHub is also difficult to use?) Haha, is GitHub usable in China? ( &lt;strong&gt;Zhou:&lt;/strong&gt; It is, it is…) Oh, that’s not too bad then. But, China’s Great Firewall still has a huge impact, many resources can’t be accessed here, right? ( &lt;strong&gt;Zhou:&lt;/strong&gt; That’s right, for instance the Go programming language’s website is blocked.) Ah really? Is it because it’s made by Google? (Chuckles.) In any case, I think there are still many difficulties to face. Also, in Japan many programmers still spend most of the time at work (to put food on the table), it’s very difficult for them to contribute to open source projects. Ten years ago nobody cares about open source in Japan, but nowadays people start to realise the importance of open source, and the number of open source projects is growing. I believe China will soon follow this pattern as well, I am looking forward to it.  &lt;/p&gt;
  &lt;p&gt;
In the beginning no one knows what will succeed. When I started with Ruby I could not possibly have predicted its success. So I think for a programming language, timing is really important - and you’ll never know until you tried. I think in China there might also be languages that emerge from the right time that will eventually be a global success.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; In the book when you were talking about Dart, you mentioned that the ecological environment is really important for a programming language. So what do we need to do to ensure a good ecological environment?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; From a user’s perspective, the most important thing is what benefits a programming language can offer. Before Rails came along, many Ruby users including myself, believe Ruby is a user-friendly language, and that’s the reason we like to use it. After Rails was born, more and more people like to use Ruby because &lt;em&gt;making websites using Rails is really productive&lt;/em&gt;. So I think if you could communicate to your users what the benefits are by using your new programming language, it will help with its adoption and increase the chance of success.  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
&lt;strong&gt;Zhou:&lt;/strong&gt; Thank you very much Matz! Do you have anything else to say to Chinese programmers?&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
&lt;strong&gt;Matz:&lt;/strong&gt; In the book &lt;em&gt;The World of Code&lt;/em&gt; I have mentioned that programming will likely to develop and evolve in the form of open source. New generations of programming languages and software are likely to emerge as open source projects. People are happy to freely use the software developed by others, and to take from that, and work on your own open source projects and make a little impact on the world - then you would become a world class software engineer. The software engineers I met in China are all very hard working and enjoying learning. I hope more of these people will step up and take on the challenge, and become world class programmers who will make a decent impact.  &lt;/p&gt;
&lt;/blockquote&gt;
]]&gt;</description>
      <link>http://persumi.com/u/fredwu/tech/e/blog/p/an-interview-with-yukihiro-matz-matsumoto</link>
      <title>An Interview with Yukihiro &quot;Matz&quot; Matsumoto</title>
    </item>
  </channel>
</rss>