Matthew Lindfield Seager en Sun, 24 Feb 2019 14:28:03 +1000 Mon, 20 May 2019 14:46:41 +1000 <p>Glenn Vanderburg with a very compelling talk on why &ldquo;engineering&rdquo; is the appropriate name for the science and art of designing and making software development: <a href=""></a></p> <p><img src="" width="600" height="266" alt="" /><img src="" width="600" height="323" alt="" /></p> Sun, 19 May 2019 22:11:41 +1000 <p>Enjoyed reading about in the New Yorker: <a href="">;</a></p> <p>I won&rsquo;t &ldquo;be trapped on a platform that owns everything [I&rsquo;ve] written and is doing everything it can to exploit [my] data and attention&rdquo; 👍</p> Sat, 18 May 2019 21:17:44 +1000 <p><a href="">;</a></p> <p>I went in expecting it to be about Rails and that I’d know most of it already. I was wrong on both counts! It’s mostly about Rack and it really helped me understand what happens in the gap between the web server and Rails!</p> Fri, 17 May 2019 17:30:22 +1000 <p>Logster is a nice nice little gem from the fine folks at Discourse that lets you view your Rails logs in the browser in Development and Production</p> <p><a href="">;</a></p> Fri, 17 May 2019 16:52:24 +1000 <p>I was curious how <code>class​ Test &lt; ActiveRecord::Migration[6.0]</code> actually works under the covers. Three key discoveries were:</p> <ul> <li><code>ActiveRecord::Migration[6.0]</code> gets evaluated</li> <li>Migration has a class method <code>[](version)</code></li> <li>Ruby has syntactic sugar where <code>a[b]</code> is the same as <code>a.[](b)</code></li> </ul> Digging in to Ruby Method Definitions Thu, 16 May 2019 23:12:00 +1000 <p>Today I learned that parentheses are optional in Ruby, even when defining methods, not just when you&rsquo;re calling them.</p> <p>Somehow that got me digging into positional arguments, named arguments and blocks so here&rsquo;s a comprehensive (but pathological) example of defining a method without parentheses but with all 7 possible argument types:</p> <pre><code>def arguments required_positional, optional_positional=2, *other_positionals, another_required_positional, required_keyword:, optional_keyword: 7, another_required_keyword:, **other_keywords, &amp;block puts &quot;required_positional = #{required_positional}&quot; puts &quot;optional_positional = #{optional_positional}&quot; puts &quot;other_positionals = #{other_positionals}&quot; puts &quot;another_required_positional = #{another_required_positional}&quot; puts &quot;required_keyword = #{required_keyword}&quot; puts &quot;optional_keyword = #{optional_keyword}&quot; puts &quot;another_required_keyword = #{another_required_keyword}&quot; puts &quot;other_keywords = #{other_keywords}&quot; 3.times(&amp;block) end arguments 1, 2.0, 3, 4, 5, other_b: 10, another_required_keyword: 8, other_a: 9, required_keyword: 6, other_c: 11 do print 'foo ' end # required_positional = 1 # optional_positional = 2.0 # other_positionals = [3, 4] # another_required_positional = 5 # required_keyword = 6 # optional_keyword = 7 # another_required_keyword = 8 # other_keywords = {:other_b=&gt;10, :other_a=&gt;9, :other_c=&gt;11} # foo foo foo </code></pre> <h3 id="observation-1">Observation 1</h3> <p>You may have noticed that I passed <code>2.0</code> (as a Float) to the <code>optional_positional</code> argument, which defaults to <code>2</code> (as an Integer). I did this because <code>*other_positionals</code> only gets left over arguments. If I omit the <code>2.0</code> (hoping for <code>optional_positional</code> to be set to it&rsquo;s default value of <code>2</code>) then <code>optional_positional</code> greedily grabs the first spare argument (3, in the example below), &ldquo;stealing&rdquo; it from the <code>other_positionals</code> array:</p> <pre><code>arguments 1, 3, 4, 5, other_b: 10, another_required_keyword: 8, other_a: 9, required_keyword: 6, other_c: 11 do print 'bar ' end # required_positional = 1 # optional_positional = 3 # other_positionals = [4] # another_required_positional = 5 # required_keyword = 6 # optional_keyword = 7 # another_required_keyword = 8 # other_keywords = {:other_b=&gt;10, :other_a=&gt;9, :other_c=&gt;11} # bar bar bar </code></pre> <h3 id="observation-2">Observation 2</h3> <p>The <a href="">Ruby docs</a> state that (emphasis mine):</p> <blockquote> <p>Prefixing an argument with * causes any remaining arguments to be converted to an Array.<br /> The array argument <strong>must be the last positional argument</strong>, it must appear before any keyword arguments.</p> </blockquote> <p>As you can see in the examples above, that&rsquo;s not the behaviour we&rsquo;re seeing. I added an additional (required) positional argument after the array argument and Ruby happily accepted it. I&rsquo;m not sure if that&rsquo;s a language bug or a documentation bug but given that it&rsquo;s very un-idiomatic Ruby you will hopefully never see (or write!) this in the wild. Just because you can, doesn&rsquo;t mean you should! :)</p> <h3 id="observation-3">Observation 3</h3> <p>This is basically just a variation of the previous two observations but I&rsquo;ll point it out anyway&hellip; the second required positional argument (<code>another_required_positional</code>) takes precedence over <code>optional_positional</code> and <code>*other_positionals</code>. This makes sense (once you accept the undocumented ability to add additional required positional arguments) but I thought I&rsquo;d mention it anyway. If we only provide two positional arguments they are consumed by the 1st and 4th required arguments, leaving the 2nd at its default value and the 3rd (array) empty:</p> <pre><code>arguments 1, 5, other_b: 10, another_required_keyword: 8, other_a: 9, required_keyword: 6, other_c: 11 do print 'baz ' end # required_positional = 1 # optional_positional = 2 # other_positionals = [] # another_required_positional = 5 # required_keyword = 6 # optional_keyword = 7 # another_required_keyword = 8 # other_keywords = {:other_b=&gt;10, :other_a=&gt;9, :other_c=&gt;11} # baz baz baz </code></pre> <h3 id="observation-4">Observation 4</h3> <p>In case you were wondering, the undocumented behaviour for positional arguments does not hold true for keyword arguments. Adding an additional keyword argument after the keyword hash argument, <code>**other_keywords</code>, causes a syntax error:</p> <pre><code>def faulty_keyword_arguments( required_keyword:, optional_keyword: 'b', **other_keywords, another_required_keyword:) # syntax error, unexpected tLABEL, expecting &amp; or '&amp;' # ...ords, another_required_keyword:) # ... ^ </code></pre> <p>As the message suggests, the only thing allowed here is a block argument (starting with an ampersand).</p> <p>That being said, other than the <code>**other_keywords</code> keyword hash needing to be last in the keyword arguments, there are no restrictions on the order of optional and required keyword arguments. As you can see in the intial example, <code>another_required_keyword</code> is defined after <code>optional_keyword</code>. They do not need to be grouped together like positional arguments do.</p> <h3 id="observation-5">Observation 5</h3> <p>You may be wondering if the old idiom of passing a hash after positional arguments works. This continues to work, but only if you don&rsquo;t use any keyword arguments in the method definition:</p> <pre><code>def final_hash a, b=2, *c, &amp;block puts &quot;a = #{a}&quot; puts &quot;b = #{b}&quot; puts &quot;c = #{c}&quot; end final_hash(1, 2, 3, 4, 5, six: 6, seven: 7, eight: 8) # a = 1 # b = 2 # c = [3, 4, 5, {:six=&gt;6, :seven=&gt;7, :eight=&gt;8}] </code></pre> <p>In the example above there are only 6 arguments. The last three items are a single hash - there are implicit hash braces around them. This means all the elements of the hash must be grouped together at the end. If you try to include a positional argument amongst the hash items you&rsquo;ll get an error about a missing hash rocket <code>=&gt;</code>.</p> <h3 id="observation-6a">Observation 6a</h3> <p>If all you do with the block is call it with <code>yield</code>, you don&rsquo;t need to explicity name the block in the method definition:</p> <pre><code>def inline_implicit_block a, b=2, *c puts &quot;a = #{a}&quot; puts &quot;b = #{b}&quot; puts &quot;c = #{c}&quot; yield self yield self yield self end </code></pre> <h3 id="observation-6b">Observation 6b</h3> <p>If you omit parentheses around the method arguments when calling the method, you can&rsquo;t use the single line block syntax <code>{ print 'foo ' }</code>. This is why the explicit <code>&amp;block</code> examples above have the multiline <code>do</code> and <code>end</code> block syntax. Including the braces lets us use the single line syntax:</p> <pre><code>inline_implicit_block(1, 2, 3, 4, five: 5, six: 6) { print 'qux '} # a = 1 # b = 2 # c = [3, 4, {:five=&gt;5, :six=&gt;6}] # qux qux qux </code></pre> Wed, 15 May 2019 22:15:29 +1000 <p>Mind Blown 🤯</p> <p>⌘E on a Mac copies the selected text to a special clipboard used by Find windows.</p> <p>Instead of ⌘C, ⌘F, ⌘V you can just do ⌘E, ⌘F!!! Saves a keyboard shortcut AND the contents of your clipboard!</p> Tue, 14 May 2019 14:48:44 +1000 <p>Relistening to a recent-ish episode that I had lots of thoughts on (as someone recently and still learning Ruby on Rails)</p> <video controls="controls" playsinline="playsinline" src="" width="640" height="640" poster="" preload="none"></video> Tue, 14 May 2019 14:18:22 +1000 <p>Today I watched a really helpful talk on burnout (<a href=""></a>).</p> <p>VERY slow start but the discussions of Maslach&rsquo;s Mismatches that contribute to burnout (spoiler, it&rsquo;s not just overwork) and the symptoms to watch out for were really helpful.</p> Delivering Value Mon, 13 May 2019 22:23:19 +1000 <blockquote> <p>You don’t have to be better than everyone else. Every doctor in America, save one, is not the best doctor. Every lawyer, save one, is not the best lawyer. Every Rails programmer, save one, is not the best Rails programmer. Being the best isn’t a prerequisite to running a successful business. You need to be capable, and to deliver fantastic value to your customers. That does not require being a ninjedi gurumensch. <strong>A lot of fantastic value can be delivered with capable, workmanlike coding.</strong><br /> <cite>&ndash;Patrick McKenzie - <a href="">;</a></cite></p> </blockquote> <p>I like this framing and the reminder that you don’t have to be the best to add value. I’m keen to start exploring ways I can best add value over the next month or two.</p> Sun, 12 May 2019 22:03:17 +1000 <p>Sounds like RubyKaigi 2019 had some interesting talks and announcements!</p> <p>Bundler isn’t something I think about often but I’d definitely welcome some speed gains when I do use it&hellip;</p> <p><a href=""></a> might be just the ticket!</p> Fri, 10 May 2019 21:40:43 +1000 <p>Enjoying a belated beachside birthday bash by Botany Bay before bed&hellip; then a big run and a buffet breakfast 🙂</p> Exceptionally Ordinary Thu, 09 May 2019 23:11:26 +1000 <p>I have surrounded myself, virtually, with successful creators, developers and entrepreneurs. The blogs I read and the podcasts I listen to are full of people who have found, or sometimes carved out, a niche.</p> <p>Some deliberately chose an under-served area and went deep, gradually building up a reputation and an audience. Others have “laddered up” from one opportunity to another, refining their skills as they go.</p> <p>I look at what nearly all of them do and think to myself, “I could do that”. As best I can tell I am smart, articulate and capable.</p> <p>Capable of writing. Capable of developing. Capable of designing interfaces that make sense. Capable of thinking strategically, weighing risks and making decisions. Capable of learning just about anything. Capable of teaching others.</p> <p>And yet there seems to be one big thing I am incapable of. I am incapable of staying focused on one thing for more than a few weeks. Incapable of coming up with a long term plan and sticking with it. Incapable of mastering a topic once I’ve got the basics (or at best the intermediates) down pat. Incapable of finishing projects without external motivation.</p> <p>I’m a big believer in focusing on your strengths, building them up until you stand out. And yet I wonder, are there some weaknesses that are too big to ignore? Can a big enough weakness hamstring a person, negating any strengths. Should I focus on my strengths or try to overcome my weaknesses?</p> <p>But maybe it’s a moot point. Perhaps both approaches require a level of determination and grit that I’m not capable of.</p> <p>And so I drift. Accumulating shallow learnings. A jack of a great many IT trades. A master of none.</p> <p>But that’s okay isn’t it? Not everyone can be a master. There are a lot of people happily existing at levels below master. There‘s hobbyists. Amateurs. Prosumers. Juniors. Apprentices. Professionals. The proficient. The competent. The ordinary.</p> <p>Perhaps I need to stop surrounding myself with the exceptional. They are, after all, exceptions. Maybe I need to settle for being ordinary.</p> <p>Or maybe I need to look for different opportunities. To look for people or places where versatility is what’s needed. Perhaps that’s on smaller teams that don’t have the headroom for exceptional experts? Or finding a partner with complimentary strengths and weaknesses?</p> <p>I’m not sure what the answer is. I’m not even sure I’ve figured out what the question is.</p> Wed, 08 May 2019 22:18:23 +1000 <p>Looks like the (unedited?) videos for Railsconf 2019 are up for the 1st and 2nd of May&hellip;</p> <p><a href="">;</a></p> <p><a href="">;</a></p> <p>Makes Rubyconf AU 2019 stand out even more for getting the edited videos up the same day as the talks!!!</p> Tue, 07 May 2019 19:55:31 +1000 <p>Good article on delegating (technically forwarding) in Standard Ruby, in Rails or with a third party gem for more control:</p> <p><a href="">;</a></p> Tue, 07 May 2019 09:46:30 +1000 <p>Today I learned Transport NSW has been trialling on-demand public transport!!! Looks like a local but public Uber Pool to get people the last (or first) &ldquo;mile&rdquo; from/to existing public transport. Very cool!</p> <p><a href="">;</a></p> Sun, 05 May 2019 21:45:38 +1000 <p>I’ve never developed for Android, I‘ve never tried “Reactive” programming and I’ve only used Java in uni classes but I enjoyed reading <a href="">;</a></p> <p>The basic concepts reminded me a little of Key-Value Observing in Cocoa on Mac</p> Lesson on Learning Sat, 04 May 2019 16:12:11 +1000 <p>Just found some old notes I took about learning, although I’m not sure of the context. All of it looks useful but the things I highlighted are still things I need to learn.</p> <h1 id="self-learning-is-not-a-sprint">Self-learning is not a Sprint</h1> <h2 id="pre-requisite-concepts">Pre-requisite concepts</h2> <ul> <li>prodigy myth (highlighted) vs growth mindset</li> <li>grit: develop it like a muscle</li> <li>be willing to look/be stupid</li> <li>set deadlines</li> </ul> <h2 id="strategies">Strategies</h2> <ul> <li>small steps</li> <li>don’t ignore mistakes</li> </ul> <h2 id="self-study-techniques">Self-study techniques</h2> <ul> <li>a few (15) minutes each day</li> </ul> Fri, 03 May 2019 17:27:29 +1000 <p>Good post (as usual) about Microsoft, Zoom and Slack by Ben Thompson: <a href="">;</a></p> <p>If he is correct, I don’t think Microsoft will be winning any new customers with Teams. It’s clunky, painful and feels “enterprisey”</p> Campaign Monitor API Wed, 01 May 2019 22:13:49 +1000 <p>I was working with the Campaign Monitor API (<a href=""></a>) today.</p> <p>It works but I don’t love that their gem (<a href=""></a>) keeps returning Hashie Mashes instead of “real” Ruby objects. I might be missing something but I kept having to use parts of the Mash to fetch additional Mashes which then contained the data I was after. It would be nice if I could retrieve the “parent” object and then lazily load child objects as I access them.</p> <p>On that note, the property names were quite inconsistent. Sometimes they would be ruby-like but then other times I’d have to write things like <code>;:Name)</code> or <code>client_ref.ClientID</code>.</p> <p>Lastly, I didn’t like that the API offers almost nothing in the way of filtering or searching when retrieving results. It felt like every time I wanted to do anything I had to iterate through a whole list (possibly across multiple pages) until I found the result I was after.</p> <p>Maybe I’m spoiled by how developer friendly most Ruby code is but it felt a little like this API and the gem were just slapped together so they could tick off “RESTful API” and “Ruby wrapper” on their feature list checkboxes but without really thinking about the end user of the software.</p> Tue, 30 Apr 2019 21:14:41 +1000 <p>📚 I ended up enjoying the Fire Sermon so much I read the next two in quick succession!</p> <p>Dark at times, but believable and compelling! Glad I read them!</p> <p><a href="">;</a></p> Tue, 30 Apr 2019 21:11:45 +1000 <p>I enjoyed the latest episode of Without Fail, gave some good insight into how Facebook became what it is</p> <p><a href="">;</a></p> Sun, 28 Apr 2019 21:56:58 +1000 <p>I’m really enjoying listening to Build Your SaaS. The latest episode on pricing and why “charge more” is good general advice (but only general advice) was nuanced and thought provoking!</p> <p><a href="">;</a></p>