<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Will Lawrence</title>
    <description>The latest articles on DEV Community by Will Lawrence (@williamlawrence).</description>
    <link>https://dev.to/williamlawrence</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F82376%2Ff8e960d6-3127-4eca-a8d2-39e103af612b.jpg</url>
      <title>DEV Community: Will Lawrence</title>
      <link>https://dev.to/williamlawrence</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/williamlawrence"/>
    <language>en</language>
    <item>
      <title>Using Capybara to test responsive code</title>
      <dc:creator>Will Lawrence</dc:creator>
      <pubDate>Fri, 11 Nov 2022 20:41:21 +0000</pubDate>
      <link>https://dev.to/aha/using-capybara-to-test-responsive-code-4a96</link>
      <guid>https://dev.to/aha/using-capybara-to-test-responsive-code-4a96</guid>
      <description>&lt;p&gt;As more users opt for mobile browsing, &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design"&gt;responsive design&lt;/a&gt; becomes more important — even for applications that are primarily used on a desktop. Responsive design is a key consideration for Aha! Ideas because it's convenient to answer polls and submit ideas using mobile devices. Usually the application behavior between mobile and desktop are the same, just rearranged on the page. But what happens when application behavior is different between devices with different-sized screens? Automated tests are necessary to ensure these different screen behaviors perform as expected in their environments.&lt;/p&gt;

&lt;p&gt;Engineering at Aha! focuses on using and improving &lt;a href="https://github.com/teamcapybara/capybara"&gt;the Capybara test framework&lt;/a&gt;. We have added many helpers and additional functionality to make working with Capybara easy. Testing at mobile widths is another chance to improve our testing tooling. Here is the incremental approach that we used to add mobile testing helpers.&lt;/p&gt;

&lt;h2&gt;
  
  
  First pass
&lt;/h2&gt;

&lt;p&gt;Below, we have an example test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"mobile user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;scenario&lt;/span&gt; &lt;span class="s2"&gt;"user logs in on mobile"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# These labels are specific to mobile widths&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"First name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Last name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test will fail because we aren't resizing to mobile width, so our name labels won't appear. Let's fix that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"mobile user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# resize to mobile width&lt;/span&gt;
  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;375&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;764&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;scenario&lt;/span&gt; &lt;span class="s2"&gt;"user logs in on mobile"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# These labels are specific to mobile widths&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"First name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Last name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an acceptable first pass. Our page is indeed resized for mobile testing. However, it presents three problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It doesn't tell us why we are resizing. The test has that information but it would not be clear out of the test.&lt;/li&gt;
&lt;li&gt;This code isn't particularly reusable because it requires some insight into how Capybara works.&lt;/li&gt;
&lt;li&gt;The test window remains resized for all subsequent tests. This is a subtle problem that will lead to unexpected and intermittent test failures.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using a helper
&lt;/h2&gt;

&lt;p&gt;Let's see how we can fix those three problems. Below is a helper we can use to resize for mobile testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# in spec/support/capybara_helpers.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;with_mobile_width&lt;/span&gt;
  &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;375&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;764&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# resize to mobile&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="c1"&gt;# run the test&lt;/span&gt;
  &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# resize back to default&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then in our test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"mobile user"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;scenario&lt;/span&gt; &lt;span class="s2"&gt;"user logs in on mobile"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with_mobile_width&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
       &lt;span class="c1"&gt;# These labels are specific to mobile widths&lt;/span&gt;
       &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"First name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Last name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution works better. It can be reused, it tells us why we are resizing, and it won't interfere with other tests. But there is still room for improvement.&lt;/p&gt;

&lt;p&gt;We are adding another layering of nesting to the test. If we continue to use it in other places, then we are going to have some deeply nested tests. There is another way we can get this functionality without using this helper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating our configuration
&lt;/h2&gt;

