<?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>Forem: Touré Holder</title>
    <description>The latest articles on Forem by Touré Holder (@toureholder).</description>
    <link>https://forem.com/toureholder</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%2F423986%2F0bd61aa6-5f8c-4fdd-ba5d-edf4878dd651.jpg</url>
      <title>Forem: Touré Holder</title>
      <link>https://forem.com/toureholder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/toureholder"/>
    <language>en</language>
    <item>
      <title>Should one get good at test-last development before learning TDD?</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Wed, 22 Sep 2021 00:43:19 +0000</pubDate>
      <link>https://forem.com/toureholder/should-one-practice-test-last-development-before-learning-tdd-2o7h</link>
      <guid>https://forem.com/toureholder/should-one-practice-test-last-development-before-learning-tdd-2o7h</guid>
      <description>&lt;p&gt;I'd been writing tests for a while in a test-last development manner before learning how to develop software using the test-driven technique.&lt;/p&gt;

&lt;p&gt;I find that many developers feel daunted by the practice of writing failing tests before writing the implementation/production code to make the tests pass, especially when they have little or no experience writing tests at all.&lt;/p&gt;

&lt;p&gt;Since I can't go back in time and learn software testing using a test-driven development approach, I honestly don't know what it feels like and have thus decided to elicit the opinion of the community :)&lt;/p&gt;

&lt;p&gt;Do you think it's better to introduce someone with no test writing experience to the practice of software testing with TDD right off the bat? Or is it better to learn TDD after becoming familiar with test-last development?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>tdd</category>
      <category>healthydebate</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Creating adaptive layouts with Flutter</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Fri, 02 Jul 2021 11:39:55 +0000</pubDate>
      <link>https://forem.com/toureholder/creating-adaptive-layouts-with-flutter-56oa</link>
      <guid>https://forem.com/toureholder/creating-adaptive-layouts-with-flutter-56oa</guid>
      <description>&lt;p&gt;In this tutorial you'll learn how to easily make a UI layout for your flutter app that adapts to different screen sizes with the &lt;a href="https://pub.dev/packages/adaptive_layout" rel="noopener noreferrer"&gt;&lt;code&gt;adaptive_layout&lt;/code&gt;&lt;/a&gt; package.&lt;/p&gt;

&lt;p&gt;The next few sections show how to build a simple UI that displays a list of movie posters and titles and allows the user to see more details of the movie when they tap an item in the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small screen UI
&lt;/h2&gt;

&lt;p&gt;On small, phone-sized, screens when the user taps an item they will navigate to a different screen with the details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Fsmall_screen_ui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Fsmall_screen_ui.png" title="small screen ui" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Large screen UI
&lt;/h2&gt;

&lt;p&gt;On large screens, when the user taps a list item the details are displayed on the right side of the list and there is no navigation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_better_738.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_better_738.png" title="large screen ui" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Live demo
&lt;/h2&gt;

&lt;p&gt;Even better than an image, &lt;a href="https://flutter-adaptive-layout-tutorial.surge.sh/" rel="noopener noreferrer"&gt;see a live demo of what we'll be building&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's go!
&lt;/h2&gt;

&lt;p&gt;We'll take care of the behavior expected for small screens first, then adapt our implementation for larger screens. These are the steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Create a new app&lt;/li&gt;
&lt;li&gt;2. Provide the data set&lt;/li&gt;
&lt;li&gt;3. Create the model&lt;/li&gt;
&lt;li&gt;4. Create the movie list page&lt;/li&gt;
&lt;li&gt;5. Create the movie detail page&lt;/li&gt;
&lt;li&gt;6. Navigate to the detail screen when an item is tapped&lt;/li&gt;
&lt;li&gt;7. Convert movie list page into home page&lt;/li&gt;
&lt;li&gt;8. Make the home page adaptive with the &lt;code&gt;adaptive_layout&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;9. Display the detail view when an item is tapped on large screens&lt;/li&gt;
&lt;li&gt;BONUS: Make it look a little better on large screens&lt;/li&gt;
&lt;li&gt;BONUS: Tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Create a new app
&lt;/h2&gt;

&lt;p&gt;Go ahead and &lt;code&gt;create&lt;/code&gt; a new flutter app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter create adaptive_layout_example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Provide the data set
&lt;/h2&gt;

&lt;p&gt;We'll be using a hard-coded data set, so we can focus our efforts on the UI layout.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under the &lt;code&gt;lib&lt;/code&gt; folder, create a folder called &lt;code&gt;data&lt;/code&gt; with a file named &lt;code&gt;data.dart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Copy the contents of &lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/tree/main/lib/data/data.dart" rel="noopener noreferrer"&gt;this file&lt;/a&gt; into your file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/f5e4e5592276aeaa7547f722d06187120f7809d3" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Create the model
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;Movie&lt;/code&gt; class with a static function that parses the data into a list of &lt;code&gt;Movie&lt;/code&gt;s and returns the list.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Under the &lt;code&gt;lib&lt;/code&gt; folder, create a folder called &lt;code&gt;model&lt;/code&gt; with a file &lt;code&gt;movie.dart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Paste the following content into the file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'../data/data.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;overview&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;posterPath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;overview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;posterPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="nl"&gt;overview:&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'overview'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="nl"&gt;posterPath:&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'poster_path'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;LARGE_POSTER_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://image.tmdb.org/t/p/w300"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;SMALL_POSTER_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://image.tmdb.org/t/p/w92"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/96096fe65ed390e4e3c7bd979f7c2e890da95ec2" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Create the movie list page
&lt;/h2&gt;

&lt;p&gt;Now let's create a page that will display the list of movies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new folder under &lt;code&gt;lib&lt;/code&gt; called &lt;code&gt;pages&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Within the &lt;code&gt;pages&lt;/code&gt; folder create a file named &lt;code&gt;movie_list_page.dart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;movie_list_page.dart&lt;/code&gt; create two &lt;code&gt;StatelessWidget&lt;/code&gt;s: one called &lt;code&gt;MovieListPage&lt;/code&gt; and another called &lt;code&gt;MovieListView&lt;/code&gt;, with this content.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieListPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MovieListPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getList&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;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Movies'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;MovieListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;movies:&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;onTapItem:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// TODO: Navigate to detail screen&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieListView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;onTapItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MovieListView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTapItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&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;ListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;itemCount:&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&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;ListTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'list_item_&lt;/span&gt;&lt;span class="si"&gt;$index&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;leading:&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SMALL_POSTER_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;posterPath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${movie.title}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;contentPadding:&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;onTap:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;onTapItem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observe that &lt;code&gt;MovieListPage&lt;/code&gt; is a container widget for the presentational &lt;code&gt;MovieListView&lt;/code&gt; widget.&lt;/p&gt;

&lt;p&gt;Now, remove the framework generated &lt;code&gt;MyHomePage&lt;/code&gt; and &lt;code&gt;_MyHomePageState&lt;/code&gt; classes from &lt;code&gt;lib/main.dart&lt;/code&gt; and use &lt;code&gt;MovieListPage()&lt;/code&gt; as the &lt;code&gt;home&lt;/code&gt; widget for the &lt;code&gt;MaterialApp&lt;/code&gt;. The &lt;code&gt;lib/main.dart&lt;/code&gt; file should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&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;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="s"&gt;'Adaptive Layout Tutorial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;theme:&lt;/span&gt; &lt;span class="n"&gt;ThemeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;primarySwatch:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="c1"&gt;// Use `MovieListPage()` as the `home` widget&lt;/span&gt;
      &lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="n"&gt;MovieListPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The list page should now be displayed when the app starts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Fmovie_list_page_326.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Fmovie_list_page_326.png" title="movie list page" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/8e87521759a3f383cd175265cb4cfa9f147d9788" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Create the movie detail page
&lt;/h2&gt;

&lt;p&gt;Now let's create a page that will display more details of a given movie:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Within the &lt;code&gt;pages&lt;/code&gt; folder create a file named &lt;code&gt;movie_detail_page.dart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Similarly, in &lt;code&gt;movie_detail_page.dart&lt;/code&gt; create two &lt;code&gt;StatelessWidget&lt;/code&gt;s: a container widget called &lt;code&gt;MovieDetailPage&lt;/code&gt; and a presentational &lt;code&gt;MovieDetailView&lt;/code&gt; widget, with this content:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieDetailPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MovieDetailPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&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;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;MovieDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieDetailView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MovieDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&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;SingleChildScrollView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;24.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;crossAxisAlignment:&lt;/span&gt; &lt;span class="n"&gt;CrossAxisAlignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;ClipRRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;borderRadius:&lt;/span&gt; &lt;span class="n"&gt;BorderRadius&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;circular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LARGE_POSTER_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;posterPath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mf"&gt;24.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textTheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;headline4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;textAlign:&lt;/span&gt; &lt;span class="n"&gt;TextAlign&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mf"&gt;24.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;overview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textTheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subtitle1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;textAlign:&lt;/span&gt; &lt;span class="n"&gt;TextAlign&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For simplicity, we are just displaying the poster image, title and overview of the movie in the detail view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/e05d2e71c7fee7b0ddbfa2aeac13e536395b7b59" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Navigate to the detail screen when an item is tapped
&lt;/h2&gt;

&lt;p&gt;Update the &lt;code&gt;onTapItem()&lt;/code&gt; callback of the &lt;code&gt;MovieListView&lt;/code&gt; in the &lt;code&gt;MovieListPage&lt;/code&gt; widget, so we can navigate to the detail screen and back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Within the `MovieListPage` widget&lt;/span&gt;
&lt;span class="nl"&gt;onTapItem:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MaterialPageRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MovieDetailPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, our small screen UI is done! You should now be able to navigate to the detail screen and back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Fsmall_screen_ui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Fsmall_screen_ui.png" title="small screen ui" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/427abcb49341d9276fe34506cb842067a501e5e4" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Convert movie list page into home page
&lt;/h2&gt;

&lt;p&gt;As a first step to making our layout adaptive to different screen sizes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert &lt;code&gt;MovieListPage&lt;/code&gt; to a &lt;code&gt;StatefulWidget&lt;/code&gt;. (In VS Code place the cursor on &lt;code&gt;StatelessWidget&lt;/code&gt;, press CTRL/CMD + . and select "Convert to StatefulWidget".)&lt;/li&gt;
&lt;li&gt;For semantic's sake rename it to &lt;code&gt;HomePage&lt;/code&gt; and the file to &lt;code&gt;home_page.dart&lt;/code&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On small screens the &lt;code&gt;HomePage&lt;/code&gt; widget will contain only the &lt;code&gt;MovieListView&lt;/code&gt;. On large screens the &lt;code&gt;HomePage&lt;/code&gt; widget will contain the &lt;code&gt;MovieListView&lt;/code&gt; and the &lt;code&gt;MovieDetailView&lt;/code&gt; side by side. You'll understand why we converted the widget to a &lt;code&gt;StatefulWidget&lt;/code&gt; in just a bit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/a1b006b874539150b5ca681f58f1c0f023030290" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Make the home page adaptive with the &lt;code&gt;adaptive_layout&lt;/code&gt; package
&lt;/h2&gt;