&lt;p&gt;I want to be able to drop a &lt;code&gt;:mobile_width&lt;/code&gt; in our test declaration. This resolves our three problems and won't clutter the tests. Below is an update to our configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# in spec/support/capybara.rb&lt;/span&gt;
&lt;span class="n"&gt;rspec_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Capybara&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current_session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;browser&lt;/span&gt;

  &lt;span class="c1"&gt;# if we have :mobile in test, resize. Otherwise go to default.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:mobile_width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;375&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;764&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are using the &lt;code&gt;before(:each)&lt;/code&gt; hook. This does exactly what it says on the box. Before each test runs, hook into it and perform an action. In this case, we are checking to see if the test has a &lt;code&gt;:mobile_width&lt;/code&gt; key. If it does, run at a mobile width. If it does not, run at the standard width. The test looks a lot cleaner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s2"&gt;"mobile user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:mobile_width&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;scenario&lt;/span&gt; &lt;span class="s2"&gt;"user logs in on mobile"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# These labels are specific to mobile widths&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"First name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Last name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the tests in the mobile user context are now going to run at that width. We have addressed the original three issues. This is reusable, it explains what we are doing to the test, and the mobile width won't leak into other tests. We also don't need to add another layer of testing to our code like we did by adding the &lt;code&gt;with_mobile_width&lt;/code&gt; helper, so the tests remain tidy and sustainable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Aha! is happy, healthy, and hiring. Join us!
&lt;/h3&gt;

&lt;p&gt;This feature took a lot of tinkering and guidance from other engineers. Without such a knowledgeable and helpful team, I would not have arrived at this clean solution. If you want to build lovable software with this talented and growing team, &lt;a href="https://www.aha.io/company/careers/current-openings?category=engineering"&gt;apply to an open role&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>testing</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Math and Ruby: Generating Fibonacci Numbers</title>
      <dc:creator>Will Lawrence</dc:creator>
      <pubDate>Sun, 31 Oct 2021 19:04:48 +0000</pubDate>
      <link>https://dev.to/williamlawrence/generating-fibonacci-numbers-3961</link>
      <guid>https://dev.to/williamlawrence/generating-fibonacci-numbers-3961</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is going to be a little interlude between the the Project Euler problems because the next problem has to do with Fibonacci numbers! &lt;/p&gt;

&lt;p&gt;The Fibonacci sequence is generated with two initial integers, usually 0 and 1, and then adding those two terms to create the next term in the sequence. The sequence continues to infinity by adding the two previous terms in the sequence. They come up in the Project Euler problems pretty frequently because they are mathematically interesting and present some performance issues when generating them.&lt;/p&gt;

&lt;p&gt;This post is going to talk about a three ways to generate Fibonacci numbers, and what the different tradeoffs &lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Recursion
&lt;/h2&gt;

&lt;p&gt;Because of the way the Fibonacci sequence is defined, it lends itself to being generated with a recursive function. Lets take a look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nth_term_recursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nth_term_recursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;nth_term_recursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have our base cases, 0 and 1, the first two terms of the sequence. After that, we keep calling the method until we get to the base case, and then we roll up to the actual value of the term in the sequence that we wanted. This works, and it's a classic.&lt;/p&gt;

&lt;p&gt;However, as we get more into the project Euler problems, we are going to run into some issues with performance. This method runs in &lt;code&gt;O(2^n)&lt;/code&gt; time, which is fine for small values, but is really slow when it comes to large values, say the 10,000th term in the sequence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: Iteration
&lt;/h2&gt;

&lt;p&gt;Using iteration and holding the values in memory, we can speed up the method. Let's take a look.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nth_term&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="n"&gt;next_term&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;next_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;

    &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;next_term&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;fibonacci_terms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method will yield the same results. We start with our base case, and then generate a hash where the key is the index of the term in the sequence, and the value is the value of the term. By using a hash, we can store the terms of the sequence that are needed to generate the term that we want. This gives us a method that operates in &lt;code&gt;O(n)&lt;/code&gt; time, which is a big improvement. If we want, we could even memoize the results so that we could find terms that were already calculated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 3: Binet's Formula
&lt;/h2&gt;