&lt;p&gt;To help us implement us display different layouts on different screen sizes we'll use the &lt;a href="https://pub.dev/packages/adaptive_layout" rel="noopener noreferrer"&gt;&lt;code&gt;adaptive_layout&lt;/code&gt;&lt;/a&gt; package.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install it with
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flutter pub add adaptive_layout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;adaptive_layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.1.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Now in &lt;code&gt;home_page.dart&lt;/code&gt;, import the package:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:adaptive_layout/adaptive_layout.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the &lt;code&gt;body&lt;/code&gt; of the &lt;code&gt;Scaffold&lt;/code&gt; of &lt;code&gt;HomePage&lt;/code&gt; to be an &lt;code&gt;AdaptiveLayout&lt;/code&gt; with a &lt;code&gt;smallLayout&lt;/code&gt; and a &lt;code&gt;largeLayout&lt;/code&gt; like so:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomePage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_HomePageState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_HomePageState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_HomePageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getList&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;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Movies'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="c1"&gt;// Now using an `AdaptiveLayout` as the `body`&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;AdaptiveLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// Provide `MovieListView` as the `smallLayout`&lt;/span&gt;
        &lt;span class="nl"&gt;smallLayout:&lt;/span&gt; &lt;span class="n"&gt;MovieListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;movies:&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;onTapItem:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;MaterialPageRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MovieDetailPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="c1"&gt;// Provide a `Row` as the `largeLayout`&lt;/span&gt;
        &lt;span class="nl"&gt;largeLayout:&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;MovieListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;movies:&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nl"&gt;onTapItem:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="c1"&gt;// TODO: Update detail view to the right&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;'Select a movie from the list on the left to see the details here.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;smallLayout&lt;/code&gt; is just our &lt;code&gt;MovieListView&lt;/code&gt; and the &lt;code&gt;largeLayout&lt;/code&gt; is a 2-column &lt;code&gt;Row&lt;/code&gt; with the &lt;code&gt;MovieListView&lt;/code&gt; in the first &lt;code&gt;Expanded&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;At this point, on small screens the app should have the same behavior as before of navigating to the detail page when a list item is tapped. On large screens we should now see the list on the left-hand side of the screen and the message "Select a movie from the list on the left to see the details here" in the center of the right-hand side of the screen: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_initial_738.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_initial_738.png" title="large screen ui" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, nothing happens when we tap a list item on large screens. Let's tackle that next.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Display the detail view when an item is tapped on large screens
&lt;/h2&gt;

&lt;p&gt;With a few new lines of code in the &lt;code&gt;home_page.dart&lt;/code&gt; file we can display the detail view on the right hand side when an item is tapped on large screens.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a private property of the &lt;code&gt;_HomePageState&lt;/code&gt; of type &lt;code&gt;Movie?&lt;/code&gt; named &lt;code&gt;_selectedMovie&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_HomePageState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_selectedMovie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the &lt;code&gt;onTapItem()&lt;/code&gt; callback of the &lt;code&gt;MovieListView&lt;/code&gt; in the &lt;strong&gt;&lt;code&gt;largeLayout&lt;/code&gt;&lt;/strong&gt; of the &lt;code&gt;AdaptiveLayout&lt;/code&gt; widget to update the &lt;code&gt;_selectedMovie&lt;/code&gt; property with &lt;code&gt;setState&lt;/code&gt;. This is why we converted the widget to a &lt;code&gt;StatefulWidget&lt;/code&gt; a few steps ago.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Within the `largeLayout`&lt;/span&gt;
&lt;span class="nl"&gt;onTapItem:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_selectedMovie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the second &lt;code&gt;Expandable&lt;/code&gt; of the &lt;code&gt;Row&lt;/code&gt; to display the message if &lt;code&gt;_selectedMovie&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt; and the &lt;code&gt;MovieDetailView&lt;/code&gt; otherwise.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;_selectedMovie&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
        &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;'Select a movie from the list on the left to see the details here.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MovieDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;_selectedMovie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And... we're done! 🎉&lt;/p&gt;

&lt;p&gt;On small, phone-sized, screens when the user taps an item they will navigate to a different screen with the details and on larger screens the details are displayed on the right side of the list and there is no navigation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_done_738.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_done_738.png" title="large screen ui" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/5df19896e44c182059598f886bf55660bae37ae5" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  BONUS: Make it look a little better on large screens
&lt;/h2&gt;

&lt;p&gt;To make our app look a little better, let's leave the selected list item highlighted and put a divider line between the list view and the detail view with a few new lines of code in the &lt;code&gt;home_page.dart&lt;/code&gt; file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a new attribute &lt;code&gt;selectedId&lt;/code&gt; attribute to &lt;code&gt;MovieListView&lt;/code&gt;, so it knows which item a selected.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieListView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;onTapItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;selectedId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MovieListView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTapItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;selectedId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the &lt;code&gt;itemBuilder&lt;/code&gt; of the &lt;code&gt;ListView.builder&lt;/code&gt; to wrap the &lt;code&gt;ListTile&lt;/code&gt; in a &lt;code&gt;Container&lt;/code&gt; and give the &lt;code&gt;Container&lt;/code&gt; color if the &lt;code&gt;ListTile&lt;/code&gt;'s movie is the selected one.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;selectedId&lt;/span&gt;
      &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;primaryColor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withOpacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transparent&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;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'list_item_&lt;/span&gt;&lt;span class="si"&gt;$index&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;leading:&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SMALL_POSTER_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;posterPath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;${movie.title}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;contentPadding:&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;onTap:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;onTapItem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the first &lt;code&gt;Expandable&lt;/code&gt; of the &lt;code&gt;Row&lt;/code&gt; in the &lt;code&gt;largeLayout&lt;/code&gt; of the &lt;code&gt;AdaptiveLayout&lt;/code&gt; to provide the selected movie's &lt;code&gt;id&lt;/code&gt; to the &lt;code&gt;MovieListView&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;MovieListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;movies:&lt;/span&gt; &lt;span class="n"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;onTapItem:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_selectedMovie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nl"&gt;selectedId:&lt;/span&gt; &lt;span class="n"&gt;_selectedMovie&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Lastly, let's add a border to the left-hand side of the detail view's &lt;code&gt;Container&lt;/code&gt; with some &lt;code&gt;BoxDecoration&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;decoration:&lt;/span&gt; &lt;span class="n"&gt;BoxDecoration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;border:&lt;/span&gt; &lt;span class="n"&gt;Border&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;left:&lt;/span&gt; &lt;span class="n"&gt;BorderSide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;300&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="nl"&gt;width:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;_selectedMovie&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
        &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="s"&gt;'Select a movie from the list on the left to see the details here.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MovieDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;_selectedMovie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course the sky's the limit with the design, but I think our app is minimally presentable now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_better_738.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftoureholder%2Fflutter_adaptive_layout_tutorial%2Fmain%2Fdocs%2Flarge_screen_ui_better_738.png" title="large screen ui" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/commit/270ee50594899df6456cdf0440257d117bc043ab" rel="noopener noreferrer"&gt;See the changes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  BONUS: Tests