&lt;p&gt;There is actually a way to directly calculate the terms in the Fibonacci sequence, but there is a problem. It can only be used in limited cases (at least on a computer). We can use &lt;a href="https://mathworld.wolfram.com/BinetsFibonacciNumberFormula.html"&gt;Binet's Formula&lt;/a&gt;. However, because of the rounding errors that occur when we take square roots, this method breaks down. Let's take a look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binets_formula&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Binet's Formula is not accurate for n &amp;gt; 70"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;

  &lt;span class="n"&gt;sqrt5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;((((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sqrt5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sqrt5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sqrt5&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that I output a string when we are looking at the terms greater than 70. Lets compare what happen when we use Binet's Formula against our iterative method for the 70th and 71st terms of the Fibonacci sequence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):001:0&amp;gt; Fibonacci.nth_term(70)
=&amp;gt; 190392490709135
irb(main):002:0&amp;gt; Fibonacci.binets_formula(70)
=&amp;gt; 190392490709135
irb(main):003:0&amp;gt; Fibonacci.nth_term(71)
=&amp;gt; 308061521170129
irb(main):004:0&amp;gt; Fibonacci.binets_formula(71)
Binet's Formula is not accurate for n &amp;gt; 70
=&amp;gt; 308061521170130
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we start getting drift between the results, and the result from Binet's formula is no longer accurate.&lt;br&gt;
However, for the terms that are accurate, we can get them in constant time, so that's cool. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For problems that use the Fibonacci sequence, I will likely use the iterative approach since that has a good balance between speed and accuracy, but something tells me that there are even more complex ways to get large Fibonacci numbers in a faster time than &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can checkout the source code for this post &lt;a href="https://github.com/william-lawrence/math-and-ruby/blob/main/helpers/fibonacci.rb"&gt;on my Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ruby</category>
      <category>algorithms</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Math and Ruby: Project Euler Problem 1</title>
      <dc:creator>Will Lawrence</dc:creator>
      <pubDate>Sun, 24 Oct 2021 18:37:45 +0000</pubDate>
      <link>https://dev.to/williamlawrence/math-and-ruby-project-euler-problem-1-57j4</link>
      <guid>https://dev.to/williamlawrence/math-and-ruby-project-euler-problem-1-57j4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is the first post that I am writing in a while, and it's mostly because I wanted to start working through all the problems on &lt;a href="https://projecteuler.net/"&gt;Project Euler&lt;/a&gt;. I wanted to do this for a few reasons. First, they are hard problems, so they are good way to practice. Second, they let me keep my math skills sharp. Third, They ley me practice my ruby.&lt;/p&gt;

&lt;p&gt;This first problem is fun, but we don't get a chance to look at clever mathematical approaches. But we do get to see some of the methods that we have in ruby. &lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The Following Problem was taken from &lt;a href="https://projecteuler.net/problem=1"&gt;Project Euler&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.&lt;br&gt;
Find the sum of all the multiples of 3 or 5 below 1000.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a great problem because it takes a classic problem (FizzBuzz) and adds an extra layer too it. More importantly, it has a single integer result as opposed to an array of integers and strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking it down.
&lt;/h2&gt;

&lt;p&gt;This problem is basically saying that we need to do a few things. First, we need to find all the numbers from 1-999 that are multiples of 3 or 5. Then, we need to sum all those numbers together. This is a pretty straightforward problem. Let's see what we can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt One: Iterative Approach
&lt;/h2&gt;

&lt;p&gt;I remember the first time I was asked to look at FizzBuzz, and the sort of approach that I would take when I first started coding. It would have looked something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a pretty short method, but it certainly has room to improves. When we run this code, we get the following result: &lt;code&gt;233168&lt;/code&gt;. Spoilers, this is the correct answer. But we can get it in a much more ruby way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt Two: Declarative Approach
&lt;/h2&gt;

&lt;p&gt;So the iterative method gets us the correct answer, but can we get there with less code? Yes. If take a more declarative approach and take advantage of ruby's array methods, we can write the following method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;select!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;zero?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;zero?&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this is doing a lot so let's break it down. First we are using &lt;code&gt;*&lt;/code&gt; and a range to create all the values that we need to look at, 1-999. Then we are creating new array by selecting all the value that are multiples of 3 or 5 from the original array. Finally, we find the sum of the newly created array to get our result. The result of this method is &lt;code&gt;233168&lt;/code&gt;, which is the same as the above method. &lt;/p&gt;

&lt;h1&gt;
  
  
  Comparing Methods
&lt;/h1&gt;

&lt;p&gt;Is either of these approaches better? From a stylistic and readability perspective, the second method is probably better, but you need to know how splats, ranges, and array methods work. &lt;/p&gt;

&lt;p&gt;But what about performance? When we benchmark the iterative approach, we get the result in 0.039 milliseconds When we benchmark the declarative approach, we get our result in 0.106 milliseconds. So the iterative approach is a lot quicker. I would need to dive into the implementation details to see why, but my guess is that the declarative method is probably generating a lot of overhead, while the iterative method is just performing the calculations we need.&lt;/p&gt;

&lt;p&gt;What is the fastest way we could achieve this result?&lt;br&gt;
What is the most readable way we could get this result?&lt;br&gt;
And finally, what is the best way?&lt;/p&gt;

&lt;p&gt;You can checkout the source on &lt;a href="https://github.com/william-lawrence/math-and-ruby"&gt;my GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ruby</category>
      <category>algorithms</category>
      <category>programming</category>
    </item>
    <item>
      <title>Maslow's Hierarchy of Needs In An Application</title>
      <dc:creator>Will Lawrence</dc:creator>
      <pubDate>Mon, 20 Jan 2020 00:50:00 +0000</pubDate>
      <link>https://dev.to/williamlawrence/maslow-s-hierarchy-of-needs-in-an-application-dcm</link>
      <guid>https://dev.to/williamlawrence/maslow-s-hierarchy-of-needs-in-an-application-dcm</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;First, thanks for reading! This is my first post here on Dev.&lt;/p&gt;

&lt;p&gt;If you aren’t familiar with &lt;a href="https://en.wikipedia.org/wiki/Maslow%27s_hierarchy_of_needs"&gt;Malsow’s Hierarch of Needs&lt;/a&gt; here's a brief explanation of the theory. There's a hierarchy of what a person needs, and they need to have all the things on one of the tiers before they can start fulfilling the needs on the next tier. Without having your basic physical needs satisfied, you can't have your higher-order needs fulfilled.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you need in application?
&lt;/h2&gt;

&lt;p&gt;Let’s take that and apply it to applications. Let’s assume that you can only have one of the following before you can add another:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Tests&lt;/li&gt;
&lt;li&gt;Readability&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;li&gt;Functionality &lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think that I would probably go in the following order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Functionality--the app should work, right?&lt;/li&gt;
&lt;li&gt;Readability--hopefully a person can read the code.&lt;/li&gt;
&lt;li&gt;Maintainability--the code should be easy to maintain. This falls in line with readability, but has more to do with organization. &lt;/li&gt;
&lt;li&gt;Security--the application should be secure and follow basic security principles.&lt;/li&gt;
&lt;li&gt;Accessibility--the application should be accessible to &lt;em&gt;ALL&lt;/em&gt; users. &lt;/li&gt;
&lt;li&gt;Documentation--the code, as well as any user documentation, exists and is valid. &lt;/li&gt;
&lt;li&gt;Tests--the application has automated testing. This is my passion and it makes me so sad that this falls so low.&lt;/li&gt;
&lt;li&gt;Performance--the application is performant. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Your Turn
&lt;/h2&gt;

&lt;p&gt;How would you rank them?&lt;/p&gt;

&lt;p&gt;What would you add?&lt;/p&gt;

&lt;p&gt;What is missing?&lt;/p&gt;

&lt;p&gt;How did you decide your order?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>healthydebate</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