&lt;/h2&gt;

&lt;p&gt;I chose not to TDD this so we could focus on the layout, but you can find &lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial/tree/main/test/" rel="noopener noreferrer"&gt;the tests&lt;/a&gt; here in the source code.&lt;/p&gt;

&lt;p&gt;Note in the tests that I use &lt;code&gt;WidgetTester&lt;/code&gt; to specify a small screen size in a &lt;code&gt;setUp&lt;/code&gt; function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;physicalSizeTestValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AdaptiveLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBreakpoints&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mediumScreenMinWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;devicePixelRatioTestValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and to specify a large screen size like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;physicalSizeTestValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AdaptiveLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBreakpoints&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;largeScreenMinWidth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;devicePixelRatioTestValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Head over the the &lt;a href="https://github.com/toureholder/flutter_adaptive_layout_tutorial" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt; to see the complete source code with a separate commit for each step 😉.&lt;/p&gt;

&lt;p&gt;Congrats on making it to the end and thanks for following along! 👏 ❤️ ⭐ 🦄 🔖&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Does TDD help you to write more SOLID code?</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Fri, 16 Apr 2021 09:50:29 +0000</pubDate>
      <link>https://forem.com/toureholder/does-tdd-have-anything-to-do-with-solid-2cl9</link>
      <guid>https://forem.com/toureholder/does-tdd-have-anything-to-do-with-solid-2cl9</guid>
      <description>&lt;p&gt;It's clear to most that SOLID principles help us to produce more testable code and that unit testing promotes following SOLID principles.&lt;/p&gt;

&lt;p&gt;I'm wondering if driving development through tests (TDD) helps you to follow SOLID principles any more that testing after development.&lt;/p&gt;

&lt;p&gt;What do you think?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>tdd</category>
      <category>healthydebate</category>
    </item>
    <item>
      <title>Does TDD slow you down or help you go faster?</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Fri, 16 Apr 2021 00:20:19 +0000</pubDate>
      <link>https://forem.com/toureholder/does-tdd-slow-you-down-or-help-you-go-faster-1bel</link>
      <guid>https://forem.com/toureholder/does-tdd-slow-you-down-or-help-you-go-faster-1bel</guid>
      <description>&lt;p&gt;I have the impression that I spend less time doing manual testing and "thinking" about what to test when I do TDD. But I've heard very different opinions on this.&lt;/p&gt;

&lt;p&gt;For those of you who've done a fair share of both &lt;strong&gt;test-driven development&lt;/strong&gt; and &lt;strong&gt;test-last development&lt;/strong&gt;, do you perceive any difference in the speed of getting your code to production?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>tdd</category>
      <category>healthydebate</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Removing sensitive data from your Git history with BFG</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Wed, 07 Apr 2021 09:55:20 +0000</pubDate>
      <link>https://forem.com/toureholder/removing-sensitive-data-from-your-git-history-with-bfg-4ni4</link>
      <guid>https://forem.com/toureholder/removing-sensitive-data-from-your-git-history-with-bfg-4ni4</guid>
      <description>&lt;p&gt;Here's how to remove sensitive data, like certificate files or passwords in your files, from your git repo and history with &lt;a href="https://rtyley.github.io/bfg-repo-cleaner/"&gt;BFG Repo-Cleaner&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Remove the sensitive files and secrets from your code and commit changes
&lt;/h2&gt;

&lt;p&gt;Note that, by default, BFG doesn't modify the contents of your latest commit. So, remove the sensitive files and secrets from your code, commit the changes and ensure that your latest commit is clean with none of the undesired data in it before proceeding. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install BFG
&lt;/h2&gt;

&lt;p&gt;You can download a JAR from the &lt;a href="https://rtyley.github.io/bfg-repo-cleaner/"&gt;site&lt;/a&gt;. If you're on Mac, &lt;code&gt;brew install bfg&lt;/code&gt; should suffice.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Clone a fresh copy of your repo, using the --mirror flag:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git clone &lt;span class="nt"&gt;--mirror&lt;/span&gt; git://example.com/my-repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Clean sensitive files
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;--delete-files&lt;/code&gt; to nuke files in your repo history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Examples&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;bfg &lt;span class="nt"&gt;--delete-files&lt;/span&gt; certificate.p12 my-repo.git
&lt;span class="nv"&gt;$ &lt;/span&gt;bfg &lt;span class="nt"&gt;--delete-files&lt;/span&gt; keystore.jks my-repo.git
&lt;span class="nv"&gt;$ &lt;/span&gt;bfg &lt;span class="nt"&gt;--delete-files&lt;/span&gt; id_&lt;span class="o"&gt;{&lt;/span&gt;dsa,rsa&lt;span class="o"&gt;}&lt;/span&gt; my-repo.git
&lt;span class="nv"&gt;$ &lt;/span&gt;bfg &lt;span class="nt"&gt;--delete-files&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.&lt;span class="o"&gt;{&lt;/span&gt;txt,log&lt;span class="o"&gt;}&lt;/span&gt; my-repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the specified name matches on file name, not on path within repo. So &lt;code&gt;$ bfg --delete-files path/to/certificate.p12 my-repo.git&lt;/code&gt; won't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Clean sensitive strings
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;--replace-text&lt;/code&gt; to clean strings from your repo history. Each string will be rewritten as "***REMOVED***" by default. This is a two-step process.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1. Create a file with a new line for each string you want to remove
&lt;/h3&gt;

&lt;p&gt;Create a simple text file however you'd like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"password123"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; passwords.txt
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"123password"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; passwords.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.2. Run the command
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;bfg --replace-text&lt;/code&gt; referencing the file you just created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;bfg &lt;span class="nt"&gt;--replace-text&lt;/span&gt; passwords.txt my-repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Take a look at your new history
&lt;/h2&gt;

&lt;p&gt;Enter the folder of the git repo and make sure your history has been updated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-repo.git

&lt;span class="c"&gt;# Use git commands to examine the history&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git log
&lt;span class="nv"&gt;$ &lt;/span&gt;git show HEAD
&lt;span class="nv"&gt;$ &lt;/span&gt;git show HEAD~1
&lt;span class="nv"&gt;$ &lt;/span&gt;git show d89bb58
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You won't see the physical files of your working tree if you list files in this directory, since we did a bare/mirror clone, in case you were wondering.)&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Strip out the unwanted dirty data
&lt;/h2&gt;

&lt;p&gt;Once satisfied with the state of the history, clean up those sensitive files, which git now considers unnecessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git reflog expire &lt;span class="nt"&gt;--expire&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;now &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git gc &lt;span class="nt"&gt;--prune&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;now &lt;span class="nt"&gt;--aggressive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Push
&lt;/h2&gt;

&lt;p&gt;Finally, once you're happy with the updated state of your repo, push it back up and you're done!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're with a team have everyone ditch their old copies of the repo and do fresh clones.&lt;/p&gt;

&lt;p&gt;Thanks for following along. Cheers!&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>dyld: Symbol not found: _ffi_prep_closure_loc</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Mon, 03 Aug 2020 00:48:12 +0000</pubDate>
      <link>https://forem.com/toureholder/dyld-symbol-not-found-ffiprepclosureloc-1b85</link>
      <guid>https://forem.com/toureholder/dyld-symbol-not-found-ffiprepclosureloc-1b85</guid>
      <description>&lt;p&gt;Did a regular &lt;code&gt;flutter run&lt;/code&gt; targeting my iPhone simulator today and this craziness showed up on my screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Error output from CocoaPods:
↳
    dyld: lazy symbol binding failed: Symbol not found: _ffi_prep_closure_loc
      Referenced from: /Users/toure/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle
      Expected &lt;span class="k"&gt;in&lt;/span&gt;: /usr/lib/libffi.dylib

    dyld: Symbol not found: _ffi_prep_closure_loc
      Referenced from: /Users/toure/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle
      Expected &lt;span class="k"&gt;in&lt;/span&gt;: /usr/lib/libffi.dylib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After much longer than I liked, I found a fix buried in a &lt;a href="https://github.com/ffi/ffi/issues/687#issuecomment-468005152"&gt;github issue&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem uninstall ffi
brew reinstall libffi
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LDFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-L/usr/local/opt/libffi/lib"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PKG_CONFIG_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/opt/libffi/lib/pkgconfig"&lt;/span&gt;
gem &lt;span class="nb"&gt;install &lt;/span&gt;ffi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I decided to share this since the error in the title of the issue is different from the one that I got. Hope this can save someone some time.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The really effective part of TDD is not so much whether you write the test first (according to Uncle Bob)</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Sat, 25 Jul 2020 12:55:56 +0000</pubDate>
      <link>https://forem.com/toureholder/the-really-effective-part-of-tdd-is-not-so-much-whether-you-write-the-test-first-according-to-uncle-bob-3h6n</link>
      <guid>https://forem.com/toureholder/the-really-effective-part-of-tdd-is-not-so-much-whether-you-write-the-test-first-according-to-uncle-bob-3h6n</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is also available in &lt;a href="https://dev.to/toureh/tdd-realmente-efetiva-segundo-tio-bob-2gb3"&gt;Portuguese 🇧🇷&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Do you know how this statement from Robert C. Martin ends?&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;The really effective part of TDD is ...&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Robert C. Martin (colloquially known as Uncle Bob), is the author of the classic Clean Code book, one of the original authors of the Agile Manifesto and a real &lt;a href="https://www.youtube.com/results?search_query=uncle+bob+tdd"&gt;die hard defender&lt;/a&gt; of &lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;TDD&lt;/a&gt; as a tool to improve developer productivity and code quality.&lt;/p&gt;

&lt;p&gt;Not too long ago I read an old blog post of his where he states that the really effective part of TDD &lt;strong&gt;is not&lt;/strong&gt; so much whether you write the test first and I must admit I was somewhat taken aback.&lt;/p&gt;

&lt;p&gt;This kinda shocked me because Uncle Bob is as pro-test-first-development as it gets. He's even &lt;a href="https://youtu.be/GvAzrC6-spQ?t=23"&gt;said on occasion&lt;/a&gt; that writing tests after production code is a waste of time. 😱&lt;/p&gt;

&lt;p&gt;So what could be so important, with regards to TDD, that Uncle Bob would consider it to be more important than the order in which we write tests and production code?&lt;/p&gt;

&lt;p&gt;The answer lies in the history of the famous 3 Laws of TDD. You've probably seen them or some version of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You must write a failing test before you write any production code.&lt;/li&gt;
&lt;li&gt;You must not write more of a test than is sufficient to fail, or fail to compile.&lt;/li&gt;
&lt;li&gt;You must not write more production code than is sufficient to make the currently failing test pass.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In &lt;a href="https://blog.cleancoder.com/uncle-bob/2014/12/17/TheCyclesOfTDD.html"&gt;another of his blog posts&lt;/a&gt; called "The Cycles of TDD", Uncle Bob tells the story of how the 3 laws came to be as he recounts an experience he had while paring with Kent Beck, &lt;strong&gt;the father of Extreme programming (XP) and of TDD!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;"I sat with Kent Beck in 1999 and paired with him in order to learn. What he taught me to do was certainly test first; but it involved a more fine-grained process than I’d ever seen before. He would write &lt;strong&gt;one line of a failing test&lt;/strong&gt;, and then write &lt;strong&gt;the corresponding line of production code&lt;/strong&gt; to make it pass. Sometimes it was slightly more than one line; but the scale he used was was very close to line by line."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I, and many others, have written about these three laws over the years. They now appear in many different styles, formats, and injunctive statements. But the goal is always to promote the &lt;strong&gt;line by line&lt;/strong&gt; granularity that I experienced while working with Kent so long ago."&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;This was a real AHA moment for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/msriR5ybSpQgo/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/msriR5ybSpQgo/giphy.gif" alt="Mind blown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see, I had always thought that I had to finish writing all the tests for whatever I was developing before touching the production code to actually be doing TDD.&lt;/p&gt;

&lt;p&gt;I attribute this line of thought to the fact that I used to do &lt;a href="http://xunitpatterns.com/test%20last%20development.html"&gt;Test-last Development&lt;/a&gt;, before trying out TDD. In other words, I used to code up the feature, doing exploratory testing all the while, and then write automated tests after the fact. So, in my head, TDD was just about inverting that order.&lt;/p&gt;

&lt;p&gt;As a result, writing tests before the production code just sounded backwards to me. (And scared the living hell out of me.) I also see little sense in trying to complete a suite of tests without proper IntelliSense on a screen with all kinds of squiggly red lines in the IDE since the methods and properties being testing don't exist yet.&lt;/p&gt;

&lt;p&gt;But as I drilled deeper into the study on the fundamentals of TDD, it became vividly clear how the practice is really grounded in repetitions of &lt;strong&gt;very small cycles&lt;/strong&gt; of testing and implementation. In the book &lt;a href="https://www.jamesshore.com/Agile-Book/test_driven_development.html"&gt;The Art of Agile Development&lt;/a&gt; (&lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;recommended by Martin Fowler&lt;/a&gt;), the author, James Shore, recommends working in cycles of testing and implementation no greater than 5 minutes or 5 lines of code.&lt;/p&gt;

&lt;p&gt;If you're asking yourself what this looks like in action, I'd recommend watching these two videos: &lt;a href="https://www.youtube.com/watch?v=AoIfc5NwRks&amp;amp;t=1450s"&gt;part of The Three Laws of TDD video&lt;/a&gt; and &lt;a href="https://youtu.be/JOYNHkRN_YY"&gt;Tutorial: Mastering Test-Driven Development with Angular&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since coming to all this realization I've been doing TDD almost exclusively and I've been finding the process very intuitive and &lt;strong&gt;fast&lt;/strong&gt;. 😃&lt;/p&gt;

&lt;p&gt;So let's wrap up, going back to the statement I asked you to complete at the beginning of this post and to the moment when Uncle Bob claimed that the really effective part of TDD is not so much whether you write the test first. 👀&lt;/p&gt;

&lt;p&gt;I found it in &lt;a href="https://blog.cleancoder.com/uncle-bob/2016/11/10/TDD-Doesnt-work.html"&gt;yet another of his posts&lt;/a&gt; where he talks about a study that basically concludes that TDD doesn't produce higher quality code than other methods of development.&lt;/p&gt;

&lt;p&gt;You should definitely read &lt;a href="https://blog.cleancoder.com/uncle-bob/2016/11/10/TDD-Doesnt-work.html"&gt;the whole thing&lt;/a&gt; some time to understand the &lt;strong&gt;context&lt;/strong&gt; of the statement, but I'll sum it up for you: In the study, 58 developers where divided into 2 groups and asked to do a programming task. One group had to do TDD while the other did TLD (Test-last development). Both groups were asked to work on small chunks of the task, rather than utilize a waterfall approach. At the end of the experiment, metrics where compared and the study concludes that "TDD does not affect testing effort, software external quality, and developers’ productivity."&lt;/p&gt;

&lt;p&gt;What do you have to say about that Uncle Bob?&lt;/p&gt;

&lt;p&gt;In his analysis, Uncle Bob points out that the study asked the folks doing TLD to work in “small chunks”, inadvertently forcing both groups to use the TDD process of short cycles, and writes:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;The really effective part of TDD is the size of the cycle, not so much whether you write the test first. &lt;strong&gt;The reason we write the tests first is that it encourages us to keep the cycles really short&lt;/strong&gt;.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;And there you have it. Thanks for the read!&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
    </item>
    <item>
      <title>A efetividade real de TDD não está no fato de escrever o teste antes do código (segundo Tio Bob)</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Wed, 22 Jul 2020 11:27:35 +0000</pubDate>
      <link>https://forem.com/toureholder/tdd-realmente-efetiva-segundo-tio-bob-2gb3</link>
      <guid>https://forem.com/toureholder/tdd-realmente-efetiva-segundo-tio-bob-2gb3</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is also available in &lt;a href="https://dev.to/toureh/the-really-effective-part-of-tdd-is-not-so-much-whether-you-write-the-test-first-according-to-uncle-bob-3h6n"&gt;English&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Tente imaginar como esta frase do Robert C. Martin termina:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;The really effective part of TDD is&lt;/em&gt; ..."&lt;/p&gt;

&lt;p&gt;Robert C. Martin, (carinhosamente conhecido como Tio Bob) é autor do livro clássico &lt;a href="https://www.amazon.com/C%C3%B3digo-Habilidades-Pr%C3%A1ticas-Softwar-Portuguese/dp/8576082675"&gt;Código Limpo&lt;/a&gt;, um dos autores originais do Manifesto Agile e um &lt;a href="https://www.youtube.com/results?search_query=uncle+bob+tdd"&gt;defensor ferrenho&lt;/a&gt; da prática de &lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;TDD&lt;/a&gt;  como uma ferramenta para aumentar a produtividade de desenvolvedores e a qualidade do código produzido por eles.&lt;/p&gt;

&lt;p&gt;Recentemente li um post (antigo) no blog do Tio Bob no qual ele afirma que a efetividade real de TDD &lt;strong&gt;não está&lt;/strong&gt; no fato de escrever o teste antes do código de produção e confesso que fiquei um tanto quanto ... chocado.&lt;/p&gt;

&lt;p&gt;Esta afirmação me chamou muito atenção porque o evangelismo do Tio Bob a favor de TDD é implacável. Tão implacável que ele já foi capaz de &lt;a href="https://youtu.be/GvAzrC6-spQ?t=23"&gt;afirmar&lt;/a&gt; que escrever testes depois de escrever código de produção é um desperdício de tempo. 😱&lt;/p&gt;

&lt;p&gt;Então, qual fator poderia ser tão importante para a prática de TDD ao ponto do Tio Bob considerá-lo mais importante que a relação de ordem entre a criação de testes e a criação do código de produção?&lt;/p&gt;

&lt;p&gt;A resposta repousa na história das famosas 3 Leis de TDD. Você provavelmente já ouviu essas 3 leis ou pelo menos alguma versão delas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não é permitido escrever código de produção a não ser que seja para fazer passar um teste que esteja falhando.&lt;/li&gt;
&lt;li&gt;Não é permitido escrever mais do teste do que seja necessário para fazer o teste falhar, ou deixar de compilar.&lt;/li&gt;
&lt;li&gt;Não é permitido escrever mais código de produção do que o suficiente para fazer um teste passar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em &lt;a href="https://blog.cleancoder.com/uncle-bob/2014/12/17/TheCyclesOfTDD.html"&gt;outro post&lt;/a&gt; no seu blog, intitulado "Os Ciclos de TDD", o Tio Bob conta como as 3 leis se originaram enquanto relata uma experiência que teve quando pareou com Kent Beck, &lt;strong&gt;o criador da metodologia Extreme programming (XP) e da prática de TDD&lt;/strong&gt;!&lt;/p&gt;




&lt;p&gt;"&lt;em&gt;Eu me sentei para parear com Kent Beck em 1999 para aprender. De fato ele me ensinou a escrever os testes primeiro, mas em um processo mais granular do que eu já tinha visto antes. Ele escreveria &lt;strong&gt;uma linha de teste&lt;/strong&gt; que falharia e então escreveria &lt;strong&gt;uma linha de código de produção&lt;/strong&gt; correspondente para fazer o teste passar. Às vezes era um pouco mais de uma linha, mas a escala que ele utilizava era muito próximo de linha a linha&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;....&lt;/p&gt;

&lt;p&gt;&lt;em&gt;O objetivo de escrever sobre as 3 leis sempre foi promover essa granularidade &lt;strong&gt;linha a linha&lt;/strong&gt; que eu experimentei enquanto trabalhava com Kent.&lt;/em&gt;” (Tradução livre)&lt;/p&gt;




&lt;p&gt;Não sei se a frase acima teve o mesmo impacto revelador em você que teve em mim quando a li pela primeira vez. &lt;em&gt;But, I was mind blown.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/msriR5ybSpQgo/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/msriR5ybSpQgo/giphy.gif" alt="Mind blown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando comecei a tentar fazer TDD, eu achava que só estaria fazendo TDD de verdade se eu terminasse de escrever todos os testes da funcionalidade que eu iria implementar, antes de encostar no código de produção.&lt;/p&gt;

&lt;p&gt;Eu atribuo esta linha de pensamento ao fato de eu praticar apenas &lt;a href="http://xunitpatterns.com/test%20last%20development.html"&gt;Test-last Development&lt;/a&gt; (TLD), antes de me aventurar no mundo de TDD. Ou seja, eu implementava uma funcionalidade e depois de estar satisfeito com os resultados de testes exploratórios, eu então escrevia testes automatizados. Na minha cabeça TDD seria apenas uma inversão desta ordem.&lt;/p&gt;

&lt;p&gt;Resultado: A ideia de escrever testes antes de escrever código de produção me parecia pouco intuitivo (e me apavorava). Também não via (e continuo não vendo) praticidade em tentar completar um conjunto de testes sem IntelliSense e com quase todas as linhas sublinhadas de vermelho pelo IDE pelo fato dos métodos e propriedades da classe a ser implementada não existirem ainda. &lt;/p&gt;

&lt;p&gt;Ao me aprofundar no estudo sobre o tema, encontrei várias fontes que frisam o fato de que a prática de TDD é fundamentada em repetições de &lt;strong&gt;pequenos ciclos&lt;/strong&gt; de teste e desenvolvimento. Por exemplo, no livro &lt;a href="https://www.jamesshore.com/Agile-Book/test_driven_development.html"&gt;The Art of Agile Development&lt;/a&gt;, (leitura &lt;a href="https://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;indicada pelo Martin Fowler&lt;/a&gt;), o James Shore recomenda trabalhar em ciclos de teste e desenvolvimento que não passam de 5 minutos ou de 5 linhas de código.&lt;/p&gt;

&lt;p&gt;Se você estiver se perguntando como isso funciona na prática, recomendo 2 vídeos:&lt;br&gt;
&lt;a href="https://youtu.be/JOYNHkRN_YY"&gt;Tutorial: Mastering Test-Driven Development with Angular&lt;/a&gt; e &lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=AoIfc5NwRks&amp;amp;t=1450s"&gt;este trecho do vídeo The Three Laws of TDD&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com esta realização, eu voltei a praticar TDD, seguindo as 3 leis à risca na maior parte do tempo e hoje o processo tem se tornado muito mais intuitivo e &lt;strong&gt;rápido&lt;/strong&gt;. 😃&lt;/p&gt;

&lt;p&gt;Para finalizar, vamos voltar àquela frase incompleta do início deste post e o momento em que o Tio Bob é pego com a boca na botija, flagrado, afirmando que a efetividade real de TDD não está no fato de escrever o teste antes do código de produção. 👀&lt;/p&gt;

&lt;p&gt;Eu encontrei a afirmação em &lt;a href="https://blog.cleancoder.com/uncle-bob/2016/11/10/TDD-Doesnt-work.html"&gt;outro post&lt;/a&gt; do seu blog no qual o ele analisa um estudo que conclui que a prática de TDD não tem um impacto significativo sobre a qualidade do software produzido por equipes.&lt;/p&gt;

&lt;p&gt;Aconselho fortemente ler &lt;a href="https://blog.cleancoder.com/uncle-bob/2016/11/10/TDD-Doesnt-work.html"&gt;o post&lt;/a&gt; na sua integridade para entender &lt;strong&gt;o contexto&lt;/strong&gt; da afirmação, mas para resumir o estudo: 58 desenvolvedores foram divididos em 2 grupos para realizar alguns desafios de programação. Um grupo deveria fazer TDD enquanto o outro grupo fizesse TLD (Test-last development). Os 2 grupos foram orientados a trabalhar em &lt;strong&gt;pequenos ciclos&lt;/strong&gt; de desenvolvimento e testes e não de uma forma cascata. No final, métricas foram comparadas e o estudo conclui que TDD não tem efeito (nem positivo, nem negativo) sobre a produtividade dos desenvolvedores nem sobre a qualidade do código produzido.&lt;/p&gt;

&lt;p&gt;Então, porque raios a gente deveria escrever testes &lt;strong&gt;antes&lt;/strong&gt; do código de produção?&lt;/p&gt;

&lt;p&gt;Em resposta a este estudo, o Tio Bob destaca o fato que tanto os devs do grupo de TDD quanto os do grupo de TLD trabalharam em pequenos ciclos e afirma:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;A efetividade real de TDD está no tamanho do ciclo, e não no fato de escrever o teste antes. &lt;strong&gt;Escrevemos testes antes porque isso nos motiva a manter os ciclos muito pequenos&lt;/strong&gt;.&lt;/em&gt;" (Tradução livre)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Texto original:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"The really effective part of TDD is the size of the cycle, not so much whether you write the test first. The reason we write the tests first is that it encourages us to keep the cycles really short."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Wow!&lt;/p&gt;

&lt;p&gt;Obrigado por ler até o final (ou por pular para o final só para ver a resposta). Espero que o post tenha sido enriquecedor para você!&lt;/p&gt;

</description>
      <category>tdd</category>
    </item>
    <item>
      <title>Easy Continuous Delivery with Travis CI and Firebase hosting</title>
      <dc:creator>Touré Holder</dc:creator>
      <pubDate>Sun, 05 Jul 2020 13:56:29 +0000</pubDate>
      <link>https://forem.com/toureholder/easy-cd-with-travis-ci-and-firebase-hosting-4p62</link>
      <guid>https://forem.com/toureholder/easy-cd-with-travis-ci-and-firebase-hosting-4p62</guid>
      <description>&lt;p&gt;Continuous delivery with Travis CI and Firebase hosting. It's as easy as 1, 2, 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Select the repository you want to use with Travis CI.
&lt;/h2&gt;

&lt;p&gt;Click on your profile picture in the top right of your &lt;a href="https://travis-ci.com/dashboard"&gt;Travis Dashboard&lt;/a&gt;, click Settings, and toggle the repositories you want to use with Travis CI. &lt;a href="https://docs.travis-ci.com/user/tutorial/#to-get-started-with-travis-ci-using-github"&gt;See the docs.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Add your Firebase CI token to your environment variables
&lt;/h2&gt;

&lt;p&gt;On your command line install Firebase CLI, initiate your project and generate a CI token, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the CLI&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; firebase-tools

&lt;span class="c"&gt;# Run this command from your app’s root directory&lt;/span&gt;
firebase init

&lt;span class="c"&gt;# This will print out a new access token &lt;/span&gt;
firebase login:ci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go to your repository settings in Travis CI: &lt;a href="https://travis-ci.com/dashboard"&gt;Dashboard&lt;/a&gt; &amp;gt; menu icon of the repository &amp;gt; Settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--idGp6PDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/FfzluiK.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--idGp6PDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/FfzluiK.jpg" alt="Settings option in menu" title="Settings option in menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Settings page, add a new environment variable called FIREBASE_TOKEN with the access token you just generated on the command-line as the value and be sure to leave "Display value in build log" turned off since your token should be stored securely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--028aHo2a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/dZgELhl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--028aHo2a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/dZgELhl.jpg" alt="Adding a new environment variable" title="Adding a new environment variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Add a &lt;code&gt;.travis.yml&lt;/code&gt; file to your repository
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;.travis.yml&lt;/code&gt; file with these two commands in an appropriate &lt;a href="https://docs.travis-ci.com/user/job-lifecycle/"&gt;phase&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install -g firebase-tools&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;firebase deploy --token "$FIREBASE_TOKEN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a complete example of a simple an Angular CI/CD pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dist&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trusty&lt;/span&gt;
&lt;span class="na"&gt;sudo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node_js&lt;/span&gt;
&lt;span class="na"&gt;node_js&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10"&lt;/span&gt;

&lt;span class="na"&gt;addons&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;chrome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt;

&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;directories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./node_modules&lt;/span&gt;

&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm build&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm run test -- --no-watch --no-progress --browsers=ChromeHeadless&lt;/span&gt;


&lt;span class="na"&gt;after_success&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install -g firebase-tools&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;firebase deploy --token "$FIREBASE_TOKEN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push a commit with your &lt;code&gt;.travis.yml&lt;/code&gt; and the files generated by &lt;code&gt;firebase init&lt;/code&gt; to your remote and that should be enough to kick-off your build and deploy your app to Firebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;I want to finish up explaining why I wrote yet another Travis CI + Firebase hosting post.&lt;/p&gt;

&lt;p&gt;While setting up continuous delivery of my Angular app I had a very hard time using the &lt;a href="https://docs.travis-ci.com/user/deployment/firebase/"&gt;Travis CI Firebase Deployment provider&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, I couldn't get the Travis CLI to work on my Mac due to annoying Xcode and command-line tools related errors like this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dyld: lazy symbol binding failed: Symbol not found: _ffi_prep_closure_loc
  Referenced from: /Users/toure/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle
  Expected &lt;span class="k"&gt;in&lt;/span&gt;: /usr/lib/libffi.dylib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After googling 'dyld: lazy symbol binding failed: Symbol not found: _ffi_prep_closure_loc' and going through issues and Stack overflow answers about updating my Xcode tooling and whatnot, to no avail, I gave up on trying to add an &lt;a href="https://docs.travis-ci.com/user/deployment/firebase/#generating-your-firebase-token"&gt;encrypted firebase token&lt;/a&gt; to my &lt;code&gt;.travis.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I then added the token to my environment variables and tried to keep using the Travis CI Firebase provider, but even though I could print and see the token in the pipeline, I couldn't get authentication to work. Maybe I wasn't escaping the special characters right or something.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Error: HTTP Error: 401, Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, I ended up giving up altogether on the Firebase provider and doing it the way I described in this post. Which is actually the same way I do it with other CI/CD tools that I use, like Bitbucket pipelines.&lt;/p&gt;

&lt;p&gt;Thanks for reading! Let me know what you think of the post :)&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>firebase</category>
      <category>travisci</category>
    </item>
  </channel>
</rss>
