<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Marcos Sevilla]]></title><description><![CDATA[I'm a Dart and Flutter senior engineer at Very Good Ventures who likes to talk about tech and how to make good code.]]></description><link>https://marcossevilla.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 07:57:37 GMT</lastBuildDate><atom:link href="https://marcossevilla.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Cleaner Flutter Vol. 10: State and UI]]></title><description><![CDATA[It’s amazing to think we started this series with ten volumes in mind and only the last two were focused on the app itself. That’s what you get when you talk about architecture (the right way) and split your projects in a maintainable and scalable wa...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-10</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-10</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[User Interface]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Tue, 22 Feb 2022 04:28:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645502872272/FaZj4C-bT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It’s amazing to think we started this series with ten volumes in mind and only the last two were focused on the app itself. That’s what you get when you talk about architecture (the right way) and split your projects in a maintainable and scalable way. But well, let’s talk about state and user interfaces.</p>
<p>In the previous volume, we talked about how to identify and inject dependencies in our apps. Our application’s dependencies will be repositories or data sources, but they are going to be used by the business logic components (blocs), and then the blocs are going to emit states that the user interface will use to render widgets.</p>
<p>Part of this article will be about state management using my two favorite alternatives: <a target="_blank" href="https://pub.dev/packages/bloc"><code>package:bloc</code></a> and <a target="_blank" href="https://pub.dev/packages/riverpod"><code>package:riverpod</code></a>. I have an article about the latter at <a target="_blank" href="https://marcossevilla.dev/riverpod">Riverpod: Rewriting Provider</a>, not yet one for <code>bloc</code>. I’ll try to write one soon but in the meantime, you can check <a target="_blank" href="https://medium.com/flutter-community/flutter-bloc-for-beginners-839e22adb9f5">this one</a> made by Ana from <a target="_blank" href="https://twitter.com/flutter_es">Flutter Spain</a>.</p>
<p><img src="https://media.giphy.com/media/BpGWitbFZflfSUYuZ9/giphy.gif" alt="https://media.giphy.com/media/BpGWitbFZflfSUYuZ9/giphy.gif" /></p>
<h1 id="heading-what-to-look-for-in-a-state-manager">What to look for in a state manager</h1>
<p>I want to start this discussion by explaining why I like <code>bloc</code> and <code>riverpod</code>, so this is an abstract of state management and can be used to evaluate other options when making this choice.</p>
<h2 id="heading-predictability">Predictability</h2>
<p>First of all, I think code, in general, should be easy to comprehend, and that way it’s also <strong>predictable</strong>. </p>
<p>Someone asked me once what I meant with predictable code, to explain that I’m going to quote my teammate Jorge in his <a target="_blank" href="https://verygood.ventures/blog/boring-code-part-1"><strong>Are you saying that my code is boring? Thank you!</strong></a> article:</p>
<blockquote>
<p>Producing boring code is the biggest compliment that an engineering team can receive; after all, “surprises” in a project tend to be not so good surprises. No one likes receiving a 2 a.m. emergency call, or spending 8 hours tracking down a bug that is almost impossible to reproduce and as engineers, we don’t like solving the same problem over and over again.</p>
</blockquote>
<p>Predictable code is the one that is consistent and somewhat obvious. You know the structure and that allows you to know where things are without having to ask another engineer.</p>
<p>You can see this aspect in <code>package:bloc</code> when you create a new <code>Bloc</code>. The component is created aiming for a feature-driven architecture, so each feature has one <code>Bloc</code> assigned to it. Additionally, you’re always going to have three files related to that <code>Bloc</code>: bloc, event, and state.</p>
<blockquote>
<p>💡 When you’re exploring a bloc directory, I recommend going through the files in this order: event, state, bloc. It’s an easy way to see the causes (events), the effects (states) they provoke, and what’s the relation between both (bloc).</p>
</blockquote>
<p>On <code>riverpod</code> land, I already recommended a logical structure for your business logic in my article about it, but there’s no official way to organize them as you may have functionality inside another type of <code>Provider</code> that is not a business logic one like <code>StateNotifierProvider</code>.</p>
<p>We can say <code>bloc</code> is more predictable or at least the documentation is more explicit about this aspect.</p>
<h2 id="heading-testability">Testability</h2>
<p>Testing is a critical requirement for a project in my opinion. That makes the ease to test an invaluable detail to take into consideration when choosing a state management tool.</p>
<p>You can check more about testing on the article <a target="_blank" href="https://verygood.ventures/blog/guide-to-flutter-testing"><strong>Flutter testing: A very good guide [10 Insights]</strong></a> from Very Good Ventures.</p>
<p>This is a broad topic to talk about, but I can mention some general ideas of what to search for when evaluating a state manager regarding testing.</p>
<h3 id="heading-shouldnt-depend-on-lots-of-packages">Shouldn’t depend on lots of packages</h3>
<p>If you are unit testing a layer of your architecture, you should have a few dependencies imported for testing it. </p>
<p>For <code>bloc</code>, you have a dedicated test utility called <a target="_blank" href="https://pub.dev/packages/bloc_test"><code>package:bloc_test</code></a>, which can also be used in conjunction with <a target="_blank" href="https://pub.dev/packages/mocktail"><code>package:mocktail</code></a> and used to mock blocs for widget testing.</p>
<p>For <code>riverpod</code>, there is no testing utility to facilitate <code>StateNotifier</code> testing, so it ends up being a common unit test and you could also use <code>mocktail</code> to mock the component’s dependencies.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockSharedPreferencesRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mock</span>
    <span class="hljs-keyword">implements</span> <span class="hljs-title">SharedPreferencesRepository</span> </span>{}

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">late</span> SharedPreferencesRepository preferencesRepository;

  setUp(() {
    preferencesRepository = MockSharedPreferencesRepository();
  });

  blocTest&lt;PreferencesBloc, PreferencesState&gt;(
    <span class="hljs-string">'emits [PreferencesEmpty] when PreferencesCleared is added.'</span>,
    setUp: () {
      when(preferencesRepository.clearValues).thenAnswer((_) <span class="hljs-keyword">async</span> {});
    },
    build: () =&gt; PreferencesBloc(repository: preferencesRepository),
    act: (bloc) =&gt; bloc.add(PreferencesCleared()),
    expect: () =&gt; <span class="hljs-keyword">const</span> &lt;PreferencesState&gt;[PreferencesEmpty()],
  );
}
</code></pre>
<h3 id="heading-set-up-should-be-easy">Set up should be easy</h3>
<p>As we mentioned in the <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-9">previous volume</a>, state management is a combination between dependency injection and reactive components. That means that to test these reactive components isolated we don’t need any dependency injection other than mocking their dependencies. And when using them to test UI, we should inject them with our DI mechanism easily without additional setup that can be repetitive and frustrating.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  group(<span class="hljs-string">'ProfileBloc'</span>, () {
    blocTest&lt;ProfileBloc, ProfileState&gt;(
      <span class="hljs-string">'emits [ProfileLoaded] when ProfileAccountAdded is added.'</span>,
      build: () =&gt; ProfileBloc(),
      act: (bloc) =&gt; bloc.add(ProfileAccountAdded(user)),
      expect: () =&gt; &lt;ProfileState&gt;[
        ProfileLoaded(
          current: user,
          accounts: [user],
        ),
      ],
    );
  });
}
</code></pre>
<p>Both <code>bloc</code> and <code>riverpod</code> are pretty easy to test, but I’d love a utility like <code>bloc_test</code> for <code>state_notifier</code> (not exactly a <code>riverpod</code> related request).</p>
<h3 id="heading-100-coverage-is-achievable">100% coverage is achievable</h3>
<p>I’m not saying that your project <strong>must have</strong> 100% test coverage, but for me it’s a useful metric to at least determine that your project has a decent amount of tests and can also help you to see which parts of your app are not being triggered, helping you to evaluate if it’s critical to test it.</p>
<p>That said, I do think that if you strive for that one-hundred mark, your packages should help you do so by exposing a clean and comprehensible API that won’t stand in your way to get it.</p>
<p>Yes, both picks are good with that.</p>
<h2 id="heading-unique-benefits">Unique benefits</h2>
<p>I have to say I like these two packages because they both have something unique in their way to do state management. I love how <code>bloc</code> has evolved to simplify the <code>Stream</code> API and reactive concepts from <a target="_blank" href="https://pub.dev/packages/rxdart"><code>package:rxdart</code></a>. Also, I’m a big fan of how <code>riverpod</code> has introduced an innovative approach to dependency injection that facilitates communication between components.</p>
<p>I think both are robust solutions to the problems that may appear when developing apps, but I got to give bloc an advantage in this regard that comes from being built on top of the <code>Stream</code> API: <a target="_blank" href="https://pub.dev/packages/bloc_concurrency"><code>package:bloc_concurrency</code></a>.</p>
<p>This is the most recent addition to the bloc library and has improved the ways to handle events in our blocs by introducing <code>EventTransformers</code> that can apply useful behaviors to process these events.</p>
<pre><code class="lang-dart">FileBlocNew({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.fileRepo}) : <span class="hljs-keyword">super</span>(FileState.initial()) {
    <span class="hljs-keyword">on</span>&lt;LoadFiles&gt;(
      (event, emit) =&gt; loadFiles(event, emit.call),
      <span class="hljs-comment">// If a LoadFiles event is added while a previous LoadFiles event</span>
      <span class="hljs-comment">// is still processing, the previous LoadFiles event will be cancelled.</span>
      <span class="hljs-comment">// This is beneficial since we only care about the latest result, and</span>
      <span class="hljs-comment">// avoids waiting on unnecessary and possibly out of date results.</span>
      transformer: restartable(),
    );
    <span class="hljs-keyword">on</span>&lt;DeleteFile&gt;(
      (event, emit) =&gt; deleteFile(event, emit.call),
      <span class="hljs-comment">// The default behavior of Bloc 7.2+ is to process events in parallel,</span>
      <span class="hljs-comment">// so we could have left out the transformer here.</span>
      <span class="hljs-comment">//</span>
      <span class="hljs-comment">// However, it is worth leaving here to indicate that the writes here</span>
      <span class="hljs-comment">// don't mutate the states of other files, so we can benefit from</span>
      <span class="hljs-comment">// concurrent processing.</span>
      <span class="hljs-comment">//</span>
      <span class="hljs-comment">// If the order of writes is important, we could have used sequential()</span>
      <span class="hljs-comment">// here.</span>
      transformer: concurrent(),
    );
  }
</code></pre>
<p>That snippet was taken from the <a target="_blank" href="https://github.com/VGVentures/bloc_concurrency_demos/">bloc_concurrency_demos</a> repository. More about <code>bloc_concurrency</code> in my teammate Joanna’s deep dive article <a target="_blank" href="https://verygood.ventures/blog/how-to-use-bloc-with-streams-and-concurrency"><strong>How to use Bloc with streams and concurrency</strong></a>.</p>
<h1 id="heading-verdict">Verdict</h1>
<p>You can’t go wrong with these two state managers.</p>
<p>State management itself becomes a subjective matter because everyone has different needs. But if you’re thinking about a definitive tool and you know that your app can become a behemoth one day, I think the easiest way is to go with the bloc library.</p>
<p>It’s been around for quite some time now and has proven to be the best way to scale apps. Not to mention that is a library, conjunction of packages that provide pretty sweet functionality that most apps will need if they grow enough.</p>
<p>I still like <code>riverpod</code> as an alternative, and you can use both with my friend Frank’s <a target="_blank" href="https://pub.dev/packages/riverbloc"><code>package:riverbloc</code></a>, which takes the reactive components and compatibility with the rest of the packages from <code>bloc</code> and the dependency injection used with <code>riverpod</code> to make a cool team-up.</p>
<h1 id="heading-building-widgets-based-on-state">Building widgets based on state</h1>
<p>I wanted to add this small section to this article because I think sometimes is underestimated, and that’s how to structure our widgets to handle state properly.</p>
<p>For <code>bloc</code>, we can use <code>flutter_bloc</code> widgets to inject blocs into the widget tree and then render other widgets or even trigger actions based on their state. We’re going to focus on how to structure <code>Bloc</code> injection in our widgets as for <code>riverpod</code> we have a <code>ProviderScope</code> that allows us to use <code>Providers</code> from every widget that is below it on the widget tree.</p>
<h2 id="heading-page-view-pattern">Page-View pattern</h2>
<p>There’s a common issue that gets open every once in a while at the <a target="_blank" href="https://github.com/felangel/bloc">Bloc GitHub repository</a> that has to do with <a target="_blank" href="https://stackoverflow.com/questions/71071187/why-cant-we-use-blocprovider-ofbloccontext-inside-of-consumer-with-bloc-attri/71093717#71093717">calling a bloc that is not on the context that is being used</a>. </p>
<p>To avoid getting this issue as much as possible, there is the <strong>Page-View pattern</strong> that uses a <strong>Page</strong> widget to inject the <code>Bloc</code> via <code>BlocProvider</code>, and then use it on a <strong>View</strong> widget with a new <code>BuildContext</code>.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SignUpPage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> SignUpPage({Key? key}) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-keyword">static</span> Page page() =&gt; <span class="hljs-keyword">const</span> MaterialPage&lt;<span class="hljs-keyword">void</span>&gt;(child: SignUpPage());

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> BlocProvider(
      create: (_) =&gt; SignUpBloc(),
      child: <span class="hljs-keyword">const</span> SignUpView(),
    );
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SignUpView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> SignUpView({Key? key}) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> BlocListener&lt;SignUpBloc, SignUpState&gt;(
      listener: (context, state) {
        <span class="hljs-keyword">if</span> (state.complete) {
          Navigator.of(context).pushReplacement&lt;<span class="hljs-keyword">void</span>, <span class="hljs-keyword">void</span>&gt;(
            HomePage.page(),
          );
        }
      },
      child: SignUpForm(),
    );
  }
}
</code></pre>
<p>This pattern makes even more sense when you test your widgets. When testing <code>SignUpPage</code> from the snippet above, you only have to pump your page and check if the view is rendered.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  testWidgets(<span class="hljs-string">'renders SignUpView'</span>, (tester) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> tester.pumpApp(<span class="hljs-keyword">const</span> SignUpPage());
    expect(find.byType(SignUpView), findsOneWidget);
  });
}
</code></pre>
<p>Then, to test the view, you only need to inject a bloc and mock its state to comply with your test’s expectations.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockSignUpBloc</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">MockBloc</span>&lt;<span class="hljs-title">SignUpEvent</span>, <span class="hljs-title">SignUpState</span>&gt;
    <span class="hljs-keyword">implements</span> <span class="hljs-title">SignUpBloc</span> </span>{}

<span class="hljs-keyword">void</span> main() {
  testWidgets(
    <span class="hljs-string">'navigates to HomePage when SignUpState is complete'</span>,
    (tester) <span class="hljs-keyword">async</span> {
      <span class="hljs-keyword">const</span> user = User(
        email: <span class="hljs-string">'me@marcossevilla.dev'</span>,
        name: <span class="hljs-string">'Marcos'</span>,
        biography: <span class="hljs-string">"I'm a software engineer"</span>,
        pin: <span class="hljs-string">'0123'</span>,
      );

      <span class="hljs-keyword">final</span> signUpBloc = MockSignUpBloc();

      whenListen(
        signUpBloc,
        Stream.fromIterable([SignUpState(user: user, complete: <span class="hljs-keyword">true</span>)]),
        initialState: SignUpState(user: user),
      );

      <span class="hljs-keyword">await</span> tester.pumpApp(
        BlocProvider&lt;SignUpBloc&gt;.value(
          value: signUpBloc,
          child: <span class="hljs-keyword">const</span> SignUpView(),
        ),
      );
      <span class="hljs-keyword">await</span> tester.pumpAndSettle();

      expect(find.byType(HomePage), findsOneWidget);
    },
  );
}
</code></pre>
<blockquote>
<p>💡 This pattern forces us to scope our blocs so that they are created right above the “branch” of the widget tree that consumes their state. For example, we have the SignUpBloc scoped to the sign-up feature, not globally created for every part of the tree.</p>
</blockquote>
<h2 id="heading-widget-reusability">Widget reusability</h2>
<p>At last, I want to talk about how to reuse widgets. I’ll probably create a more in-depth article about widget structure and maybe throw some atomic design in the mix, but in the meantime, I’ll give you this short explanation on how to create widgets based on state.</p>
<p>The first question that should come to our minds before creating a widget should be “Am I going to reuse this widget in another part of our app?”</p>
<p>Once we answered that, we can define which widgets are going to be sent to the widgets folder on our feature or to our app component package, if you like to extract the components you reuse in various features.</p>
<p>Then, I suggest you apply the same principle of the bloc injection and maintain your state as the closest parent to the widget that is going to consume it. For example:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> CounterView({Key? key}) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> BlocBuilder(
      builder: (context, count) {
        <span class="hljs-keyword">return</span> Scaffold(
          appBar: AppBar(title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Counter'</span>)),
          body: Center(
            child: Text(
              <span class="hljs-string">'<span class="hljs-subst">$count</span>'</span>,
              style: Theme.of(context).textTheme.headline1,
            ),
          ),
          floatingActionButton: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.end,
            children: &lt;Widget&gt;[
              FloatingActionButton(
                child: <span class="hljs-keyword">const</span> Icon(Icons.add),
                onPressed: () =&gt; context.read&lt;CounterBloc&gt;().add(Increment()),
              ),
              <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">4</span>),
              FloatingActionButton(
                child: <span class="hljs-keyword">const</span> Icon(Icons.remove),
                onPressed: () =&gt; context.read&lt;CounterBloc&gt;().add(Decrement()),
              ),
              <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">4</span>),
              FloatingActionButton(
                child: <span class="hljs-keyword">const</span> Icon(Icons.brightness_6),
                onPressed: () =&gt; context.read&lt;ThemeCubit&gt;().toggleTheme(),
              ),
            ],
          ),
        );
      },
    );
  }
}
</code></pre>
<p>This widget has a <code>BlocBuilder</code> as root widget and just consumes the state on the <code>Text</code> widget located at the body of the <code>Scaffold</code>. Neither the <code>AppBar</code> nor the <code>FloatingActionButton</code> consumes this state, so it can be better organized like this:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CounterView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> CounterView({Key? key}) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Counter'</span>)),
      body: Center(
        child: BlocBuilder&lt;CounterBloc, <span class="hljs-built_in">int</span>&gt;(
          builder: (context, count) {
            <span class="hljs-keyword">return</span> Text(
              <span class="hljs-string">'<span class="hljs-subst">$count</span>'</span>,
              style: Theme.of(context).textTheme.headline1,
            );
          },
        ),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: &lt;Widget&gt;[
          <span class="hljs-comment">// buttons...</span>
        ],
      ),
    );
  }
}
</code></pre>
<p>In case we want additional functionality to our <code>Text</code> widget, we can do two things. We’re going to reset the counter if we tap on an <code>IconButton</code> right below the count.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CountDisplay</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> CountDisplay({
    Key? key,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.count,
  }) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> count;

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          <span class="hljs-string">'<span class="hljs-subst">$count</span>'</span>,
          style: Theme.of(context).textTheme.headline1,
        ),
        IconButton(
          icon: <span class="hljs-keyword">const</span> Icon(Icons.restore),
          onPressed: () =&gt; context.read&lt;CounterBloc&gt;().add(Reset()),
        ),
      ],
    );
  }
}
</code></pre>
<p>But if we want to reuse this widget with the same <code>IconButton</code> but different functionality, I’d suggest decoupling it from the <code>CounterBloc</code> reset event and parametrize that interaction this way:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CountDisplay</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> CountDisplay({
    Key? key,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.count,
    <span class="hljs-keyword">this</span>.onRestore,
  }) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> count;
  <span class="hljs-keyword">final</span> VoidCallback? onRestore;

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          <span class="hljs-string">'<span class="hljs-subst">$count</span>'</span>,
          style: Theme.of(context).textTheme.headline1,
        ),
        IconButton(
          icon: <span class="hljs-keyword">const</span> Icon(Icons.restore),
          onPressed: onRestore,
        ),
      ],
    );
  }
}
</code></pre>
<h1 id="heading-wrap-up">Wrap-up</h1>
<p>Thanks for completing this series with me! I appreciate all the love people have been giving to these articles, from comments to questions of when the next one was coming out.</p>
<p>I know the last two were a bit late and maybe they won’t feel like part of the same series as the others because my opinions about architecture have changed over this past year, but CleanScope is still a strong option if you want to follow clean architecture as close as possible.</p>
<p>I’ll write another article about architecture and what CleanScope taught me about it down the road, explaining where it succeed and where there was room for improvement.</p>
<p>All I can say is, keep on learning about architecture, it’s a broad topic that requires knowledge on many subtopics as you saw during this series. Remember that if you follow the SOLID principles and the dependency rule, you are most likely to have a robust architecture!</p>
<hr />
<p>Thanks to my friend <a target="_blank" href="https://hashnode.com/@elianortega">Elian</a> for his help on volumes <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-2">2</a> and <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-5">5</a>, he put a lot of effort into those and I’m humbled to have him as a writing partner for the whole Cleaner Flutter initiative! </p>
<p><img src="https://media.giphy.com/media/3oFzmqN1xHwaEXGl7q/giphy.gif" alt="the end" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 9: Injecting dependencies]]></title><description><![CDATA[I’m going to start this article by mentioning an important algorithmic paradigm that sometimes slips through our hands when designing a system: divide and conquer.
In the first volume, I used an analogy to express how I like to think about projects, ...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-9</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-9</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[dependency injection]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Sat, 19 Feb 2022 20:12:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645301061830/wyRRHjLNs.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I’m going to start this article by mentioning an important algorithmic paradigm that sometimes slips through our hands when designing a system: divide and conquer.</p>
<p>In the <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-1">first volume</a>, I used an analogy to express how I like to think about projects, apps, and software in general: LEGOs. Those small blocks can fit together to form a bigger structure, more importantly, having the possibility to take one block and reuse it for another structure that we can build later. Talking about efficiency here.</p>
<p>A project can grow unexpectedly and that brings us the popular scalability problem. But how can we plan against it?</p>
<p>Yes, you guessed, dividing and conquering. By splitting our code into small pieces, we can affect fewer parts of our code at the same time when maintaining it. It makes even more sense when we want to isolate one component in an environment that only mocks its dependencies to test expected behaviors atomically.</p>
<h1 id="heading-identify-dependencies">Identify dependencies</h1>
<p>Ok, now that we mentioned dependencies, let’s talk about them.</p>
<p>Now that we have our architecture, we need to follow its patterns. As we already know, we have our domain layer which has repository contracts, and then the data layer that implements those contracts. </p>
<p>Each one of these layers is a dependency on our app. In our app, we have two parts of our architecture that we will cover in the next volume of this series, but for now, we’ve seen data and domain. The data layer is a dependency of the repository layer and can be configured on the app to be used in the domain layer by our repository.</p>
<p>Usually, Dart packages and Flutter plugins are data sources that should be dependencies of our repository in the domain layer, so we don’t need to create a separate package to handle the data layer. But in some cases, the direct use of a package/plugin it’s not enough abstraction to be a dependency for our repository, that’s why we create data sources or API packages. You can see an example of the latter in the <a target="_blank" href="https://bloclibrary.dev/#/fluttertodostutorial?id=data-layer"><code>flutter_todos</code></a> example on the <a target="_blank" href="https://bloclibrary.dev/">bloc library</a>.</p>
<p>In that same example, we can see that abstracting our data layer can allow us to create different implementations of it, an aspect that we remarked on <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-7">volume 7</a>.</p>
<blockquote>
<p>💡 One thing to note is that the abstraction of these dependencies varies depending on the project, sometimes using a package or plugin as a repository dependency can be enough abstraction depending on what we want to do.</p>
</blockquote>
<h1 id="heading-what-is-dependency-injection">What is dependency injection</h1>
<p>But first, what is dependency injection? This explanation from <a target="_blank" href="https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/">freeCodeCamp.com</a> works for us:</p>
<blockquote>
<p>So, transferring the task of creating the object to someone else and directly using the dependency is called <strong>dependency injection</strong>.</p>
</blockquote>
<p>Translating... It’s a technique (like <a target="_blank" href="https://dragonball.fandom.com/wiki/Kamehameha">Kamehameha</a>) that is based on recognizing a class dependency and not creating it inside that class but instead receiving that class as a property that is created and provided from another source.</p>
<p>See this:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> </span>{
  <span class="hljs-keyword">final</span> bar = Bar();

  <span class="hljs-keyword">void</span> doAnything() {
    bar.doSomething();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> </span>{
  <span class="hljs-keyword">void</span> doSomething() {}
}
</code></pre>
<p>In this case, <code>Foo</code> depends on <code>Bar</code>, and to use it, it creates an object inside itself to later use one of its methods. We recognize <code>Bar</code> as a dependency of <code>Foo</code>, but <code>Foo</code> it's not following dependency injection.</p>
<h1 id="heading-a-pattern-to-follow">A pattern to follow</h1>
<p>Let’s fix the previous approach by defining an adequate pattern for our code.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> </span>{
  Foo({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.bar});

  <span class="hljs-keyword">final</span> Bar bar;

  <span class="hljs-keyword">void</span> doAnything() {
    bar.doSomething();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> </span>{
  <span class="hljs-keyword">void</span> doSomething() {}
}
</code></pre>
<p>Yup, that looks better.</p>
<p>If we ask for our dependency on the object’s constructor, we can give it an instance created in another part of our code and comply with the DI pattern.</p>
<p>This is especially useful when testing our class, that way, we can create a mock instance of our dependency and set up specific behavior to test if our class behaves the way we want to based on the behavior we define.</p>
<p>But still, this can be improved.</p>
<p><img src="https://media.giphy.com/media/26xBKqeFFspRZjDTW/giphy.gif" alt="https://media.giphy.com/media/26xBKqeFFspRZjDTW/giphy.gif" /></p>
<p>You are probably wondering, what’s wrong with that approach?</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> foo = Foo(bar: Bar());

  foo.bar.doSomething();
}
</code></pre>
<p>Oh no, that doesn’t look good. Our <code>bar</code> property is public, so we can access its methods without using <code>foo</code> explicitly! </p>
<p>We can fix it by making our property private:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> </span>{
  Foo({<span class="hljs-keyword">required</span> Bar bar}) : _bar = bar;

  <span class="hljs-keyword">final</span> Bar _bar;

  <span class="hljs-keyword">void</span> doAnything() {
    _bar.doSomething();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> </span>{
  <span class="hljs-keyword">void</span> doSomething() {}
}

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> foo = Foo(bar: Bar());

  foo.doAnything();
}
</code></pre>
<p>This way, we define a variable of type <code>Bar</code> in our constructor’s scope and then assign its value to our private variable.</p>
<p>Here’s another tip: if you want to have a fallback instance for your dependency and not make it required in your constructor, you can define the constructor instance as nullable.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> </span>{
  Foo({Bar? bar}) : _bar = bar ?? Bar();

  <span class="hljs-keyword">final</span> Bar _bar;

  <span class="hljs-keyword">void</span> doAnything() {
    _bar.doSomething();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> </span>{
  <span class="hljs-keyword">void</span> doSomething() {}
}

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> foo = Foo();

  foo.doAnything();
}
</code></pre>
<p>This will allow you to instantiate your <code>Foo</code> object without passing an instance of <code>Bar</code>. This comes in handy when your dependency doesn’t need any configuration and can be used with its default behavior.</p>
<p>One thing to take into consideration with this last tip is that some of your dependencies will require an explicit instance configured for your class, like a data source that depends on a <code>Dio</code> object (see <a target="_blank" href="https://marcossevilla.dev/dio">Better HTTP with Dio</a>) and we assume that object already has a base URL. We can require a new instance to force ourselves to pass an object with that already defined.</p>
<p>And before we move on, please don’t do this...</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> </span>{
  Foo(<span class="hljs-keyword">this</span>._bar);

  <span class="hljs-keyword">final</span> Bar _bar;

  <span class="hljs-keyword">void</span> doAnything() {
    _bar.doSomething();
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> </span>{
  <span class="hljs-keyword">void</span> doSomething() {}
}
</code></pre>
<p>You straight-up can’t use named parameters with this approach, and that can be a problem if your class needs to support more dependencies and you want to have a clean API. Just, don’t.</p>
<h1 id="heading-ways-of-injection-in-our-apps">Ways of injection in our apps</h1>
<p>There are already different alternatives to implement dependency injection in our apps. As we mentioned on <a target="_blank" href="https://marcossevilla.dev/riverpod">Riverpod: Rewriting Provider</a>, most of the packages that need DI to solve problems like state management (which is DI + reactive state components) use <a target="_blank" href="https://pub.dev/packages/provider"><code>package:provider</code></a>.</p>
<p>Other alternatives use the <a target="_blank" href="https://en.wikipedia.org/wiki/Service_locator_pattern">service locator pattern</a>, like <a target="_blank" href="https://pub.dev/packages/get_it"><code>package:get_it</code></a>. But as we selected <a target="_blank" href="https://pub.dev/packages/riverpod"><code>package:riverpod</code></a> and <a target="_blank" href="https://pub.dev/packages/bloc"><code>package:bloc</code></a> as the two state management alternatives to use in our architecture, we will explain briefly how they implement dependency injection.</p>
<h2 id="heading-how-provider-does-it">How Provider does it</h2>
<p>To implement DI, <a target="_blank" href="https://pub.dev/packages/flutter_bloc"><code>package:flutter_bloc</code></a> has widgets that use <code>package:provider</code> to inject blocs in our widget tree. That’s by using a Flutter widget called <code>InheritedWidget</code>, which allows us to provide properties to its children.</p>
<p>You can check how to use <code>BlocProvider</code> and dependency injection with <code>bloc</code> on the <a target="_blank" href="https://bloclibrary.dev/#/flutterbloccoreconcepts?id=blocprovider">official documentation</a>.</p>
<h2 id="heading-how-riverpod-does-it">How Riverpod does it</h2>
<p>Aiming to improve the way we do DI with <code>provider</code>, <code>riverpod</code> has a unique way to inject dependencies in our apps, I talk more about that on <a target="_blank" href="https://marcossevilla.dev/riverpod">Riverpod: Rewriting Provider</a>.</p>
<h1 id="heading-what-to-import-in-our-app">What to import in our app</h1>
<p>If there’s no configuration for our data layer, we want to import only our repository to the app. This happens when the dependency our repository relies on can create an internal instance without us providing one as I mentioned previously.</p>
<p>That said, if you can create your repository in your app without injecting dependencies, you should only import your repository package and any models or functionality from the data source you may need. Like this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">library</span> todos_repository;

<span class="hljs-comment">// Here you export your repository and </span>
<span class="hljs-comment">// the `Todo` model from your API.</span>
<span class="hljs-keyword">export</span> <span class="hljs-string">'package:todos_api/todos_api.dart'</span> <span class="hljs-keyword">show</span> Todo;
<span class="hljs-keyword">export</span> <span class="hljs-string">'src/todos_repository.dart'</span>;
</code></pre>
<p>On the other hand, if you need to initialize a data source/API dependency when creating your repository in the app project, then feel free to also import that package into your app.</p>
]]></content:encoded></item><item><title><![CDATA[Riverpod: Rewriting Provider]]></title><description><![CDATA[I think it's not an exaggeration to say that most of the content on Flutter is about state management. Being a reactive framework for the client-side, Flutter has integrated the concept of state since its birth. But if you do a complex project, setSt...]]></description><link>https://marcossevilla.dev/riverpod</link><guid isPermaLink="true">https://marcossevilla.dev/riverpod</guid><category><![CDATA[state]]></category><category><![CDATA[management]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[Dart]]></category><category><![CDATA[Flutter Examples]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Sun, 06 Feb 2022 03:11:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644103494293/98q0uQdcK.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I think it's not an exaggeration to say that most of the content on Flutter is about state management. Being a reactive framework for the client-side, Flutter has integrated the concept of state since its birth. But if you do a complex project, <code>setState</code> won't solve your problems, that's why there are state managers.</p>
<p>Flutter's most popular state management tool is <a target="_blank" href="https://pub.dev/packages/provider"><code>package:provider</code></a>. Ok, maybe there's another one I'm not recommending nor mentioning, but <code>provider</code> it's probably the one that most state management packages use or take inspiration from. At the time I'm writing this, 396 packages depend on <code>provider</code> according to <a target="_blank" href="https://pub.dev">pub.dev</a>.</p>
<p>I'm not going to talk much about <code>provider</code> because I already made a clarification that I consider important in my article on <a target="_blank" href="https://marcossevilla.dev/state-notifier"><code>state_notifier</code></a>. That article is a must-read since it clarifies quite what <code>provider</code> is and it is one of the packages that <code>riverpod</code> incorporates.</p>
<p>But... what is <code>riverpod</code> and why do I like it so much?</p>
<h1 id="heading-cause">Cause</h1>
<p>In the <code>state_notifier</code> article, I explained that Provider was a tool that allows us to easily use <code>InheritedWidget</code>, which is the class in Flutter that gives access to its properties to its children in the widget tree.</p>
<p><code>provider</code> itself has some problems because of this relationship with <code>InheritedWidget</code>.</p>
<p>First, <strong>doesn't allow us to create two Providers of the same type unless they are on a different subtree</strong>. If we have a class from which we want to create two separate objects to handle similar logic in different modules of the app, it's impossible for us because an <code>InheritedWidget</code> is found in the tree looking for a specific data type --or class--. </p>
<p>This also causes <code>Providers</code> not to be found and leaves us runtime errors that could be avoided in the compilation. Strike one.</p>
<p>Then <strong>combining Providers can be cumbersome, more complex than it should, and throw unexpected errors</strong> from the same unusual <code>InheritedWidget</code> manipulation. The common way to make a <code>Provider</code> aware of changes in another to react in its logic is by using a <code>ProxyProvider</code> or <code>ChangeNotifierProxyProvider</code> and yet these aren't the best alternatives in synchronization or syntax (it gets very nested). You can make hacky workarounds for this but I'm not into that.</p>
<p>They are a dependency injection and not exactly a listener for events. Strike two.</p>
<p>Finally: <strong>depending on InheritedWidget, it depends on Flutter</strong>. Which isn't the best if you like to encapsulate your business logic in a separate package and maintain a separation of concerns with your logic independent of the SDK of the user interface. </p>
<p>Strike three... well, not necessarily, but do you see that there are many opportunities for improvement?</p>
<h1 id="heading-effect">Effect</h1>
<p>All these problems made the creator of <code>provider</code>, Rémi Rousselet, have the initiative to re-engineer <code>InheritedWidget</code> from scratch, thus creating <a target="_blank" href="http://pub.dev/packages/riverpod"><code>package:riverpod</code></a>.</p>
<p>In simple words, <code>riverpod</code> doesn't depend on Flutter so it doesn't depend on <code>InheritedWidget</code>, it allows us to combine <code>Providers</code> to listen to and react to its changes and it guarantees us reliable code from the compilation stage.</p>
<p>Yes, it solves <code>provider</code>'s problems, and very well if you ask me.</p>
<p>Let's see it in action and its equivalents with respect to Provider.</p>
<h1 id="heading-which-package-do-i-use">Which package do I use</h1>
<p>If you do a search in <a target="_blank" href="http://pub.dev">pub.dev</a>, you will find 3 versions of <code>riverpod</code>, let me explain what each one does.</p>
<ul>
<li><p><a target="_blank" href="https://pub.dev/packages/riverpod"><code>package:riverpod</code></a>: Contains the core functionality to use it without depending on Flutter. This is the one to use if you are creating a package for a business logic layer other than the graphical interface.</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/flutter_riverpod"><code>package:flutter_riverpod</code></a>: Contains the core, plus all the classes and widgets used to link the logic with the user interface, depending on Flutter. It's the one that you must use if your project already needs Flutter and you are not separating the logic in another package outside the project. It's the most common because of how projects are usually organized.</p>
</li>
<li><p><a target="_blank" href="https://pub.dev/packages/hooks_riverpod"><code>package:hooks_riverpod</code></a>: Contains the core and adds the necessary functionality to be used in conjunction with <a target="_blank" href="http://pub.dev/packages/flutter_hooks"><code>package:flutter_hooks</code></a>, which must also be added as a dependency. It's the one you should use if your project uses hooks to simplify your code in the user interface and Riverpod to access the state. I'm not going to go too deep into this package in this article.</p>
</li>
</ul>
<p>And if it wasn't clear, this image is in the documentation to make it more clear:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11nfppj1dee9m5gekyb4.png" alt="Which Riverpod do I use" /></p>
<h1 id="heading-migrating-from-provider-to-riverpod">Migrating from Provider to Riverpod</h1>
<h2 id="heading-from-multiprovider-to-providerscope">From MultiProvider to ProviderScope</h2>
<p>Initially, when we wanted to insert a <code>Provider</code> in the widget tree, we did something like this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  runApp(
    MultiProvider(
      providers: [
        Provider(create: (_) =&gt; MyProvider()),
      ],
      child: MyApp(),
    ),
  );
}
</code></pre>
<p>Here we could have a list of our <code>Providers</code> and it depended on the <code>MultiProvider</code>, a single <code>Provider</code> or <code>ChangeNotifierProvider</code>. This way gave us a scope that determined wherein our widget tree we would be able to use our logic component.</p>
<p>In <code>riverpod</code>, our <code>Providers</code> can be used as global variables that we can also consume in a global scope called <code>ProviderScope</code> and this scope can be overwritten as necessary in the tree.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}
</code></pre>
<h2 id="heading-new-way-to-create-providers">New way to create Providers</h2>
<p>Once our <code>ProviderScope</code> is declared, we can use any <code>Provider</code> below it. Now let's see how we make a <code>Provider</code>.</p>
<p>In the case of <code>provider</code>, we create a class that inherits from <code>ChangeNotifier</code>, <code>StateNotifier</code>, a repository or service class of its own. <code>riverpod</code> comes with <code>StateNotifier</code> by default, so it's easier to implement this alternative, same way there are more types of Providers than we will talk about in a moment.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NamesNotifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StateNotifier</span>&lt;<span class="hljs-title">List</span>&lt;<span class="hljs-title">String</span>&gt;&gt; </span>{
  NamesNotifier([<span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">String</span>&gt;? initialNames]) : <span class="hljs-keyword">super</span>(initialNames ?? []);

  <span class="hljs-keyword">void</span> add(<span class="hljs-built_in">String</span> newName) {
    state = [...state, newName];
  }
}
</code></pre>
<p>We can use this <code>NamesNotifier</code> both in <code>provider</code> and <code>riverpod</code> because the logic components are not affected by the package, which already takes care of incorporating this component into the widget tree for use. </p>
<p>In <code>provider</code>, we need to include the packages <a target="_blank" href="https://pub.dev/packages/state_notifier"><code>state_notifier</code></a> and <a target="_blank" href="https://pub.dev/packages/flutter_state_notifier"><code>flutter_state_notifier</code></a>. In <code>riverpod</code>, these are not needed since <a target="_blank" href="https://pub.dev/packages/flutter_riverpod"><code>flutter_riverpod</code></a> contains the <code>ConsumerWidget</code> (equivalent to the <code>Consumer</code> widget in <code>provider</code> but used more similar to <code>StatelessWidget</code>).</p>
<blockquote>
<p>💡 I quickly clarify that the core of the packages is in <a target="_blank" href="https://pub.dev/packages/riverpod"><code>riverpod</code></a> and <a target="_blank" href="https://pub.dev/packages/state_notifier"><code>state_notifier</code></a>, and the other packages that I mentioned that are called the same with the difference of the <em>flutter</em> prefix contain the widgets to communicate the logic of these packages with the user interface.</p>
</blockquote>
<p>To create a <code>Provider</code> on <code>riverpod</code>, use the following:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> myProvider = Provider((ref) =&gt; MyProvider());
</code></pre>
<p>And to create a <code>StateNotifierProvider</code> in <code>riverpod</code> we do this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> namesNotifierProvider = StateNotifierProvider&lt;NamesNotifier, <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">String</span>&gt;&gt;((_) =&gt; NamesNotifier());
</code></pre>
<p>Once declared, no matter what file it's in, the <code>Provider</code> is in the <code>ProviderScope</code> and is available wherever it is needed via <code>ProviderRef</code>.</p>
<p>I want you to analyze the syntax a bit.</p>
<ol>
<li><p>We declare them as a <code>final</code> variable.</p>
</li>
<li><p>We instance the class <code>Provider</code>, which contains a callback function by which we return the class. </p>
<blockquote>
<p>Note: this function will serve us much later.</p>
</blockquote>
</li>
<li><p>The callback returns a variable of type <code>ProviderRef</code>, which we call <code>ref</code>, for our use in creating the <code>Provider</code>.</p>
</li>
</ol>
<p>The <code>ref</code> variable is what would be a <code>BuildContext</code> for <code>Providers</code> in <code>riverpod</code>. With it, we can access other <code>Providers</code> in the tree and the good thing is that we can access it in the creation of any <code>Provider</code>.</p>
<p>See why it was good to separate him from Flutter? We no longer need <code>BuildContext</code>.</p>
<h2 id="heading-use-of-providers-with-widgets">Use of Providers with Widgets</h2>
<p>In <code>provider</code>, we use the <code>BuildContext</code> of the <code>build</code> method of any widget to access our <code>Provider</code> since it is an<code>InheritedWidget</code>.</p>
<p>We can do it in two ways...</p>
<ul>
<li>Use <code>ConsumerWidget</code>.</li>
</ul>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WidgetToShowNames</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ConsumerWidget</span> </span>{
  <span class="hljs-keyword">const</span> WidgetToShowNames({Key? key}) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context, WidgetRef ref) {
    <span class="hljs-keyword">final</span> names = ref.watch(namesNotifierProvider);
    <span class="hljs-keyword">return</span> ListView.builder(
      shrinkWrap: <span class="hljs-keyword">true</span>,
      itemCount: names.length,
      itemBuilder: (_, index) {
        <span class="hljs-keyword">final</span> name = names[index];
        <span class="hljs-keyword">return</span> Text(name);
      },
    );
  }
}
</code></pre>
<ul>
<li>Use <code>Consumer</code> widget.</li>
</ul>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WidgetToShowNames</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> WidgetToShowNames({Key? key}) : <span class="hljs-keyword">super</span>(key: key);

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Consumer(
      builder: (context, ref, child) {
        <span class="hljs-keyword">final</span> names = ref.watch(namesNotifierProvider);
        <span class="hljs-keyword">return</span> ListView.builder(
          shrinkWrap: <span class="hljs-keyword">true</span>,
          itemCount: names.length,
          itemBuilder: (_, index) {
            <span class="hljs-keyword">final</span> name = names[index];
            <span class="hljs-keyword">return</span> Text(name);
          },
        );
      },
    );
  }
}
</code></pre>
<p>Yes, there's a <code>ConsumerWidget</code> that is very similar to a<code>StatelessWidget</code>, but adds a <code>WidgetRef</code> as a parameter to the <code>build</code> method. This new parameter allows us to access any <code>Provider</code> that we create and be listening (or observing) the changes it may have.</p>
<p>Likewise, we can use a <code>StatelessWidget</code> in conjunction with the <code>Consumer</code> widget that works in the same way as in <code>Provider</code>, only that it gives us our <code>WidgetRef</code> instead of the type that we define since there can be multiple Providers with the same type and that no longer guarantees that we will get the value we want when sending the type.</p>
<blockquote>
<p>💡 In this section of <strong>What Marcos Recommends...</strong></p>
<p>I use <code>ConsumerWidget</code> since I don't like to nest more widgets with <code>Consumer</code>, the code seems much more readable to me and it is easier to find where your Providers are used having classified your widgets in <code>StatelessWidget</code>, <code>StatefulWidget</code> and <code>ConsumerWidget</code>.</p>
</blockquote>
<h2 id="heading-combining-providers">Combining Providers</h2>
<p>One of the solutions that <code>riverpod</code> brings to <code>Provider</code> problems is easier communication between <code>Providers</code>. We achieve this thanks to the <code>ProviderRef</code>.</p>
<p>The creation of a <code>Provider</code> gives us by default its possible combination with another that is in the reference. This is how we can inject dependencies of <code>Providers</code> and establish behaviors based on those changes.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> authenticateUser = FutureProvider&lt;<span class="hljs-built_in">String</span>&gt;(
  (ref) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> ref.read(authProvider.notifier).login();
    <span class="hljs-keyword">return</span> ref.read(authProvider);
  },
);

<span class="hljs-keyword">final</span> authProvider = StateNotifierProvider&lt;AuthNotifier, <span class="hljs-built_in">String</span>&gt;(
  (_) =&gt; AuthNotifier(),
);

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthNotifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StateNotifier</span>&lt;<span class="hljs-title">String</span>&gt; </span>{
  AuthNotifier() : <span class="hljs-keyword">super</span>(<span class="hljs-string">'no-token'</span>);

  Future&lt;<span class="hljs-built_in">String</span>&gt; login() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> Future.delayed(
      <span class="hljs-keyword">const</span> <span class="hljs-built_in">Duration</span>(seconds: <span class="hljs-number">3</span>),
      () =&gt; state = <span class="hljs-string">'token'</span>,
    );
  }
}
</code></pre>
<p>Suppose we have a <code>Provider</code> with authentication functionality, which we call <code>authProvider</code>, we use its <code>login</code> method that sets an access token as its state. Having the token in the state, we can use that state to call an authentication function and save the value for other queries.</p>
<p>What? What's that <code>FutureProvider</code> thing? Glad you ask...</p>
<h1 id="heading-everything-is-a-provider">Everything is a Provider</h1>
<p>As you can see, there are many types of <code>Providers</code>, and it's a word that's going to come up everywhere if you work with <code>riverpod</code>.</p>
<p>Just like Flutter tells you to consider everything a widget in the framework, at <code>riverpod</code> I suggest you <em>consider everything a Provider</em>. A <code>Provider</code> can be a function (they are built with functions themselves), a state variable, a global variable (literally), and so on.</p>
<h2 id="heading-provider-types">Provider types</h2>
<p>I'm going to present to you the most common and used types of <code>Providers</code> so far.</p>
<ul>
<li><p><code>StateProvider</code>: Exposes a value that can be modified from outside. We access the state through the <code>state</code> variable and we can change it. Very similar to <code>ValueNotifier</code>.</p>
</li>
<li><p><code>FutureProvider</code>: Constructs an asynchronous value or <code>AsyncValue</code> and has the operation of an ordinary <code>Future</code>. It's useful to load data from a service whose method to obtain this data is asynchronous.</p>
</li>
<li><p><code>StreamProvider</code>: Create and expose the last value in a <code>Stream</code>. Ideal for communication in real-time with Firebase or some other API whose events can be interpreted in <code>Stream</code>.</p>
</li>
<li><p><code>StateNotifierProvider</code>: Create a <code>StateNotifier</code> and expose its state. The most used for logic components, it allows easy access to <code>state</code>, which is usually a private property that's modified by public methods.</p>
</li>
<li><p><code>ScopedProvider</code>: Defines a <code>Provider&lt;T&gt;</code> (of a generic type) that behaves differently somewhere in the project. It's used in conjunction with the <code>overrides</code> property of <code>ProviderScope</code> and defines with the latter the scope where this <code>ScopedProvider</code> is going to be modified.</p>
</li>
<li><p><code>ProviderFamily</code>: This type of <code>Provider</code> is a modifier, that is, all of the above can use it. In itself, it defines an additional parameter that's involved in the creation of our <code>Provider</code>, such as a <code>String</code>.</p>
</li>
</ul>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> usersFamily = FutureProvider.family&lt;User, <span class="hljs-built_in">String</span>&gt;(
  (ref, id) <span class="hljs-keyword">async</span> =&gt; dio.<span class="hljs-keyword">get</span>(<span class="hljs-string">'https://my_api.dev/users/<span class="hljs-subst">$id</span>'</span>),
);
</code></pre>
<ul>
<li><code>AutoDisposeProvider</code>: Another modifier that allows us to automatically <code>dispose</code> of our <code>Providers</code>, allowing us to delete the state when the widgets where they are used are destroyed.</li>
</ul>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> numbersProvider = StreamProvider.autoDispose(
    (ref) {
      <span class="hljs-keyword">final</span> streamController = StreamController&lt;<span class="hljs-built_in">int</span>&gt;();

      ref.onDispose(() {
        streamController.close();
      });

      <span class="hljs-keyword">return</span> streamController.stream;
    },
);
</code></pre>
<p><img src="https://media.giphy.com/media/kSlJtVrqxDYKk/giphy.gif" alt="https://media.giphy.com/media/kSlJtVrqxDYKk/giphy.gif" /></p>
<h1 id="heading-best-practices">Best practices</h1>
<h2 id="heading-how-to-structure-providers">How to structure Providers</h2>
<p><code>riverpod</code> has the peculiarity that, as we saw previously, it covers many use cases with different types of <code>Providers</code>, from app state to ephemeral state.</p>
<p>The problem is that there is no guide on how to structure <code>Providers</code>, so I always recommend separating your logic in a good way.</p>
<p>I summarize it in my personal rules:</p>
<ul>
<li><p>Separate project folders by functionalities (features).</p>
</li>
<li><p>In a specific functionality I try to have a <code>/provider</code> folder where I have all my <code>Providers</code>.</p>
</li>
<li><p>I don't have more than one logic component (<code>StateNotifier</code>) for functionality.</p>
</li>
<li><p>In the provider folder, I separate my state, logic component, and <code>Provider</code> in separate files. You can also have a generated <code>freezed</code> file if you use that tool for state union classes.</p>
</li>
</ul>
<p>With the rules that I mentioned before, we have a folder structure like this...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644116858334/89nnqsBKo.png" alt="carbon.png" /></p>
<h1 id="heading-some-things-to-consider">Some things to consider</h1>
<p>I was thinking for a long time if there are any downsides or something to say as a warning about <code>riverpod</code>. Being honest and objective, I don't find many things and the ones I do find aren't critical.</p>
<p><code>riverpod</code> is already in a stable phase, as you can see. You can implement it in your projects from now on and I dare to say that it may be a better option than <code>provider</code>. It's a package that can take your time to master, but once you do, it becomes a very capable tool.</p>
<p>I also clarify that it isn't a replacement for <code>provider</code> yet, since <code>provider</code> still solves many needs. For me, <code>riverpod</code> is becoming a real state management option since more developers are mastering it and the problems it solves are valued. Many have yet to find scenarios where <code>provider</code> shows its flaws.</p>
<p><img src="https://media.giphy.com/media/ZwvpEzDz05oc0/giphy.gif" alt="https://media.giphy.com/media/ZwvpEzDz05oc0/giphy.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 8: Implementing contracts]]></title><description><![CDATA[We have already talked about repositories, I would say quite a bit. But we still have one more part to cover about them, their implementation. At this point in the volumes of the series, we have established actions that we want to take through DataSo...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-8</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-8</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Wed, 12 May 2021 21:48:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644427063762/B3VVwSVHp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We have already talked about repositories, I would say quite a bit. But we still have one more part to cover about them, their implementation. At this point in the volumes of the series, we have established actions that we want to take through <code>DataSources</code>.</p>
<p>In general, implementing a repository is straightforward. Since they are only a class that manages the data sources and, through them, creates a complete data flow.</p>
<p>In the previous volume, we saw about <code>DataSources</code> or <code>DataProviders</code>, so we are going to include them as dependencies of our repository.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SomeRepository</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ISomeRepository</span> </span>{
    SomeRepository({
      <span class="hljs-keyword">required</span> ILocalDataSource localDataSource,
      <span class="hljs-keyword">required</span> IRemoteDataSource remoteDataSource,
    }) :  _localDataSource = localDataSource,
      _remoteDataSource = remoteDataSource;

    <span class="hljs-keyword">final</span> ILocalDataSource _localDataSource;
    <span class="hljs-keyword">final</span> IRemoteDataSource _remoteDataSource;
}
</code></pre>
<p>Our repository also implements the interface (or abstract class) repository that we made from the domain layer, overriding its methods later on.</p>
<p>We can also see the dependency injection pattern that I like to follow, keeping variables private and only assigning it the value of a variable declared at the constructor scope.</p>
<p>This way of using private variables with dependency injection limits us to using this dependency indirectly and only through the object's methods, avoiding its direct use as a property (bypassing).</p>
<h1 id="heading-implementing-methods">Implementing methods</h1>
<p>We are going to override the <code>getModel</code> method that sets our abstract repository to use our data sources and define a specific data flow.</p>
<p>The <code>getModel</code> method is in charge of fetching specific data in a list based on an ID. This method uses the <code>remoteDataSource</code> to query the data to a REST API and from here the flow has two possible scenarios:</p>
<ol>
<li>If the API responds correctly, then the data is stored locally by the <code>localDataSource</code>.</li>
<li>If the API had an error, then the last locally saved value is returned. If there is no saved value, a cache error is thrown.</li>
</ol>
<p>The code looks like this...</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SomeRepository</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ISomeRepository</span> </span>{
    SomeRepository({
      <span class="hljs-keyword">required</span> ILocalDataSource localDataSource,
      <span class="hljs-keyword">required</span> IRemoteDataSource remoteDataSource,
    }) :  _localDataSource = localDataSource,
      _remoteDataSource = remoteDataSource;

    <span class="hljs-keyword">final</span> ILocalDataSource _localDataSource;
    <span class="hljs-keyword">final</span> IRemoteDataSource _remoteDataSource;

    <span class="hljs-meta">@override</span>
    Future&lt;SomeModel&gt; getModel(<span class="hljs-built_in">int</span> modelId) <span class="hljs-keyword">async</span> {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">final</span> model = <span class="hljs-keyword">await</span> _remoteDataSource.getModel(modelId);
        <span class="hljs-keyword">await</span> _localDataSource.saveModel(model);
        <span class="hljs-keyword">return</span> model;
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-comment">// if the API call fails...</span>
        <span class="hljs-keyword">try</span> {
          <span class="hljs-keyword">final</span> model = _localDataSource.getSavedModel();
          <span class="hljs-keyword">return</span> model;
        } <span class="hljs-keyword">catch</span> (e) {
          <span class="hljs-keyword">throw</span> CacheError();
        }
      }
    }
}
</code></pre>
<p>So we can see that our repository was an intermediary for concrete action. We are not interested in whether the data comes via HTTP or some other protocol, a data source takes care of that. Nor if it is saved in user preferences or some secure storage.</p>
<p>We are interested in the specific action of bringing an element, from which come different more steps of the process where several possible ways of interacting with this data converge.</p>
<p>Therefore, we leave interfaces or abstract classes of the <code>DataSource</code> so that they can be easily replaced by other implementations. That allows us to change a data source that uses the <a target="_blank" href="https://pub.dev/packages/shared_preferences"><code>package:shared_preferences</code></a> package to one that uses <a target="_blank" href="https://pub.dev/packages/hive"><code>package:hive</code></a> and does the same thing. Thus the <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-2"><strong>Liskov Substitution Principle</strong></a> is followed.</p>
<p><img src="https://media.giphy.com/media/UuSDgyNq5Jqkkj0t5M/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644426974021/KjOhJGx00.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 7: Where the data comes from]]></title><description><![CDATA[Where we left
The previous volume began with our data layer, a layer where we implement all the actions described in the domain layer to be able to interact with an external service, or a local service (some database on the device or contact with the...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-7</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-7</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Wed, 12 May 2021 21:48:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644424020292/HSMhPJijb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-where-we-left">Where we left</h1>
<p>The previous volume began with our data layer, a layer where we implement all the actions described in the domain layer to be able to interact with an external service, or a local service (some database on the device or contact with the hardware where we run).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644423846763/IHlBFz7TS.png" alt="Data Layer in CleanScope" /></p>
<p>As the title says, let's talk about where the data comes from. We already have our models where we establish what data we are going to use, now we have to go and bring them.</p>
<p>We call classes <code>DataSource</code> and they bring us the "raw" data, convert it into the respective models and pass it to their repository. But there are also other nomenclatures, as in the Bloc library, they are called <a target="_blank" href="https://bloclibrary.dev/#/architecture?id=data-provider"><code>DataProvider</code></a>.</p>
<p>You can call it whatever you want, it seems to me that the name <code>DataProvider</code> would be better if <code>Providers</code> of these classes were created.</p>
<p>Since we don't create <code>Providers</code> for <code>DataSources</code> in <code>riverpod</code>, the name is enough for me.</p>
<p>More of this is in the article on business logic.</p>
<h1 id="heading-the-source-of-the-data">The source of the data</h1>
<p>To define what a <code>DataSource</code> is, I'm going to borrow the concept of <code>DataProvider</code> from <a target="_blank" href="https://bloclibrary.dev/">bloclibrary.dev</a>...</p>
<blockquote>
<p>They provide raw data, they should be generic and versatile. They will usually expose simple APIs to perform CRUD operations.</p>
</blockquote>
<p>When I use <code>DataSources</code> I separate them into two folders: local and remote. This is because <code>DataSources</code> are a way to bring information, which as I mentioned before can be on the same device or to an external API where we have to use HTTP or some other internet protocol.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644423848453/I5mx9X0lK.png" alt="DataSources folder structure" /></p>
<p>A common question is why we don't use repositories to do everything the <code>DataSource</code> does. Mainly because many possible actions are carried out with the data that we want to bring.</p>
<p>A case that happens to me quite often is that I want to save some data in a local database --my preferred option is <a target="_blank" href="https://docs.hivedb.dev/#/"><code>hive</code></a>-- and I bring the data from a REST API. The save-to-device action and the API call action are two different functions. In addition to being two actions that are executed in two different data sources.</p>
<p>Given the above, my repository is in charge of establishing this flow with two different data sources and is in charge of handling the data returned by various data sources and subsequently communicating that result to the business logic.</p>
<h1 id="heading-implementing-a-datasource">Implementing a DataSource</h1>
<h2 id="heading-localdatasource">LocalDataSource</h2>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'dart:convert'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'package:hive/hive.dart'</span> <span class="hljs-keyword">show</span> Box;

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ILocalDataSource</span> </span>{
  SomeModel getSomeModel();
  Future&lt;<span class="hljs-keyword">void</span>&gt; saveSomeModel(SomeModel model);
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LocalDataSource</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ILocalDataSource</span> </span>{
  LocalDataSource({<span class="hljs-keyword">required</span> Box box}) : _box = box;

  <span class="hljs-keyword">final</span> Box _box;

  <span class="hljs-meta">@override</span>
  SomeModel getSomeModel() {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">final</span> encodedJson = _box.<span class="hljs-keyword">get</span>(<span class="hljs-string">'model_key'</span>);
      <span class="hljs-keyword">final</span> model = SomeModel.fromJson(json.decode(encodedJson));
      <span class="hljs-keyword">return</span> model;
    } <span class="hljs-keyword">catch</span> (_) {
      <span class="hljs-keyword">throw</span> CacheException();
    }
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; saveSomeModel(SomeModel model) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _box.put(<span class="hljs-string">'model_key'</span>, json.encode(model.toJson()));
    } <span class="hljs-keyword">catch</span> (_) {
      <span class="hljs-keyword">throw</span> CacheException();
    }
  }
}
</code></pre>
<p>This is what a <code>DataSource</code> looks like locally. I reuse this structure to store unique values in a <code>Box</code>, which is the equivalent of a table in SQL.</p>
<p>I always recommend that every class that you are going to test make an abstract class, so it is easier for them to make their mocks with packages like <a target="_blank" href="https://pub.dev/packages/mocktail"><code>mocktail</code></a>.</p>
<p>In the same way, define the dependencies that you are going to use as properties of the class to only provide you with an object with which you can perform the actions you need. We will see this last point in more detail in the <code>RemoteDataSource</code>.</p>
<p><img src="https://media.giphy.com/media/3orieNQgdcxedKjA3e/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644423849930/rFyvqPMrx.gif" /></p>
<h2 id="heading-remotedatasource">RemoteDataSource</h2>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IRemoteDataSource</span> </span>{
  Future&lt;SomeModel&gt; getModel(<span class="hljs-built_in">int</span> modelId);
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RemoteDataSource</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IRemoteDataSource</span> </span>{
  RemoteDataSource({
    <span class="hljs-keyword">required</span> Dio client
  }) : _client = client;

  <span class="hljs-keyword">final</span> Dio _client;

  <span class="hljs-meta">@override</span>
  Future&lt;SomeModel&gt; getModel(<span class="hljs-built_in">int</span> modelId) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> _client.<span class="hljs-keyword">get</span>(<span class="hljs-string">'/models/<span class="hljs-subst">$modelId</span>/'</span>);
      <span class="hljs-keyword">if</span> (response.statusCode != <span class="hljs-number">200</span>) <span class="hljs-keyword">throw</span> ServerException();
      <span class="hljs-keyword">return</span> SomeModel.fromJson(response.data);
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-keyword">throw</span> ServerException();
    }
  }  
}
</code></pre>
<p>Some packages make it much easier for us to structure our code and <a target="_blank" href="https://pub.dev/packages/dio"><code>package:dio</code></a> is one of them. If you want to learn more about <code>dio</code>, check <a target="_blank" href="https://marcossevilla.dev/dio">here</a>.</p>
<p>It is a very similar structure to the <code>LocalDataSource</code>. We have a dependency injection pattern where we still define dependencies as properties and pass an instance to our private property. All equal.</p>
<p>The difference lies in the implementation of how we get the data, one accesses the database with <code>hive</code> and the other goes to a remote API to take this data through <code>dio</code> (HTTP).</p>
<h3 id="heading-other-implementations">Other implementations</h3>
<p>For both types of <code>DataSources</code>, we can have different implementations so we make an interface that we can implement and define the body of the methods that we are going to use.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:http/http.dart'</span> <span class="hljs-keyword">show</span> Client;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AnotherRemoteDataSource</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IRemoteDataSource</span> </span>{
  AnotherRemoteDataSource({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">Uri</span> url,
    <span class="hljs-keyword">required</span> Client client,
  })   : _url = url,
        _client = client;

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">Uri</span> _url;
  <span class="hljs-keyword">final</span> Client _client;

  <span class="hljs-meta">@override</span>
  Future&lt;SomeModel&gt; getModel() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">final</span> result = <span class="hljs-keyword">await</span> _client.<span class="hljs-keyword">get</span>(_url);
      <span class="hljs-keyword">if</span> (response.statusCode != <span class="hljs-number">200</span>) <span class="hljs-keyword">throw</span> ServerException();
      <span class="hljs-keyword">final</span> decode = json.decode(result.body);
      <span class="hljs-keyword">return</span> SomeModel.fromJson(decode);
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-keyword">throw</span> ServerException();
    }
  }
}
</code></pre>
<p>This other implementation uses Dart's official <code>http</code> package and we can see that the result will be the same, only with a different way of doing it with another package.</p>
<p>There are 2 great advantages that <a target="_blank" href="https://pub.dev/packages/dio"><code>package:dio</code></a> offers us compared to HTTP. One is decoding our response from a pure JSON string to a Dart <code>Map &lt;String, dynamic&gt;</code>. We'll look at the other one in the next section.</p>
<h1 id="heading-reusing-code">Reusing code</h1>
<p>As you have seen from previous articles, CleanScope focuses on developing a project based on specific features. By abstracting our data logic into <code>DataSources</code> and <code>Repositories</code> we can arrive at a structure that, combined with <code>dio</code>, is very organized.</p>
<p>The following example is following how the creation of our data layer to be used as a dependency for our project would look like using <a target="_blank" href="https://pub.dev/packages/flutter_bloc"><code>flutter_bloc</code></a>:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> localDataSource = LocalDataSource(box: Box());
  <span class="hljs-keyword">final</span> remoteDataSource = RemoteDataSource(
    client: Dio(BaseOptions(AppConfig.apiUrl)),
  );

  <span class="hljs-keyword">final</span> someRepository = SomeRepository(
    localDataSource: localDataSource,
    remoteDataSource: remoteDataSource,
  );

  runApp(App(someRepository: someRepository));
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> App({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.someRepository});

  <span class="hljs-keyword">final</span> SomeRepository someRepository;

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> RepositoryProvider.value(
      value: someRepository,
      child: <span class="hljs-keyword">const</span> AppView(),
    );
  }
}
</code></pre>
<p>In the following article, we are going to go into detail about what the repository already implemented looks like, but for the moment we know that it receives its 2 <code>DataSources</code> as properties.</p>
<p><code>dio</code> allows us to reuse instances of its clients with specific configurations so that we make direct calls to endpoints without specifying a base URL. This operation can be seen in the <code>GET</code> of the <code>RemoteDataSource</code> that I built previously with <code>dio</code>:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> _client.<span class="hljs-keyword">get</span>(<span class="hljs-string">'/models/<span class="hljs-subst">$modelId</span>/'</span>);
</code></pre>
<p>That's one of the ways our <code>DataSources</code> are best used.</p>
<p><img src="https://media.giphy.com/media/QoesEe6tCbLyw/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644423851664/uevnjlUhO.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Better HTTP with Dio]]></title><description><![CDATA[The scenario in our projects where we must call an external API via HTTP is never missing.
To achieve this in Dart, we have the official package:http. This provides us with functions and classes that fulfill what is necessary to make these HTTP calls...]]></description><link>https://marcossevilla.dev/dio</link><guid isPermaLink="true">https://marcossevilla.dev/dio</guid><category><![CDATA[Dart]]></category><category><![CDATA[http]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Mon, 19 Apr 2021 13:39:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644446294297/qTBenh5TB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The scenario in our projects where we must call an external API via HTTP is never missing.</p>
<p>To achieve this in Dart, we have the official <a target="_blank" href="https://pub.dev/packages/http"><code>package:http</code></a>. This provides us with functions and classes that fulfill what is necessary to make these HTTP calls in a simple way and without much torture.</p>
<p><code>http</code> is characterized by being based on the <code>Future</code> data type for requests and can also be used on all stable platforms that Flutter supports.</p>
<p>With <code>http</code> we can make calls in a few lines as follows...</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:http/http.dart'</span> <span class="hljs-keyword">as</span> http;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> url = <span class="hljs-string">'https://jsonplaceholder.typicode.com/todos/1'</span>;

  <span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(url);

  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Response statusCode: <span class="hljs-subst">${response.statusCode}</span>'</span>);
  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Response body: <span class="hljs-subst">${response.body}</span>'</span>);
}
</code></pre>
<p>And many examples in the community are made using <code>http</code> because in many cases it solves more than enough.</p>
<p>But not all is so easy. Sometimes we have use cases where our APIs expose us to endpoints that contain more complex functionality like uploading/downloading a file, streaming data, etc.</p>
<p>There are many cases where this functionality can be implemented in <code>http</code> but the detail is that it is not very easy to do it, <a target="_blank" href="https://stackoverflow.com/questions/63195155/dart-flutter-post-request-and-stream-response">here</a> you can see an example.</p>
<h1 id="heading-enter-dio">Enter Dio</h1>
<p>As always, I like to show you alternatives to the usual packages we use and show you the advantages, disadvantages and why these options are worth trying in your future developments.</p>
<p><a target="_blank" href="https://pub.dev/packages/dio"><code>package:dio</code></a> is an alternative to <code>package:http</code> and helps us incorporate everything I was telling you about so we don't have to spend time building on top of <code>http</code> to develop functionality.</p>
<p>Its usage is very similar to <code>http</code> and we just need to instantiate a <code>Dio</code> object which would already be our HTTP client.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> url = <span class="hljs-string">'https://jsonplaceholder.typicode.com/todos/1'</span>;

  <span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> Dio().<span class="hljs-keyword">get</span>(url);

  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Response statusCode: <span class="hljs-subst">${response.statusCode}</span>'</span>);
  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Response body: <span class="hljs-subst">${response.data}</span>'</span>);
}
</code></pre>
<p>You can see that the only change I made was to change the <code>body</code> property of the <code>Response</code> in <code>http</code> to the <code>data</code> property of the <code>Response</code> in <code>package:dio</code>. The only difference between <code>body</code> and <code>data</code> is that the latter is decoded by <code>Dio</code> if it is a <code>Map</code>.</p>
<p>But hey, that's pretty basic, right?</p>
<p>Let's go with the advantages offered by this package.</p>
<h1 id="heading-baseoptions">BaseOptions</h1>
<p><code>dio</code> allows us to create an object with all the base configurations to interact with our API. We can inject this object as dependencies of our classes in charge of the calls to the API (or APIs).</p>
<p>By the way, we can define different <code>Dio</code> objects, as I mentioned, each one with a different configuration for specific endpoints or APIs. But let's see how this configuration is done.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> options = BaseOptions(
    baseUrl: <span class="hljs-string">'https://jsonplaceholder.typicode.com/'</span>,
    connectTimeout: <span class="hljs-number">5000</span>,
    receiveTimeout: <span class="hljs-number">3000</span>,
    responseType: ResponseType.json,
  );

  <span class="hljs-keyword">final</span> dio = Dio(options);

  <span class="hljs-keyword">final</span> response = <span class="hljs-keyword">await</span> dio.<span class="hljs-keyword">get</span>(<span class="hljs-string">'todos/1'</span>);

  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Response statusCode: <span class="hljs-subst">${response.statusCode}</span>'</span>);
  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Response body: <span class="hljs-subst">${response.data}</span>'</span>);
}
</code></pre>
<p>If you run this code, you'll notice that we can still use that <code>Dio</code> object to make the same request with a set of our <code>baseUrl</code>. So when using the <code>get</code> method we only need to specify the endpoint we want to access to retrieve that information.</p>
<p>As I said, we can create several objects that contain different <code>BaseOptions</code> in case they implement a microservices architecture where they can have a client for each API they use.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  <span class="hljs-comment">// ... previous request</span>

  <span class="hljs-keyword">final</span> optionsRickAndMorty = BaseOptions(
    baseUrl: <span class="hljs-string">'https://rickandmortyapi.com/api'</span>,
    connectTimeout: <span class="hljs-number">5000</span>,
    receiveTimeout: <span class="hljs-number">3000</span>,
    responseType: ResponseType.json,
  );

  <span class="hljs-keyword">final</span> dioRickAndMorty = Dio(optionsRickAndMorty);
  <span class="hljs-keyword">final</span> ricksponse = <span class="hljs-keyword">await</span> dioRickAndMorty.<span class="hljs-keyword">get</span>(<span class="hljs-string">'/episode/1'</span>);

  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Ricksponse statusCode: <span class="hljs-subst">${ricksponse.statusCode}</span>'</span>);
  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Ricksponse episode name: <span class="hljs-subst">${ricksponse.data[<span class="hljs-string">'name'</span>]}</span>'</span>);
}
</code></pre>
<p>Here I make a call to another very famous API that my friends from <a target="_blank" href="https://twitter.com/flutter_es"><strong>Flutter Spain</strong></a> use, <a target="_blank" href="https://rickandmortyapi.com/documentation"><strong>RickAndMortyAPI</strong></a>. In this case, I create another client and another configuration to call that other endpoint and I still show the information of both.</p>
<p>Microservices enthusiasts will highly appreciate this functionality. You can check more of the options by <a target="_blank" href="https://pub.dev/packages/dio#request-options">here</a>.</p>
<p>By the way, you can see that <code>data</code> works identically to <code>body</code> when we want to access a specific property of our <code>Response</code>.</p>
<h1 id="heading-concurrency">Concurrency</h1>
<p>This is not a feature of <code>dio</code> but I would like to mention it since many do not know that it exists and it is very useful.</p>
<p>As you saw in the previous example, I am making 2 HTTP requests sequentially and at first glance it is fine, perhaps it would be necessary to separate these functions each one on its own so as not to have such a large main function. But another way we can organize our code is with a <code>Future.wait</code>.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">final</span> concurrentResponse = <span class="hljs-keyword">await</span> Future.wait([
    dioPlaceholder.<span class="hljs-keyword">get</span>(<span class="hljs-string">'todos/1'</span>),
    dioRickAndMorty.<span class="hljs-keyword">get</span>(<span class="hljs-string">'/episode/1'</span>),
]);

concurrentResponse.forEach((res) =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">'\n<span class="hljs-subst">${res.data}</span>'</span>));
</code></pre>
<p>With <code>Future.wait</code> we can send the list of <code>Futures</code> or requests that we are going to make and this method returns a list of responses where we can access each one and in this case simply print it to the console.</p>
<h1 id="heading-download-files">Download files</h1>
<p>If you have projects that require the internal use of files, they will likely require downloading some files to save on the devices that your app operates.</p>
<p>This can be done with <code>http</code> but it takes us a long time to implement from scratch. Yes, you guessed it, <code>dio</code> makes it easy for us like this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> client = Dio();
  <span class="hljs-keyword">final</span> url = <span class="hljs-string">'https://images.unsplash.com/photo-1567026392301-672e510f3369'</span>;

  <span class="hljs-keyword">final</span> directory = <span class="hljs-keyword">await</span> getTemporaryDirectory();
  <span class="hljs-keyword">final</span> fileName = <span class="hljs-string">'<span class="hljs-subst">${directory.path}</span>/downloads'</span>;

  <span class="hljs-keyword">await</span> client.download(
    url,
    fileName,
    options: Options(headers: {HttpHeaders.acceptEncodingHeader: <span class="hljs-string">'*'</span>}),
    onReceiveProgress: (received, total) {
      <span class="hljs-keyword">if</span> (total != <span class="hljs-number">-1</span>) {
        <span class="hljs-keyword">final</span> pos = received / total * <span class="hljs-number">100</span>;
        <span class="hljs-built_in">print</span>(pos);
      }
    },
  );
}
</code></pre>
<p>Analyzing how to do these downloads, we must have --as usual-- our <code>Dio</code> client, the <code>url</code> of the file we want to download, a temporary directory that we get using <a target="_blank" href="https ://pub.dev/packages/path_provider"><code>package:path_provider</code></a>, and also a directory on the device where you save those files you download.</p>
<p>Then with the asynchronous <code>download</code> method, we have all the communication with this file hosted on a remote server. We can optionally assign additional configuration via <code>Options</code>, for example, an <code>acceptEncoding</code> that allows us to tell the server which compression algorithms for the content our client supports.</p>
<p>The most important thing here is that <code>download</code> gives us access to a callback called <code>onReceiveProgress</code> which gives us two integer values: <code>received</code> and <code>total</code>. The first gives us the number of bytes of the file that have been received on the device and the second is the total number of bytes of the file.</p>
<p>Now they can safely download files in their apps.</p>
<blockquote>
<p>⚠️ If there is an error somewhere in the download, <code>dio</code> stops and deletes everything that was downloaded.</p>
</blockquote>
<h1 id="heading-upload-files">Upload files</h1>
<p>Uploading files is a normal POST request with a few tweaks involved.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:dio/dio.dart'</span>;

Future&lt;<span class="hljs-keyword">void</span>&gt; main() <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> client = Dio();
  <span class="hljs-keyword">final</span> url = <span class="hljs-string">'https://some-api.dev/'</span>;

  <span class="hljs-keyword">final</span> directory = <span class="hljs-keyword">await</span> getTemporaryDirectory();
  <span class="hljs-keyword">final</span> fileName = <span class="hljs-string">'<span class="hljs-subst">${directory.path}</span>/rant_about_the_world.txt'</span>;

  <span class="hljs-keyword">final</span> payload = FormData.fromMap({
    <span class="hljs-string">'user'</span>: <span class="hljs-string">'marcossevilla'</span>,
    <span class="hljs-string">'essay'</span>: <span class="hljs-keyword">await</span> MultipartFile.fromFile(fileName),
  });

  <span class="hljs-keyword">await</span> client.post(
    <span class="hljs-string">'<span class="hljs-subst">$url</span>/user/new'</span>,
    data: payload,
    onSendProgress: (sent, total) {
      <span class="hljs-keyword">final</span> progress = sent / total * <span class="hljs-number">100</span>;
      <span class="hljs-built_in">print</span>(progress);
    },
  );
}
</code></pre>
<p>What we do in this part is use a file from the device, whose location we contain --additionally its name-- in <code>fileName</code>. And next, we form a <code>FormData</code> object, similar to the one used in HTML, which is capable of saving the information with a <code>fromMap</code> constructor, and if we want to send a file, which will usually take a moment to upload, we use the class from <code>MultipartFile</code> which contains an asynchronous <code>fromFile</code> method to upload the file.</p>
<p>When uploading the file, we must wait for <code>MultipartFile</code> to finish executing its method, so we use an <code>await</code>.</p>
<p>Likewise, the POST provides us with the two callbacks <code>onReceiveProgress</code> and <code>onSendProgress</code> that allow us to calculate percentages to display download/upload information in our graphical interface.</p>
<h1 id="heading-bonus-tips">Bonus tips</h1>
<p>I can't leave out my favorite topics: architecture and code structure. I'm not going to make a long article explaining how to use <code>dio</code> for your architectures, but how to structure a data layer based on <code>dio</code>.</p>
<p>Orienting it to a microservices architecture where we have different APIs for separate modules (or even very specific actions), I recommend separating them by API that you use. This way you can have a client for each API with whatever <code>BaseOptions</code> you need.</p>
<pre><code class="lang-sh">data/
    |- rick_and_morty_api/
    |- joke_api/
    |- another_api/
</code></pre>
<p>Now that we have our API folder, we can separate it into 2–3 main groups:</p>
<ol>
<li><p>Models: These are the classes that represent the data that we are going to send or receive from the API.</p>
</li>
<li><p>Parsers: These are classes that abstract the conversion logic of the <code>String</code> encoded in JSON to a Dart object. This same logic could be implemented either inside the model or in a <code>DataSource</code> or <code>DataProvider</code>. They are not so necessary but many like to use them.</p>
</li>
<li><p>Datasources / DataProviders: They are in charge of executing the calls to the APIs through a specific client.</p>
</li>
</ol>
<p>Our folder structure would look like this:</p>
<pre><code class="lang-sh">data/
    |- rick_and_morty_api/
        |- models/
        |- parsers/
        |- data_providers/
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643682617202/A_SQTo3xT.gif" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Functional Programming in Dart]]></title><description><![CDATA[Close your eyes for a moment.
You are in the first year of your IT career, whichever it is, there is no discrimination here. You go to your first programming class and your teacher (let's identify him as a man) begins to explain what an algorithm is ...]]></description><link>https://marcossevilla.dev/functional-dart</link><guid isPermaLink="true">https://marcossevilla.dev/functional-dart</guid><category><![CDATA[Dart]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Wed, 10 Feb 2021 17:37:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644903245105/kcH2AV3hN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Close your eyes for a moment.</p>
<p>You are in the first year of your IT career, whichever it is, there is no discrimination here. You go to your first programming class and your teacher (let's identify him as a man) begins to explain what an algorithm is and how they exist everywhere even if they aren't noticeable with the naked eye.</p>
<p>Suddenly he introduces this word of "programming" and mentions to you that there are several types, styles, or as it sounds more intellectual: <strong>paradigms</strong>. He tells you that they're going to learn the structured paradigm because it's your first class. You hear that he also mentions the object-oriented paradigm, and calm down, you will see that a semester later.</p>
<p>There are several that he mentions that probably won't teach you in college, at least that's the way it happened to me. One of those was functional programming or the functional paradigm. This paradigm is sometimes neglected because not all languages allow it to be implemented as it should.</p>
<p>As the title says, this article is focused on the Dart language and also on <a target="_blank" href="https://pub.dev/packages/oxidized"><code>package:oxidized</code></a>. There are other packages for functionally programming in Dart but trusted sources have recommended me <code>oxidized</code>.</p>
<h1 id="heading-the-functional-paradigm">The functional paradigm</h1>
<p><img src="https://media.giphy.com/media/DHqth0hVQoIzS/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644900119562/4dVEWw7A2.gif" /></p>
<p>From that introduction, you can intuit that I'm not an expert in this paradigm, but we are going to focus on the basics so that you can understand the great tricks that can be achieved with it.</p>
<p>Functional programming has the characteristics of being declarative and also treating functions as a primitive data type, or as it sounds nicer, <strong>first-class citizens</strong>.</p>
<p>Those who already know Dart, know that it fits very well with these characteristics. We can send a function to a class or another function as a property or argument.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> greeting = (<span class="hljs-built_in">String</span> name) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">'Hi <span class="hljs-subst">$name</span>'</span>;
  };

  saySomething(greeting);
}

<span class="hljs-keyword">void</span> saySomething(<span class="hljs-built_in">Function</span>(<span class="hljs-built_in">String</span>) message) {
  <span class="hljs-built_in">print</span>(message(<span class="hljs-string">'Marcos'</span>));
}

<span class="hljs-comment">// Hi Marcos</span>
</code></pre>
<p>There we create an object that is a function and we can execute it if we pass it as an argument to another. Compatibility with the paradigm, checked.</p>
<p>In itself, functional programming has an origin closely linked to mathematics since it uses this scientific foundation to be able to process more computationally complex tasks thanks to the replacement of loops, which increase complexity many times, by functions that accept other functions as arguments or they return a function as a result. The latter are called higher-order functions.</p>
<h2 id="heading-advantages">Advantages</h2>
<p>The big question is: what is the advantage of incorporating this paradigm into our code?</p>
<p>I would summarize: it allows us to make code more concise, it reduces the complexity when reading it by not having several control statements in it. It makes testing it much easier as we have function-specific results. The coolest thing, it can be easily combined with other paradigms.</p>
<h2 id="heading-disadvantages">Disadvantages</h2>
<p>Not everything is good, there are some problems when we need a variable state since results are returned, this is where combining it with other paradigms is very useful. It can be slow when going into many recursions.</p>
<p>In general, it is not the best alternative for all tasks.</p>
<h1 id="heading-oxidized">Oxidized</h1>
<p>This package contains many tools that make it easy for us to incorporate functional programming into our project. We go by parts.</p>
<p>First, as a basis, we are going to have a <code>Person</code> entity to exemplify some use cases where we can use functional programming tools.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
  <span class="hljs-keyword">const</span> Person({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.age,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.name,
  });

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> age;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;
}
</code></pre>
<h2 id="heading-result">Result</h2>
<p>The first class that is super useful is <code>Result</code>. It's an abstract class that represents success or failure, it can return the expected result of an operation or the exception it threw. For example:</p>
<pre><code class="lang-dart">Result&lt;<span class="hljs-built_in">String</span>, Exception&gt; getPersonName(Person person) {
  <span class="hljs-keyword">final</span> returnName = Random().nextBool();

  <span class="hljs-keyword">return</span> Result.of(() {
    <span class="hljs-keyword">if</span> (returnName) {
      <span class="hljs-keyword">return</span> person.name;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">throw</span> Exception();
    }
  });
}
</code></pre>
<p>In this case, we define a function that returns a <code>Result</code> that can contain a value of <code>String</code> or  <code>Exception</code>. So our function receives a <code>Person</code> object and based on a random value that we generate, we send a response.</p>
<p>If you notice, we return the name wrapped in a <code>Result.of</code> constructor. This operation can be seen as a try-catch block, but we can forget about handling the exception here and focus on acting upon the <code>err</code> case from the result.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> person = Person(age: <span class="hljs-number">22</span>, name: <span class="hljs-string">'Marcos'</span>);

  <span class="hljs-keyword">final</span> result = getPersonName(person);

  result.when(
    ok: (name) =&gt; <span class="hljs-built_in">print</span>(name),
    err: (e) =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">'Something went wrong... <span class="hljs-subst">$e</span>'</span>),
  );
}

<span class="hljs-comment">// Something went wrong... Exception</span>
<span class="hljs-comment">// Marcos</span>
</code></pre>
<p>Now that we instantiate the class and pass it as an argument to our function, something interesting happens. Since our variable can adopt two possible values of <code>Result</code>, we have a very useful method called <code>when</code> that gives us access to two functions that return a data type each to perform some specific action, such as assignments or the execution of another function that needs the argument that it returns.</p>
<p>If that sounds a bit confusing, see <code>when</code> as an <code>if-else</code> for the two possible data types the function can return.</p>
<p>This class is very useful when we call a third-party API that we don't know very well to catch any unknown errors and return them in the function.</p>
<h2 id="heading-option">Option</h2>
<pre><code class="lang-dart">Option&lt;<span class="hljs-built_in">int</span>&gt; getAge(Person person) {
  <span class="hljs-keyword">final</span> returnAge = Random().nextBool();

  <span class="hljs-keyword">if</span> (returnAge) {
    <span class="hljs-keyword">return</span> None();
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> Some(person.age);
  }
}
</code></pre>
<p>One very similar to <code>Result</code> is <code>Option</code>. Sometimes we don't want to return two possible values, and here you will say "ah, that's a normal function" but <code>Option</code> allows us more than that.</p>
<p>First, it allows us to adapt <code>if</code> logic to decide what to do based on the result obtained. It can be used to return validation of the execution of some operation.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> me = Person(age: <span class="hljs-number">22</span>, name: <span class="hljs-string">'Marcos'</span>);

  <span class="hljs-keyword">final</span> option = getAge(me);

  option.when(
    none: () =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">'None!'</span>),
    some: (age) =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">'Aha! Your age is <span class="hljs-subst">$age</span>'</span>),
  );
}

<span class="hljs-comment">// None!</span>
<span class="hljs-comment">// Aha! Your age is 22</span>
</code></pre>
<p>We have the new classes that implement it: <code>None</code> and <code>Some</code>. <code>None</code> allows us to return an object that represents that the expected action cannot be performed and <code>Some</code> contains the value that the operation performed was expected to return.</p>
<p>See <code>None</code> as a missing value that could not be returned. This helps us to handle general errors and the composition of our code in a more expressive way.</p>
<h3 id="heading-oh-right">Oh right...</h3>
<p><code>Result</code> and <code>Option</code> are structures that are called <strong>monads</strong>. These can be applied to data types to follow a specific sequence of steps. Like when we obtain one of two specific values and execute some action based on what we receive.</p>
<p>The monad types are akin to the <em>sum types</em> found in languages such as <a target="_blank" href="https://ocaml.org">OCaml</a> and <a target="_blank" href="https://www.rust-lang.org">Rust</a>, as found in <code>package:oxidized</code>'s documentation. They encourage safer code by making errors and possible null values (such as <code>None</code>) a necessary part of the code flow, requiring you to deal with these cases appropriately.</p>
<h1 id="heading-closing-remarks">Closing remarks</h1>
<p>You can go much deeper into other functional programming packages if you want. Some of them like <a target="_blank" href="https://pub.dev/packages/dartz"><code>package:dartz</code></a> contains a lot of functionality that comes in handy if you are into math and categorization theories. I consider myself a bit more pragmatic, I quite like this style and I share these small tips with you because I consider it to be useful in any type of project.</p>
<p>Likewise, the monads that we saw have more methods that can be useful to them. They remind me a lot of the methods we have in the classes that we do with <a target="_blank" href="https://marcossevilla.dev/freezed"><code>package:freezed</code></a> but applied to functions --yeah, functional programming-- and their return values.</p>
<p>Very useful to handle different scenarios in your projects, especially possible errors or unforeseen results.</p>
<p><img src="https://media.giphy.com/media/3o7qDT9Yp5DdcN3qi4/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644900121795/t3hdidRMx.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 6: Modeling some data]]></title><description><![CDATA[Once the domain layer and all the general behaviors of our project are finished through abstraction, we can start using all those interfaces that we made to create their implementations.
Well, finally we change layers. This time it's up to the data l...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-6</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-6</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Thu, 04 Feb 2021 17:49:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644291605472/AGU0ZiD4E.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Once the domain layer and all the general behaviors of our project are finished through abstraction, we can start using all those interfaces that we made to create their implementations.</p>
<p>Well, finally we change layers. This time it's up to the data layer, starting with the models.</p>
<h1 id="heading-data-layer">Data layer</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644291472246/XQN5Xtcc-.png" alt="Data Layer" /></p>
<p>In the domain layer, the base were entities. These defined the proper data types in the project and their essential properties.</p>
<p>In the data layer it happens in the same way, we must establish the types of data that we are going to manipulate in the methods that a repository (now implemented) uses when fetching data.</p>
<blockquote>
<p>💡 In this volume, we're going to make a lot of reference to volume 3. If you haven't read it, <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-3"><strong>here</strong></a> you go.</p>
</blockquote>
<p>In this new layer, we have our components that already communicate directly with an external API of any type, be it Firebase, a REST API, etc.</p>
<p>The construction of the data layer is based on first creating the models, then we create the data sources that request data directly and finally we call a data source from the repository to return information, either in primitive data types or models.</p>
<p>I clarify that repositories are implementations of other abstract repositories and models are inheritors of entities (which are classes as such, not interfaces), but that does not mean that data sources are a single class.</p>
<p>The data sources must also have an abstract class to be able to do the same as with the repositories: be able to implement its interface with a different package without affecting any external layer and to be able to perform better tests based on the interface.</p>
<p>Let's get to the models.</p>
<p><img src="https://media.giphy.com/media/l0HlFZ3c4NENSLQRi/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644291473711/MJXPKMGXU.gif" /></p>
<h1 id="heading-models">Models</h1>
<p>I suppose you have already defined some folders in your projects called <strong>models</strong>. Here there isn't much difference, with our entities we wanted to leave as little as possible in properties and methods because our models were going to be in charge of adding that functionality.</p>
<p>A very famous constructor method in Flutter and Dart is the <code>fromJson</code>. This constructor allows us to parse a decoded JSON to a <code>Map</code> and thus serialize our data when we construct the object.</p>
<p>This type of functionality is what a model contains since we can have multiple models that inherit from that entity and define a different behavior based on its implementation. </p>
<p>It also allows us to have entities that can be used regardless of whether it contacts a backend hosted in Firebase or if it is its REST API.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItem</span> </span>{
  StoreItem({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.id,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.name,
  });

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> id;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;
}
</code></pre>
<p><code>StoreItem</code> will be the entity we use as an example. We're going to make our models based on what this entity defines, then we first create a model for the case when it comes from an API, which we are going to name <code>StoreItemAPIModel</code>.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItemModel</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StoreItem</span> </span>{
  StoreItemModel({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> id,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.isAvailable,
  }) : <span class="hljs-keyword">super</span>(id: id, name: name);

  <span class="hljs-keyword">factory</span> StoreItemModel.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> StoreItemModel(
      id: json[<span class="hljs-string">'id'</span>],
      name: json[<span class="hljs-string">'name'</span>],
      isAvailable: json[<span class="hljs-string">'isAvailable'</span>],
    );
  }

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">bool</span> isAvailable;
}
</code></pre>
<p>We only need to extend or inherit from <code>StoreItem</code> to have all our properties. </p>
<p>Notice that the constructor creates the parameters within itself and does not declare properties that we already defined in the entity, we only have to send these variables in the constructor to the parent class called <code>super</code>.</p>
<p>We also add an extra constructor, the popular <code>fromJson</code>. This constructor is the additional functionality that our model will contain for the entity.</p>
<p>And if we want to make another model with the same properties of our entity, it is very easy for us.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:cloud_firestore/cloud_firestore.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItemModel</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StoreItem</span> </span>{
  StoreItemModel({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> id,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.isAvailable,
  }) : <span class="hljs-keyword">super</span>(id: id, name: name);

  <span class="hljs-keyword">factory</span> StoreItemModel.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> StoreItemModel(
      id: json[<span class="hljs-string">'id'</span>],
      name: json[<span class="hljs-string">'name'</span>],
      isAvailable: json[<span class="hljs-string">'isAvailable'</span>],
    );
  }

  <span class="hljs-keyword">factory</span> StoreItemModel.fromFirestore(DocumentSnapshot snapshot) {
    <span class="hljs-keyword">return</span> StoreItemModel.fromJson(snapshot.data() <span class="hljs-keyword">as</span> <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt;);
  }

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">bool</span> isAvailable;
}
</code></pre>
<p>It's the same as we do with the other one but it has different methods since it is oriented to a different service. Similarly, the <code>isAvailable</code> variable that we define remains only in our model, so we must declare it outside the constructor.</p>
<p>Another thing that we can remark from this model is that we must also implement another <code>fromJson</code> because it doesn't extend from our previous class and the constructors remain at the model level.</p>
<p>This last action can be somewhat annoying and repetitive. To use the <code>fromJson</code> constructor we would have to inherit from <code>StoreItemAPIModel</code>, but it still gets complicated when calling the other constructor. From this last paragraph, stick with the first statement and ignore the rest as it is a complete mess.</p>
<h1 id="heading-best-ways-to-create-models">Best ways to create models</h1>
<p>The way we saw for creating models previously it's plenty for us. But this doesn't mean that the same cannot be automated. There are two packages that I use a lot for my models and in general, any immutable class that it has (a state, for example).</p>
<h1 id="heading-equatable-jsonserializable">Equatable + json_serializable</h1>
<p>I'm going to talk to you about <a target="_blank" href="https://pub.dev/packages/equatable"><code>package:equatable</code></a>. So far this is the package with which I make entities and, consequently, models. It allows us to create a class whose properties don't change, in addition to giving us a method that we must overwrite called <code>props</code>, this returns a list with the properties we want of the class. Very useful and complete.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:equatable/equatable.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItemEquatable</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Equatable</span> </span>{
  StoreItemEquatable({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.id,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.name,
  });

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> id;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;

  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Object</span>&gt; <span class="hljs-keyword">get</span> props =&gt; [id, name];
}
</code></pre>
<p>Once our entity is created, I suggest you combine Equatable with <a target="_blank" href="https://pub.dev/packages/json_serializable"><code>package:json_serializable</code></a> and <a target="_blank" href="https://pub.dev/packages/json_annotation"><code>package:json_annotation</code></a> to create your models with the <code>fromJson</code> constructor and the<code>toJson</code> method to be able to serialize from any API that returns in JSON format.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:json_annotation/json_annotation.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'store_item_equatable.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'store_item_model.g.dart'</span>;

<span class="hljs-meta">@JsonSerializable</span>()
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItemModel</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StoreItemEquatable</span> </span>{
  StoreItemModel({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> id,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
  }) : <span class="hljs-keyword">super</span>(id: id, name: name);

  <span class="hljs-keyword">factory</span> StoreItemModel.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> _$StoreItemModelFromJson(json);
  }

  <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; toJson() =&gt; _$StoreItemModelToJson(<span class="hljs-keyword">this</span>);
}
</code></pre>
<p>I remind you that <code>json_serializable</code> must generate the code in a file with the extension <code>**.g.dart</code>. To generate the code, you must run the command:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># if your project depends on the Flutter SDK</span>
flutter pub run build_runner build

<span class="hljs-comment"># if your project doesn't depend on the Flutter SDK, it is written in pure Dart</span>
pub run build_runner build
</code></pre>
<p>Likewise, if we want to create our model for Firestore, we just extend the model we created earlier to use its <code>fromJson</code> constructor and that's it.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'package:cloud_firestore/cloud_firestore.dart'</span> <span class="hljs-keyword">show</span> DocumentSnapshot;

<span class="hljs-keyword">import</span> <span class="hljs-string">'store_item_model.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItemFirestore</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StoreItemModel</span> </span>{
  StoreItemFirestore({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> id,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
  }) : <span class="hljs-keyword">super</span>(id: id, name: name);

  <span class="hljs-keyword">factory</span> StoreItemFirestore.fromFirestore(DocumentSnapshot doc) {
    <span class="hljs-keyword">return</span> StoreItemModel.fromJson(doc.data()!);
  }
}
</code></pre>
<p>Although Equatable checks the essentials, and well, it doesn't include an important method of immutable classes: <code>copyWith</code>. For this reason, I'm going to show you the second alternative.</p>
<h1 id="heading-freezed">Freezed</h1>
<p>To solve the problem of how long it takes to create all those constructors, <a target="_blank" href="https://pub.dev/packages/freezed"><code>package:freezed</code></a> is a great option. To know more about this package, you can see my article <a target="_blank" href="https://marcossevilla.dev/freezed">here</a>.</p>
<p><code>freezed</code> includes the following:</p>
<ul>
<li>Immutability (<code>copyWith</code> included).</li>
<li>Value equality.</li>
<li>Unions.</li>
<li>Support for <code>json_serializable</code>.</li>
</ul>
<p>So we can define all the models in the same abstract class and use the methods on themselves like this...</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:cloud_firestore/cloud_firestore.dart'</span> <span class="hljs-keyword">show</span> DocumentSnapshot;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:freezed_annotation/freezed_annotation.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'store_item.freezed.dart'</span>;
<span class="hljs-keyword">part</span> <span class="hljs-string">'store_item.g.dart'</span>;

<span class="hljs-meta">@freezed</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StoreItem</span> <span class="hljs-title">with</span> <span class="hljs-title">_</span>$<span class="hljs-title">StoreItem</span> </span>{
  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> StoreItem.model({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> id,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
  }) = StoreItemModel;

  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> StoreItem.firestore({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> id,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">bool</span> isAvailable,
  }) = StoreItemFirestore;

  <span class="hljs-keyword">factory</span> StoreItem.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) =&gt;
      _$StoreItemFromJson(json);

  <span class="hljs-keyword">factory</span> StoreItem.fromFirestore(DocumentSnapshot doc) {
    <span class="hljs-keyword">return</span> StoreItemFirestore.fromJson(doc.data());
  }
}
</code></pre>
<p>But not everything is pretty on Freezed, do you notice the problem?</p>
<p>Sure, unions are great for creating all possible constructors without having to create several separate files. But this separation of classes and files is what allows us to have separate entities and models.</p>
<p><a target="_blank" href="https://stackoverflow.com/questions/63285384/flutter-dart-subclass-a-freezed-data-class"><strong>A <code>freezed</code> class cannot be a subclass of another</strong></a> and try to extend the functionality of a <code>freezed</code> class is a time investment that isn't worth it and we lose the time we saved generating the code.</p>
<h1 id="heading-equatable-or-freezed">Equatable or Freezed?</h1>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:models_sample/store_item.dart'</span> <span class="hljs-keyword">as</span> equatable;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:models_sample/store_item_model.dart'</span> <span class="hljs-keyword">as</span> freezed;

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> aModel = equatable.StoreItemModel.fromJson(
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Computer'</span>},
  );

  <span class="hljs-keyword">final</span> bModel = freezed.StoreItemModel.fromJson(
    {<span class="hljs-string">'id'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Computer'</span>},
  );
}
</code></pre>
<p>It really has been a matter of personal preference since the result is very similar. But in the case of <strong>CleanScope</strong>, we prefer to use <code>equatable</code> for entities and models, as it allows us better abstraction and control over the code.</p>
<p>Equatable has the <code>props</code> method which is very useful in many cases. <code>freezed</code> has built-in the <code>copyWith</code> and many other methods that I detail in the article that I quoted earlier, such as the <code>when</code>, <code>maybeWhen</code>, <code>map</code>, <code>maybeMap</code>.</p>
<p>We love <code>freezed</code> we use it to generate the states for the logic in the presentation layer, but it doesn't satisfy us for the level of attraction we need in the models. It's a limitation with code generators, they take away control over your code to a certain extent.</p>
<p>When we finish this series of articles, we'll propose a minimalist version of <strong>CleanScope</strong> where we'll use <code>freezed</code> for the models as we will have fewer layers of abstraction. But that's going to be another time.</p>
<blockquote>
<p>For the moment, we're sticking with <code>equatable</code> for our models, in conjunction with <code>json_serializable</code>.</p>
</blockquote>
<p><img src="https://media.giphy.com/media/FA77mwaxV74SA/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644291482087/H-u9QuXBp.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 5: Establishing use cases]]></title><description><![CDATA[💡 Note: This article was originally posted in my friend Elian's blog and has been slightly modified for this series. You can check the original here.

Hello and welcome to the last volume where we will talk about the domain layer of our Clean Archit...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-5</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-5</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[architecture]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Sun, 31 Jan 2021 17:18:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644202647262/41Y87UOZs.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>💡 Note: This article was originally posted in my friend Elian's blog and has been slightly modified for this series. You can check the original <a target="_blank" href="https://elianortega.dev/cleaner-flutter-vol-5-establishing-use-cases">here</a>.</p>
</blockquote>
<p>Hello and welcome to the last volume where we will talk about the domain layer of our Clean Architecture proposal. Last time we talked about a fundamental part: the repositories, which allow us to create the communication of our software with the outside world.</p>
<p>On this occasion, with the use cases we are going to achieve independence from the specific interactions of the user with the system, using use cases and thus obtain maintainable, reusable code that truly meets the needs of the business.</p>
<p>But before we get into technical matters, we must remember that there are 2 perspectives: a developer's and a business perspective of the product. This differentiation is a very important topic since by being clear about the objectives of the product we can develop software in a better way.</p>
<p>Remember that all software products should first go through a process where their requirements and the interactions of a user with the software product are defined, whether this is a <code>login</code>, <code>addToShoppingCart</code>, or <code>processPayment</code>.</p>
<p>Ok, let's get into it.</p>
<h1 id="heading-what-are-use-cases">What are use cases?</h1>
<p>In Uncle Bob's words...</p>
<blockquote>
<p>The software in this layer contains the application-specific business rules. These encapsulate and implement all the use cases of the system.</p>
</blockquote>
<p>I remind you that the use cases mentioned in the definition do not refer coding part or module, but to the use cases that came from de planning phase of the project.  </p>
<p>Each event is an interaction of the user with the system and we can call this a use case. As this is also a business concept the most common way of displaying the use cases of the system is by the use case graph, which looks like this:</p>
<p><img src="https://miro.medium.com/max/643/0*D5fgzZp_5AeUFkKP.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644202527553/Gfe1voQba.png" /></p>
<p>Taken from <a target="_blank" href="https://warren2lynch.medium.com/use-case-tutorial-for-dummies-8cf426043710">Use Case Tutorial for Dummies</a>.</p>
<p>Here we have objects like:</p>
<ul>
<li><code>Actor</code>: Users who interact with the system (might be another software too).</li>
<li><code>UseCase</code>: How the actor uses the system to fulfill some functionality.</li>
<li><code>Relationship</code>: The relationship between the actors and the use cases.</li>
</ul>
<p>The example shows some use cases for a passenger at an airport. Which, as I mentioned before, is the user's interactions with the system, in this case, the logic of an airport.</p>
<h1 id="heading-in-code">In code</h1>
<p>In my experience, I have noticed that the use case layer is usually bypassed and replaced using methods directly in the software's business logic. But when we implement it we achieve better decoupling and other advantages.</p>
<p>By adding the use cases layer the folder structure for the domain layer would look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644202529006/gUDaTXF2V.png" alt="Folder Structure" /></p>
<h1 id="heading-complying-with-the-principles">Complying with the principles</h1>
<p><strong>They end up being simpler repositories</strong>. When we create the use cases, we manage to facilitate communication with the repositories and we make sure to have better abstractions that meet the specific objective of that use case, and as we saw in previous articles, with this we comply with the single responsibility principle.</p>
<p><strong>We use interfaces, not implementations</strong>. In use cases we are normally going to depend on a repository, which rather must be an interface, this way we would be complying with the Liskov substitution principle, since we could replace the repository with any other that implements the same interface and this will not affect the base logic of our use case.</p>
<h1 id="heading-implementing-in-dart">Implementing in Dart</h1>
<p>Like any of the components we've talked about throughout the series, each can be implemented in many ways. This time with the use cases we are going to use one of Dart's not very well-known features.</p>
<p>In Dart, there is something called callable classes. This allows us to use the instance of a class as if it were a function. To achieve this, all we have to do is implement the <code>call</code> method inside the class.</p>
<p>We get something like this:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CallableClass</span> </span>{
  <span class="hljs-built_in">String</span> call() =&gt; <span class="hljs-string">'Thanks for calling!'</span>;
}

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> callable = CallableClass();
  <span class="hljs-built_in">print</span>(callable()); <span class="hljs-comment">// Thanks for calling!</span>
}
</code></pre>
<p>Using this Dart feature, we can create a class for each of our use cases and implement the call method with the respective functionality.</p>
<h1 id="heading-putting-the-pieces-together">Putting the pieces together</h1>
<p>With all the information we have, we can already see an example with all the pieces that we have carried so far: entities, repositories, and use cases.</p>
<p>The code is simplified to facilitate the example. I also remind you that to understand the examples you must read the previous articles. <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-4">Here's</a> the previous one.</p>
<p>Let's imagine a very simple case of a <code>signIn</code>, for this, we are going to have a user entity and a repository interface that contains a method to make the <code>signIn</code> using an email and password.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">const</span> User({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.email,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.password,
  });

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> email;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> password;
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthRepositoryInterface</span> </span>{
  Future&lt;User&gt; signIn({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> email,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> password,
  });
}
</code></pre>
<p>This is where many developers decide not to implement the use case layer, so they call the repositories directly from the application's business logic.</p>
<p>But since we are using use cases, we create a <code>SignInUser</code> class which will be our use case. This will have a dependency on the <code>AuthRepositoryInterface</code>, then we implement the <code>call</code> method and call <code>signIn</code>. And so we have a use case with sole responsibility and decouple the repositories from the business logic (state manager).</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserSignIn</span> </span>{
  <span class="hljs-keyword">const</span> UserSignIn({
    <span class="hljs-keyword">required</span> AuthRepositoryInterface authRepository,
  }) : _authRepository = authRepository;

  <span class="hljs-keyword">final</span> AuthRepositoryInterface _authRepository;

  Future&lt;User&gt; call({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> email,
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> password,
  }) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> _authRepository.signIn(
      email: email,
      password: password,
    );
  }
}
</code></pre>
<blockquote>
<p>It doesn't matter who wins the endless battle of which is the best state management tool, since it does not matter which one we select. If we even decide to change, this does not affect our implementation at all.</p>
</blockquote>
<p>This example is quite simple, but for the moment what we are trying to do is understand each of the components that are part of this Clean Architecture proposal. Later we will make examples and videos applying all the theories with production code.</p>
<p><img src="https://media.giphy.com/media/fnDY3C9MKukcER71r7/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644202538047/N01kK9lvy.gif" /></p>
<hr />
<p>If you liked <a target="_blank" href="https://elianortega.dev/">Elian</a>'s content, you can find even more and keep in touch with him on his social networks:</p>
<ul>
<li><a target="_blank" href="https://github.com/elian-ortega">GitHub</a>.</li>
<li><a target="_blank" href="https://www.linkedin.com/in/elian-ortega">LinkedIn</a>.</li>
<li><a target="_blank" href="https://twitter.com/ElianOrtegaNCA">Twitter</a>.</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCPz6bJ3DptMMXu7_hMb1oJQ">YouTube</a>.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Freezed, or even more code generation]]></title><description><![CDATA[I have already told you about all the benefits and why you should use code generation tools in your projects. If you haven't seen my article on FlutterGen, I'll leave it for you here.
So I'm not going to give you an introduction to generating code, r...]]></description><link>https://marcossevilla.dev/freezed</link><guid isPermaLink="true">https://marcossevilla.dev/freezed</guid><category><![CDATA[code]]></category><category><![CDATA[generators]]></category><category><![CDATA[Dart]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Mon, 25 Jan 2021 21:02:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643936296101/9mfxmN8IH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have already told you about all the benefits and why you should use code generation tools in your projects. If you haven't seen my article on <strong>FlutterGen</strong>, I'll leave it for you <a target="_blank" href="https://marcossevilla.dev/flutter-gen">here</a>.</p>
<p>So I'm not going to give you an introduction to generating code, rather we are going to know a very good tool to generate it. This tool is called <code>freezed</code>.</p>
<p><code>freezed</code> comes to be a code generator for immutable classes and was created by Rémi Rousselet, who may know him more from <a target="_blank" href="https://pub.dev/packages/provider"><code>package:provider</code></a>.</p>
<h1 id="heading-immutability">Immutability</h1>
<p>Immutable classes --as the name implies-- are classes that don't change their properties and this feature is very good for state management and for use in data models. Although you may not notice it, you surely have already used immutable classes.</p>
<p>Take a look at this example...</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-keyword">void</span> main() {
  runApp(
    MaterialApp(
      home: MyWidget(),
    ),
  );
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      body: Center(
        child: Text(
          <span class="hljs-string">'Build some widgets!'</span>,
          style: Theme.of(context).textTheme.headline4!.copyWith(
                color: Colors.red,
              ),
        ),
      ),
    );
  }
}
</code></pre>
<p>Here we can see that we access the global theme of our app, specifically the property of the <code>textTheme</code> or text theme. The <code>headline4</code> object contains a default setting that cannot be changed, that is, it is immutable.</p>
<p>That's where the <code>copyWith</code> comes in. This method allows us to return an instance of the same class or an identical object to which we are applying the method, but with the possibility of changing one or more properties as we want.</p>
<p>In the previous example, it allows us to change the color of the <code>headline4</code> by means of<code>copyWith</code>.</p>
<p>And maybe at this point, you are wondering: why do I want immutable objects if I can easily assign another value to a certain property of the object?</p>
<p>Yes, correct. You can do an assignment easily in this case, but the problem is that the properties are exposed and your code becomes "easy to fool" I would call it. This is used quite a bit in state management because it is much better to change state through functions and not have access to internal properties so as not to change them outside of your class.</p>
<p>This even goes back to the <strong>Encapsulation principle</strong> of Object-Oriented Programming, where properties must be private and accessed or modified by means of methods. However, here we don't do getters and setters, we allow access to the variables through a specific state that contains them. All this without exposing our logic component.</p>
<p>The last thing I mentioned is very typical of state management using <code>StateNotifier</code>, which I use with <a target="_blank" href="https://pub.dev/packages/riverpod"><code>package:riverpod</code></a>. In a moment you will understand what I am talking about, if you have not read my article about StateNotifier, I will leave it <a target="_blank" href="https://marcossevilla.dev/statenotifier"><strong>here</strong></a>.</p>
<h1 id="heading-value-equality">Value Equality</h1>
<pre><code class="lang-yaml"><span class="hljs-comment"># Dependencies to include in pubspec.yaml</span>
<span class="hljs-attr">dependencies:</span>
  <span class="hljs-attr">freezed_annotation:</span>

<span class="hljs-attr">dev_dependencies:</span>
  <span class="hljs-attr">build_runner:</span> 
  <span class="hljs-attr">freezed:</span>
</code></pre>
<p>Leaving out a bit of immutability, Freezed not only helps you make objects immutable but also implements value equality.</p>
<p>If you directly compare two equal instances (in properties), when you run the program it will not return true. Look:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SomeClass</span> </span>{
  SomeClass({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.id});

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> id;
}

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">final</span> first = SomeClass(id: <span class="hljs-number">0</span>);
  <span class="hljs-keyword">final</span> second = SomeClass(id: <span class="hljs-number">0</span>);

  <span class="hljs-built_in">print</span>(first == second);
}
</code></pre>
<p>Run that code on <a target="_blank" href="https://dartpad.dev/"><strong>DartPad</strong></a> and you will see that it prints false, even though both objects contain the same id and are essentially the same.</p>
<p><code>freezed</code> overrides the equality operator (<code>==</code>) and the <code>hashCode</code> getter, that way, we can already compare two or more objects and get true. This is very useful for checks on higher-level layered objects.</p>
<p>We only have to create a class with the decorator <code>@freezed</code> from the <a target="_blank" href="https://pub.dev/packages/freezed_annotation"><code>package:freezed_annotation</code></a>, so that Freezed knows that it should generate code for this class.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:freezed_annotation/freezed_annotation.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'user.freezed.dart'</span>;

<span class="hljs-meta">@freezed</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-title">with</span> <span class="hljs-title">_</span>$<span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">factory</span> User({<span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name, <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> age}) = _User;
}
</code></pre>
<p>Once this abstract class <code>User</code> is made, we make a <a target="_blank" href="https://medium.com/flutter-community/dart-what-are-mixins-3a72344011f3"><strong>mixin</strong></a> with the class that Freezed will generate. We call this generated class <code>_$User</code> first because we make it private with<code>_</code> so that it can only be accessed from its own file and we also use<code>$</code>because it is a convenience to indicate this symbol so that the generated classes don't have the same name of the classes that we create.</p>
<p>Finally, our <code>factory</code> constructor of<code>User</code> is the class we would use in our code. We can create different constructors like the typical <code>fromJson</code> and we can also create our own methods. We will see this in serialization, meanwhile, we generate our code.</p>
<p><img src="https://media.giphy.com/media/wkfU652r5hLAxZL8LG/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1643935780829/apG4lj7zU.gif" /></p>
<h1 id="heading-generating-the-code">Generating the code</h1>
<p>To generate the code we include a dependency called <code>build_runner</code>, which is in charge of running the code generators that are in the project. Have a reference <code>build_runner</code> for other times that use code generators, I didn't recommend it when we talked about <a target="_blank" href="https://marcossevilla.dev/fluttergen">FlutterGen</a> because sometimes it can give version problems.</p>
<p>Leave all the dependencies that you include without a specific version, thus avoiding compatibility errors between the versions.</p>
<p>Anyway, the command to run in the root of the project is the following:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># if the project depends on Flutter SDK</span>
flutter pub run build_runner build

<span class="hljs-comment"># if the project doesn't depend on Flutter - if it's pure Dart</span>
pub run build_runner build
</code></pre>
<p>Every time you make a change to your classes you will have to run one of these commands to see the changes in your generated code, in case there are errors.</p>
<p>As a small note, if your project uses a linter like <a target="_blank" href="https://pub.dev/packages/very_good_analysis"><code>very_good_analysis</code></a>, I suggest you add these lines to your <code>analysis_options.yaml</code>, that way you don't have errors in your generated files:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">analyzer:</span>
  <span class="hljs-attr">exclude:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">"**/*.g.dart"</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">"**/*.freezed.dart"</span>
</code></pre>
<h1 id="heading-serialization">Serialization</h1>
<p>Data serialization is an essential part of the models since most apps contact third-party services or custom APIs that return responses in JSON format.</p>
<p>We decode these JSONs thanks to the <code>dart:convert</code> module that is already included in Dart, but then we have the need to locate each property of the decoded map that we have left in a data model.</p>
<p>That's where the <code>fromJson</code> constructor comes into play in our classes, which allows us to translate our map into a class, we add it like this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:freezed_annotation/freezed_annotation.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'user.freezed.dart'</span>;
<span class="hljs-keyword">part</span> <span class="hljs-string">'user.g.dart'</span>;

<span class="hljs-meta">@freezed</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-title">with</span> <span class="hljs-title">_</span>$<span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">factory</span> User({<span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name, <span class="hljs-keyword">required</span> <span class="hljs-built_in">int</span> age}) = _User;

  <span class="hljs-comment">// fromJson constructor</span>
  <span class="hljs-keyword">factory</span> User.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) =&gt; _$UserFromJson(json);
}
</code></pre>
<p>We add a new <code>part</code> directive that will be from the JSON serializable file, and then we add the new <code>factory</code> that we will have for serialization.</p>
<p><code>freezed</code> doesn't do this serialization to JSON on its own, it needs us to include the package <code>json_serializable</code> the<code>dev_dependencies</code> from <code>pubspec.yaml</code>.</p>
<p>It can go under <code>freezed</code>.</p>
<p>I have already presented you with many of the very powerful main features that <code>freezed</code> has, now we are going to the last one that I think is one of the coolest that saves many lines of code.</p>
<h1 id="heading-unions">Unions</h1>
<p><img src="https://media.giphy.com/media/pHb82xtBPfqEg/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1643935782813/iwHg5IfxPr.gif" /></p>
<p>Unions are a feature that Freezed brings to Dart from other languages like Kotlin. In Kotlin they are called sealed classes. Even the syntax that Freezed offers is very similar.</p>
<p>They are classes that implement a certain abstract class and include a "switch" in their parent class to define actions based on what implementation it is.</p>
<p>This last detail reduces the code a lot and I personally use it to define the states of my logic component. Something like this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:freezed_annotation/freezed_annotation.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'common_state.freezed.dart'</span>;

<span class="hljs-meta">@freezed</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommonState</span> <span class="hljs-title">with</span> <span class="hljs-title">_</span>$<span class="hljs-title">CommonState</span> </span>{
  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> CommonState(<span class="hljs-built_in">int</span> value) = Data;

  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> CommonState.loading() = Loading;

  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> CommonState.error([<span class="hljs-built_in">String?</span> message]) = ErrorDetails;
}
</code></pre>
<p>And then we can use the <code>when</code> or<code>maybeWhen</code> methods to perform an operation based on any of those cases, like this:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">const</span> state = CommonState(<span class="hljs-number">42</span>);

state.maybeWhen(
    <span class="hljs-keyword">null</span>,
    loading: () =&gt; <span class="hljs-string">'loading'</span>,
    error: (error) =&gt; <span class="hljs-string">'<span class="hljs-subst">$error</span>'</span>,
    orElse: () =&gt; <span class="hljs-string">'fallback'</span>,
);
</code></pre>
<p>One of the most popular dependency injection and state management packages, <a target="_blank" href="https://riverpod.dev/"><code>riverpod</code></a>, uses <code>freezed</code> to define its providers as sealed classes and is thus much easier in syntax handling widgets in Flutter that reacts to a specific state.</p>
<p>But as I always say, read the <a target="_blank" href="https://github.com/rrousselGit/freezed">documentation</a>, this is a small introduction so that you know what it is about, what you can do, and above all, lose your fear to explore it.</p>
<p><img src="https://media.giphy.com/media/xUPOqo6E1XvWXwlCyQ/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1643935784645/aKoHvPFgV.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[StateNotifier, ValueNotifier outside Flutter]]></title><description><![CDATA[Whether you are just starting out or have been using Flutter for a few years, there's one topic that always comes up and has a thousand perspectives revolving around it: state management.
State management is essential in Flutter. Many confuse it with...]]></description><link>https://marcossevilla.dev/state-notifier</link><guid isPermaLink="true">https://marcossevilla.dev/state-notifier</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter Widgets]]></category><category><![CDATA[state]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Mon, 25 Jan 2021 04:36:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643935854132/1-9Xq1c96.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whether you are just starting out or have been using Flutter for a few years, there's one topic that always comes up and has a thousand perspectives revolving around it: state management.</p>
<p>State management is essential in Flutter. Many confuse it with architecture or believe that architecture depends on a specific state handler. But the truth is that state management is a small part of the great architecture that a project can have.</p>
<p>On previous occasions I have already spoken enough on this subject, so I better leave you references to these talks that I have given:</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=2vuN03XXfcw"><strong>Flutter's Six Paths of State</strong></a> (yes, it's a reference to Naruto): It will help you to contemplate different alternatives to manage state in Flutter and choose the one that makes your life easier.</li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=_J3M7jHbKSQ&amp;t=900s"><strong>Talking about State Management + Architecture</strong></a>: It will help you to see what role the state management of your app plays in the architecture of it and serves as a critique for Six Paths of State.</li>
</ul>
<blockquote>
<p>😓 The videos I'll quote or suggest you watch are in Spanish because that's my main language. So I apologize for that.</p>
</blockquote>
<p><img src="https://media.giphy.com/media/KcVny4iEXBr7NEsSv7/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1643931809914/xzkvDd_Ak.gif" /></p>
<h1 id="heading-first-of-all-provider">First of all, Provider</h1>
<p>You're probably already familiar with <a target="_blank" href="https://pub.dev/packages/provider"><code>package:provider</code></a>, which isn't a state manager, but a friendlier way to use <code>InheritedWidget</code>. If you don't know anything about <code>InheritedWidget</code>, <a target="_blank" href="https://www.youtube.com/watch?v=FAL7oGld0YQ&amp;t=246s">here</a> you go.</p>
<p>Simply put, <code>provider</code> allows us to use <code>InheritedWidgets</code> to work with classes or more atomically, values, to handle our state. That makes it a tool for communication between widgets, or dependency injection, not for state management as such.</p>
<p>If at this precise moment I'm destroying the concept you had of <code>provider</code>, I'm accomplishing my mission. The plan is not to confuse you, it is for you to better understand why use <code>state_notifier</code>, which is the subject of this article. We'll get to that, calm down.</p>
<p><code>provider</code> itself can provide you with information, just like an <code>InheritedWidget</code> does. But the state managers are the classes that contain the data that <code>Provider</code> has. Got it?</p>
<blockquote>
<p>BLoC → BLoC pattern</p>
<p>bloc → Library to manage states implementing BLoC</p>
<p>flutter_bloc → package containing the widgets to integrate bloc with Flutter</p>
</blockquote>
<p>I call BLoCs or business logic components to those classes. They're in charge of managing this information interacting with external data sources (an API, for example) through data access classes (services or repositories). And basically, the BLoC pattern is followed there. I also have a video talking about it <a target="_blank" href="https://www.youtube.com/watch?v=L5otbgl9vlk">here</a>.</p>
<p>The classes used with <code>Provider</code> are usually <code>ChangeNotifier</code>, <code>ValueNotifier</code>; or some custom class that extends from these. They're classes that notify --as their names say-- to others (widgets included) that are consuming their properties (through <code>Providers</code>). That's the most typical and one of the simplest and most initial ways of handling state with Flutter.</p>
<blockquote>
<p>I clarify, there are other packages that use <code>provider</code> for communication of its logic components with its user interfaces.</p>
<p>Some of them are <a target="_blank" href="https://pub.dev/packages/bloc"><code>package:bloc</code></a> in its sibling <a target="_blank" href="https://pub.dev/packages/flutter_bloc"><code>package:flutter_bloc</code></a>, and <a target="_blank" href="https://pub.dev/packages/mobx"><code>package:mobx</code></a>.</p>
</blockquote>
<h1 id="heading-the-problem">The problem</h1>
<blockquote>
<p>The problem is not <code>ChangeNotifier</code>, the problem is that it depends on Flutter.</p>
</blockquote>
<p><code>ChangeNotifier</code> is a good alternative to create classes that serve as BLoC. But as you may know about me --if you read my other articles-- I really enjoy modularizing my code to extract my logic in other packages and making them as uncoupled as possible, that's when it's not enough for me. This is mostly because of its dependency on Flutter.</p>
<p>I like to create my packages separately with the least amount of dependencies possible. If I can avoid the Flutter SDK, better.</p>
<p>I propose this case...</p>
<blockquote>
<p>🤔 I'm creating my app logic in Flutter that I can reuse with other interfaces, so I make it a package. That same logic is useful to me for another app that allows me to call Dart code directly, let's remember that Dart can be compiled into binary and that opens it up to more use cases than just apps with Flutter. I already have the logic, but I use ChangeNotifier, which makes me unnecessarily dependent on Flutter.</p>
</blockquote>
<p><img src="https://i.redd.it/z26wpq3ddm121.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1643931812122/IQawO34wi.jpeg" /></p>
<h1 id="heading-hello-statenotifier">Hello StateNotifier</h1>
<p><code>StateNotifier</code> is another type of class that serves as a logic component and is a "reimplementation" of <code>ValueNotifier</code>, with the difference that it doesn't depend on Flutter.</p>
<p>This package with the functionality of <code>ValueNotifier</code> abstracted gives us the power to reuse our logic without depending on Flutter, as we wanted. Plus it has better integration with <code>provider</code> via <a target="_blank" href="https://pub.dev/packages/flutter_state_notifier"><code>package:flutter_state_notifier</code></a> because both were made by the same author.</p>
<p>After having learned a lot about <code>flutter_bloc</code> and its structure, I understood how handling states as classes were much more convenient and helped to modularize your widgets based on the current state of the <code>Bloc</code>.</p>
<p><code>StateNotifier</code> has a lot of things similar to Bloc, including:</p>
<ul>
<li>Initial state in the base constructor.</li>
<li>Changes to the state through methods.</li>
</ul>
<p>Actually, the last one is related to <code>Cubit</code> not <code>Bloc</code>.</p>
<blockquote>
<p>💡 One difference is that <code>StateNotifier</code> assigns the state to the protected variable <code>state</code> (equivalent to <code>value</code> in <code>ValueNotifier</code>) and <code>Bloc</code> uses the <code>Emitter</code> class to emit a state, which uses Stream underneath.</p>
</blockquote>
<h1 id="heading-how-to-use-statenotifier">How to use StateNotifier</h1>
<ol>
<li>We install the dependencies.</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">dependencies:</span>
    <span class="hljs-comment"># * if you use Provider</span>
    <span class="hljs-attr">provider:</span>
    <span class="hljs-attr">state_notifier:</span>
    <span class="hljs-attr">flutter_state_notifier:</span>

    <span class="hljs-comment"># * if you use `riverpod`, already includes `state_notifier`</span>
    <span class="hljs-attr">flutter_riverpod:</span>

    <span class="hljs-comment"># use the latest versions of these dependencies or </span>
    <span class="hljs-comment"># the ones compatible with the rest of your project</span>
</code></pre>
<ol>
<li>We create the states.</li>
</ol>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserState</span> </span>{}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserNotLogged</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">UserState</span> </span>{}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserLogged</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">UserState</span> </span>{
  UserLogged({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.user});
  <span class="hljs-keyword">final</span> User user;
}
</code></pre>
<ol>
<li>We create our StateNotifier.</li>
</ol>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserStateNotifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StateNotifier</span>&lt;<span class="hljs-title">UserState</span>&gt; </span>{
  <span class="hljs-comment">// we create our initial state by passing it to super, just like `bloc`.</span>
  UserStateNotifier() : <span class="hljs-keyword">super</span>(UserNotLogged());

  <span class="hljs-comment">// we change state assigning a new one to the state property.</span>
  <span class="hljs-keyword">void</span> logIn(User user) =&gt; state = UserLogged(user: user);
}
</code></pre>
<ol>
<li>We inject and then consume our StateNotifier.</li>
</ol>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  runApp(
    StateNotifierProvider&lt;UserStateNotifier, UserState&gt;(
      create: (_) =&gt; UserStateNotifier(),
      child: MyApp(),
    ),
  );
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">final</span> userState = context.watch&lt;UserStateNotifier&gt;();
    <span class="hljs-keyword">return</span> Scaffold(
      body: Center(
        child: Text(<span class="hljs-string">'<span class="hljs-subst">${userState.runtimeType}</span>'</span>),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.read&lt;UserStateNotifier&gt;().logIn(User());
        },
      ),
    );
  }
}
</code></pre>
<p>And that's a simple example of how to start using <code>StateNotifier</code> instead of <code>ChangeNotifier</code> or ValueNotifier. </p>
<p>You can see that another <code>flutter_state_notifier</code> package is used. As well as other packages like <code>bloc</code> and <code>flutter_bloc</code>, a package with the prefix <em>flutter</em> is included since this is the one that contains widgets that are useful to integrate another package with your user interface. In this case, it works for us to use the <code>StateNotifierProvider</code> class.</p>
<h1 id="heading-creating-better-states">Creating better states</h1>
<p>You can see that we created an abstract state that can be used by any class through inheritance. This is a practice that I first saw in <code>bloc</code>, where defined events alter the current state of a <code>Bloc</code>. It's very good because we define in the <code>Bloc</code> that we're going to send a state that inherits from an abstract state, as we saw in the example.</p>
<p>With <code>StateNotifier</code>, this is excellent when passing a specific type of data (our abstract state) and assigning it as we need.</p>
<p>The problem with this is that it gets a bit slow and we write boilerplate code when we have several possible states. For this reason, we are including another package called <a target="_blank" href="https://pub.dev/packages/freezed"><code>package:freezed</code></a>, which works amazingly with <code>StateNotifier</code>.</p>
<p>We can simplify the code with a union, it would look like this...</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:freezed_annotation/freezed_annotation.dart'</span>;

<span class="hljs-keyword">part</span> <span class="hljs-string">'user_state.freezed.dart'</span>;

<span class="hljs-meta">@freezed</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserState</span> <span class="hljs-title">with</span> <span class="hljs-title">_</span>$<span class="hljs-title">UserState</span> </span>{
  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> UserState(User user) = UserLogged;
  <span class="hljs-keyword">const</span> <span class="hljs-keyword">factory</span> UserState.notLogged() = UserNotLogged;
}
</code></pre>
<p>If you would like to know more about <code>freezed</code> to know how to autogenerate the above code and what it means, I suggest you read my article about this package <a target="_blank" href="https://marcossevilla.dev/freezed">here</a>.</p>
<h1 id="heading-goodbye-changenotifier-and-valuenotifier">Goodbye ChangeNotifier and ValueNotifier?</h1>
<p>Not really.</p>
<p>Rémi Rousselet, the creator of <code>provider</code>, <code>state_notifier</code>, and <code>freezed</code>; has maintained and created pull requests to the official Flutter repository to improve <code>ChangeNotifier</code>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/fluttermerge/status/1294428072717045761">https://twitter.com/fluttermerge/status/1294428072717045761</a></div>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/fluttermerge/status/1298692196951044099">https://twitter.com/fluttermerge/status/1298692196951044099</a></div>
<p>So it doesn't mean that StateNotifier is a successor. As usual:</p>
<blockquote>
<p>It's one more option that you can choose.</p>
</blockquote>
<p>I personally use <code>StateNotifier</code> with <a target="_blank" href="https://pub.dev/packages/riverpod"><code>riverpod</code></a>, the <code>provider</code> rewrite, and I quite like the combination as it includes it by default. Handling states much like the way <code>flutter_bloc</code> does seem very convenient and makes code more predictable, which is very good. All this added to the fact that the state assignment syntax is simpler and facilitates its emission.</p>
<p><img src="https://i.redd.it/jvm0gl943b121.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1643931813602/1rRCshdhq.jpeg" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 4: Hiring repositories]]></title><description><![CDATA[Welcome back to Cleaner Flutter, I hope you have been enjoying this series so far and are learning a lot.

💡 Remember to show your support with applause or reaction and share so that more people can have access to this information.

In the previous ...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-4</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-4</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter SDK]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[repository]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Fri, 15 Jan 2021 21:27:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644200654142/gFPG9jWex.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome back to <strong><em>Cleaner Flutter</em></strong>, I hope you have been enjoying this series so far and are learning a lot.</p>
<blockquote>
<p>💡 Remember to show your support with applause or reaction and share so that more people can have access to this information.</p>
</blockquote>
<p>In the previous volume, we talked about entities and started looking at the domain layer. As you see in the title, we're going to continue with repositories... and we continue to make contracts. If you don't know what they are, you can see it in the previous volume.</p>
<p>But before we get into repositories, I want to present something that I hadn't shown you before so you can understand the Clean structure that we are implementing and compare it with some other ones.</p>
<h1 id="heading-cleanscope">CleanScope</h1>
<p>This diagram can be expressed as the circles in the <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">original Clean Architecture diagram</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644200609927/LlNClxAsh.png" alt="CleanScope Architecture" /></p>
<p>We have named the architecture with all the packages and configurations of our preference: <strong><em>CleanScope</em></strong>. In the following articles, we're going to delve much more into what we like to use as tools to facilitate development since we know that there are too many options, for example in state management.</p>
<p>The purpose of implementing Clean is that all our layers are independent, but the only layer that has complete autonomy is the domain. This is because the domain defines both the types of data that we are going to use all around our app (entities) and the actions that are going to be carried out in our project (repositories and use cases).</p>
<p>The domain layer defines the general behaviors of our project, let's say all the classes that are the basics for it to work. The data layer comes to use that domain layer, implementing it in the way you want (using a specific package).</p>
<p>For example:</p>
<blockquote>
<p>☝️ The domain layer says:</p>
<p>"I have to develop an API that does <strong>[x action]</strong> and <strong>[y action]</strong>"</p>
<p>The data layer says:</p>
<p>"I'm going to develop my API using Go with 4 different endpoints, one for..."</p>
</blockquote>
<p>This is why we say that our data layer implements the components of the domain layer. But it is important to note that although a domain layer can serve us for different implementations of a data layer, both layers are used when we incorporate them into our presentation layer.</p>
<p>We are going to talk about the data and presentation layer in the following volumes, I just wanted you to observe the general flow. We will dig into the function of each component in the other layers, later. So don't worry.</p>
<p><img src="https://media.giphy.com/media/Olr6bYzpBx2JG/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644200611478/oAlfgXg_1T.gif" /></p>
<h1 id="heading-repositories">Repositories</h1>
<blockquote>
<p>☝️ Before continuing I want to clarify that, as I said in the first volume, this is one Clean architecture implementation. You can remove and add more layers than those that I am establishing.</p>
</blockquote>
<p>Pay attention to this part because you may get a bit confused here.</p>
<p>If you saw in the diagram, the repositories are not totally in the domain layer but are "shared" in turn with the data layer. This is not an error, let's say there are 2 types of repositories:</p>
<ol>
<li>Repositories in domain layer: They are abstract classes, or contracts, and define the properties and methods that our project will need in a specific feature.</li>
<li>Repositories in the data layer: These are the implementations of the contracts that we define in the domain layer.</li>
</ol>
<p>That's why we define...</p>
<blockquote>
<p>A repository is in charge of retrieving the data to us.</p>
</blockquote>
<p>But that can be abstracted a bit more. Probably in other implementations, you will see that the repository calls an API using the models, and that's fine. But there is a detail, the way it calls that external service or API can vary in implementation depending on the package that is used.</p>
<p>For example, I can have a repository that fetches data from an API and I can implement that with Dart's classic <a target="_blank" href="https://pub.dev/packages/http"><code>package:http</code></a>. But it might also be that I decide to use <a target="_blank" href="https://pub.dev/packages/dio"><code>package:dio</code></a> instead of <code>http</code> and my code should be extensible enough to switch those implementations and have no problems.</p>
<p>There we see that abstracting the logic only in repositories to get the data is a bit short. And I clarify that I make this observation for when the project they are building is medium or large, it is not necessary that for each small application you abstract that much.</p>
<p>In <strong>CleanScope</strong>, we're going to use data sources to get our information with the package we want, but that will be another time.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IMovieRepository</span> </span>{
  Future&lt;<span class="hljs-built_in">List</span>&lt;Movie&gt;&gt; getLatestMovies();
}
</code></pre>
<p>The method doesn't need a body, that is what its implementations take care of.</p>
<p>That is why we created an abstract repository class to define the methods we need to fetch the information we require. I prefix it with <code>I</code> to specify that it is my interface, so when I use my repository in the business logic that is in the presentation layer, it has a shorter and more expressive name.</p>
<blockquote>
<p>Consider that there are developers who use the <code>I</code> as a prefix for the implementation and not for the interface, there is no rule for that and it is a discussion that I've had with <a target="_blank" href="https://hashnode.com/@elianmortega">Elian</a>.</p>
<p>It seems simpler to me since I will only use the interface in my data layer and the presentation layer I will use the implementation in more places, so in that case, a shorter name suits me better.</p>
</blockquote>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MovieRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">IMovieRepository</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-built_in">List</span>&lt;Movie&gt;&gt; getLatestMovies() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// Implementation...</span>
  }
}
</code></pre>
<p>That's is the implementation of the repository in the data layer, roughly speaking.</p>
<h1 id="heading-testing">Testing</h1>
<p>Another reason why it's good to abstract the interface and not code implementation of the <code>MovieRepository</code> directly, is that it makes unit testing of this class much easier.</p>
<p>I know you probably haven't written a lot of tests in Flutter, I can't say I'm very good at it either, further the unit tests I do on my classes and functions. But it doesn't mean that it's not good to make them, conversely, if you still don't do tests (even if they are units) it's time to start.</p>
<p>We all know it already, but it never hurts to mention again that when we create an abstract class, we are creating a contract so that some implementation of that class complies with the established methods.</p>
<p>That's why by having our abstract class, we can extend from the <code>Mock</code> class of <a target="_blank" href="https://pub.dev/packages/mocktail"><code>package:mocktail</code></a> --you don't have to use this necessarily, it's only preference--, implement our interface and that our mock or test class has the methods that we set in the contract. </p>
<p>Like...</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:test/test.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:mocktail/mocktail.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockMovieRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mock</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IMovieRepository</span> </span>{ }

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-comment">// Unit tests...</span>
}
</code></pre>
<p>The test class is used as a dependency for a use case, a little spoiler.</p>
<p>And with the help of <code>mocktail</code> and <a target="_blank" href="https://pub.dev/packages/test"><code>package:test</code></a>, we can test our repository to confirm that everything works as it should.</p>
<blockquote>
<p>⚠️ As usually in the domain or data layer, we don't have Flutter as a dependency. That's why I use <code>package:test</code>, it doesn't include Flutter either and the same as the layers we're dealing with right now, they are written in pure Dart*.</p>
<p>*Unless you use a package that DOES have Flutter as a dependency.</p>
</blockquote>
<h1 id="heading-recap">Recap</h1>
<p>I wanted to make some points clearer because the domain layer is covered relatively quickly since it's more theory and then defines all the contracts that we're going to have in the project.</p>
<p>We have already seen the first part of the repositories, which is to create its interface or abstract class to later be able to implement it in the data layer (second part) and incidentally, to facilitate testing.</p>
<p>This layering of modules is the SOLID dependency inversion principle mentioned in <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-2">volume 2</a> of this series. We're going to use the abstractions that we're creating as domain contracts so that the implementations in the data layer can replace them by being of the same type, so to speak.</p>
<p>And that substitution ability of implementations to their interfaces is precisely Liskov's substitution principle, which was also covered in volume 2.</p>
<p>And so, my dear readers, that's how the SOLID rules are being complied within our layers and we are fully following Clean architecture.</p>
<blockquote>
<p>💡 Never forget that you can implement this architecture simpler or more complex, as it suits you, <strong>we</strong> simply offer you this proposal so that you can learn the concepts and see how <strong>we</strong> put them into practice.</p>
</blockquote>
<p><img src="https://media.giphy.com/media/KEYEpIngcmXlHetDqz/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644200619094/yEX7jf8rW.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 3: Dominating entities]]></title><description><![CDATA[We already saw enough of the game rules with CLEAN in the previous volumes of A Cleaner Flutter, now we have to go and write some code.
So go get your developer glasses and let's get our hands a little dirty.

⚠️ All the code that we're going to writ...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-3</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-3</guid><category><![CDATA[Flutter SDK]]></category><category><![CDATA[Dart]]></category><category><![CDATA[clean code]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Mon, 11 Jan 2021 05:11:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644198964262/vL4s3Op4W.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We already saw enough of the game rules with CLEAN in the previous volumes of <strong><em>A Cleaner Flutter</em></strong>, now we have to go and write some code.</p>
<p>So go get your developer glasses and let's get our hands a little dirty.</p>
<blockquote>
<p>⚠️ All the code that we're going to write in this article is pure Dart, with no dependencies on the Flutter SDK.</p>
</blockquote>
<p><img src="https://media.giphy.com/media/RyXVu4ZW454IM/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644198796601/WX6TUaU5t.gif" /></p>
<h1 id="heading-domain-layer">Domain layer</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644198798804/waGb990k8.png" alt="Domain layer components" /></p>
<blockquote>
<p>⚠️ I'm going to alternate between these two terms quite a bit in the next section so you don't get confused:</p>
<p>Abstract classes are the same as interfaces. In Dart, there is no keyword for creating an interface, but the abstract class does functionally the same.</p>
</blockquote>
<p>Before explaining entities, I notify you that with this article we begin to explain the domain layer, which consists of the contracts that we're going to set up in our project.</p>
<p>We're not going to sign anything, it's an expression. I'll explain what contracts are.</p>
<p>We call the abstract classes, or interfaces if you come from other languages, contracts because they settle rules: properties, actions... that must be fulfilled for a specific class.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">INetworkManager</span> </span>{
  Future&lt;<span class="hljs-built_in">bool</span>&gt; <span class="hljs-keyword">get</span> isConnected;
}
</code></pre>
<p>In this example, we can see an abstract class/interface that defines a network manager. This class is called a contract because any class that extends from it has to implement its methods and has access to its properties. As we can see in the following image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644198802161/_CoPSSCKV.png" alt="Alt Text" /></p>
<p>Here we see that since <code>NetworkManager</code> doesn't implement <code>isConnected</code>, it throws an error. Then, <code>NetworkManager</code> is forced to sign a contract to implement <code>INetworkManager</code>. </p>
<p>Got it? Great. And now, why do we make contracts?</p>
<p>As we talked about in the previous articles, we need our code to be scalable and that means it's easy to extend. That way, having abstract classes we can make the implementations that we want of the interfaces taking into consideration different types of technologies, or in the case of Flutter, they can be different packages with a separate implementation for each one.</p>
<p>And in addition to all this, contracts make testing our app much easier, since we can create test classes with packages like <a target="_blank" href="https://pub.dev/packages/mocktail">mocktail</a> and thus run our tests in classes that have the methods established in our contracts.</p>
<p>Now that we make that clear, let's go with the entities.</p>
<h1 id="heading-entities">Entities</h1>
<p>When you are going to start a project from scratch, which part do you code first?</p>
<p>In my case, I code the classes of the data that I'm going to use throughout my entire application. I consider this to be a good practice as it helps us lay down the information that will flow through all of our logic.</p>
<p>The entities can be ordinary classes that represent abstractions of actors in real life, or something very abstract such as classes of a framework like Flutter with <code>RenderObject</code>.</p>
<p>We are not going to complicate it much.</p>
<blockquote>
<p>The entities must be our data types or classes that are used in different parts of our software.</p>
</blockquote>
<p>At least that's what Uncle Bob says, and it seems right to me. Although everything ends up being an entity even in the outermost layer, we define in <strong>our</strong> version of Clean that our entities are the objects that can be returned to us --or we can send to-- an API, taking the most famous example.</p>
<p><img src="https://media.giphy.com/media/cLYofyLxn0W1zifk10/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644198803861/6QnkbP1q-.gif" /></p>
<p>When we look at the models in the data layer you probably understand the usefulness of first abstracting an entity that simply defines properties and some general behaviors and then extending its functionality into models that implement more specific methods.</p>
<p>Let's say that an entity's purpose is to define the essential characteristics of an object. The specific features are implemented by the model because the models are in charge of being used for specific use cases.</p>
<p>That's a lot <em>specific</em>.</p>
<p>The code would be like this:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Response</span> </span>{
  <span class="hljs-keyword">const</span> Response({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.message});

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> message;
}
</code></pre>
<p><code>Response</code> states the properties that every API response must have. These are simple responses to simplify the example, I know that not all answers in an API will return what this class has. Let me finish.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ResponseModel</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Response</span> </span>{
  <span class="hljs-keyword">const</span> ResponseModel({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> message,
  }) : <span class="hljs-keyword">super</span>(message: message);

  <span class="hljs-keyword">factory</span> ResponseModel.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> ResponseModel(message: json[<span class="hljs-string">'message'</span>]);
  }

  <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; toJson() {
    <span class="hljs-keyword">return</span> &lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt;{<span class="hljs-string">'message'</span>: message};
  }
}
</code></pre>
<p>Now that we have our contract, we can create a model that "signs" it, basically I mean implement or extend it. I say to sign because by inheriting from that class we are agreeing to implement all the methods it has and comply with the properties it sets.</p>
<p>For example with <code>ResponseModel</code>, we create a <code>String</code> in the same constructor and simply pass that property to the class we are inheriting from, to fulfill that property.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ResponseModel</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Response</span> </span>{
  <span class="hljs-keyword">const</span> ResponseModel({
    <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> message,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.statusCode,
  }) : <span class="hljs-keyword">super</span>(message: message);

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> statusCode;

  <span class="hljs-keyword">factory</span> ResponseModel.fromJson(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; json) {
    <span class="hljs-keyword">return</span> ResponseModel(
      message: json[<span class="hljs-string">'message'</span>],
      statusCode: json[<span class="hljs-string">'statusCode'</span>],
    );
  }

  <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; toJson() {
    <span class="hljs-keyword">return</span> &lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt;{
      <span class="hljs-string">'message'</span>: message,
      <span class="hljs-string">'statusCode'</span>: statusCode,
    };
  }
}
</code></pre>
<p>In this other example, we do the same as in the previous one, with the only difference that we add a property that is no longer the basis of our <code>Response</code> entity and thus we fulfill one of the characteristics that we talked about in the previous volumes: we <em>extend the existing functionality without altering it in the process</em>.</p>
<p>A valid extra point to mention is that as this is the basis of our entire graph, when we make a change at the entity level we will have errors in our models and for the same reason, in any other part that these models are used.</p>
<p>There we see the rule of dependency in action and how it helps us to have control of the changes in our code by the parts that depend on others.</p>
<hr />
<p>Perhaps I have written long and hard on something very simple but I'm interested in understanding the purpose of this separation. We could easily make our models all at once with the features we consider necessary, but the code would become a bit repetitive and even messy.</p>
<p>I hope you have assimilated well the concepts and especially the separation into layers that we are doing to extend the functionality and order of our code.</p>
<p>This was the simplest part and the basis for the rest (out of the concepts), in the next volume we will continue exploring the domain layer with the repositories, I promise you that it will be a little more entertaining.</p>
<p><img src="https://media.giphy.com/media/l1JJ6JMcdfjDya44KO/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644198811448/Scf77vh7JJ.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 2: SOLID principles]]></title><description><![CDATA[💡 Note: This article was originally posted in my friend Elian's blog and has been slightly modified for this series. You can check the original here.

After starting in the world of programming we all reach a point where we have to look back on the ...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-2</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-2</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[clean code]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Tue, 05 Jan 2021 15:02:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644126700638/ad9JZvtib.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>💡 Note: This article was originally posted in my friend Elian's blog and has been slightly modified for this series. You can check the original <a target="_blank" href="https://elianortega.dev/cleaner-flutter-vol-2-solid-principles">here</a>.</p>
</blockquote>
<p>After starting in the world of programming we all reach a point where we have to look back on the road and review some of the lines of code that we have written, either 1 day ago to remember an idea or years ago to review the implementation of any module of our software.</p>
<p>Many times in these glances at the code of the past we come across a list of problems such as:</p>
<ul>
<li>Having to search among many files for the answer to what we are looking for.</li>
<li>Not understanding the code we wrote.</li>
<li>Not understanding why we wrote the code the way we did.</li>
</ul>
<p><img src="https://media.giphy.com/media/GPQL5xsaunjmGcVqLn/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644121955953/K86n4DlZb.gif" /></p>
<p>These problems start when we start a project because we do not spend enough time to have a clear idea not only of what we are going to do but also of how we are going to do it.</p>
<p>We have to develop code imagining what would happen if I return in 2 years to review it, this ability to program clean and understandable code is essential to facilitate development, especially if you work in a team.</p>
<h1 id="heading-what-are-the-solid-principles">What are the SOLID principles?</h1>
<p>SOLID is the acronym for a set of principles that help us develop more maintainable code that also allows easy extension without compromising code already developed.</p>
<p>In other words...</p>
<blockquote>
<p>Write more code without damaging what already works.</p>
</blockquote>
<p>We can even see them as a set of guidelines to follow. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644126377844/nkG5sEaAg.png" alt="Da_Rules.png" /></p>
<p>Now we are going to explore each of the principles, which can be applied to any programming language, but I am going to cover them using Dart language since it is the language used by the Flutter framework. </p>
<p>Before continuing it is important to note that these were first introduced by Uncle Bob. You can see his explanation <a target="_blank" href="https://www.youtube.com/watch?v=zHiWqnTWsn4">here</a>.</p>
<h1 id="heading-s-stands-for-single-responsibility">S stands for Single Responsibility</h1>
<blockquote>
<p>A class must have one, and only one, a reason to change.</p>
</blockquote>
<p>To explain this principle we can imagine a messy room, as we have all had it at some point, perhaps even now that you are reading this.</p>
<p>But the truth is that within this, everything has its place and everything should be in its designated place.
To put the analogy aside, this principle tells us more specifically:</p>
<ul>
<li>A class must have a unique responsibility (applies to methods, variables, entities, etc).</li>
<li>There is a place for everything and everything should be in its place.</li>
<li>All the variables and methods of the class must be aligned with the objective of the class.</li>
</ul>
<p>By following these principles, we achieve smaller and simpler classes that have unique objectives. Also, we avoid giant classes with generic properties and methods that can be redundant in development.</p>
<p>Let's see an example:</p>
<p><img src="https://media.giphy.com/media/PiQejEf31116URju4V/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644121958217/aYx_jT5K0.gif" /></p>
<p>Let's take a look at this <code>signUp</code> function. This could be the method we call from our UI layer to perform the user sign-up process.</p>
<pre><code class="lang-dart">Future&lt;User&gt; signUp({
  <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
  <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> email,
  <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> password,
}) <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> isValid = name.isNotEmpty &amp;&amp; email.isNotEmpty &amp;&amp; password.isNotEmpty;

  <span class="hljs-keyword">if</span> (isValid) {
    <span class="hljs-keyword">final</span> newUser = User(
      name: name,
      email: email,
      password: password,
    );

    <span class="hljs-keyword">final</span> userMap = newUser.toMap();

    <span class="hljs-keyword">await</span> saveToDb(json.encode(userMap));
  }
}
</code></pre>
<p>In the code, we see that there is the functionality of creation, conversion to JSON, and even the call to the database that is normally an API call, so we are not fulfilling the principle.</p>
<p>This is one of the most common mistakes, especially in Flutter, since developers easily make the mistake of combining different things within the same class or methods.</p>
<blockquote>
<p>⚠️ In other articles we will see how this applies to Clean Architecture...</p>
</blockquote>
<p>Done, I got it, now... how do I apply it?</p>
<p>To follow the single responsibility principle correctly, we could create methods and classes with simple and unique functionalities.</p>
<p>In the example method <code>signUp</code> many things are done with different objectives, each of these functionalities could be separated into an individual class with a single objective.</p>
<h2 id="heading-extracting-logic">Extracting logic</h2>
<p>We could implement a class that is responsible for performing the validation, there are many ways to do this. One of them can be to use <a target="_blank" href="https://pub.dev/packages/formz"><code>package:formz</code></a> which is a Dart package that allows us to create classes for a data type and perform validations.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:formz/formz.dart'</span>;

<span class="hljs-comment">/// <span class="markdown">Define input validation errors</span></span>
<span class="hljs-keyword">enum</span> NameInputError { empty }

<span class="hljs-comment">/// <span class="markdown">Extend FormzInput and provide the input type and error type.</span></span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NameInput</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">FormzInput</span>&lt;<span class="hljs-title">String</span>, <span class="hljs-title">NameInputError</span>&gt; </span>{
  <span class="hljs-comment">/// <span class="markdown">Call super.pure to represent an unmodified form input.</span></span>
  <span class="hljs-keyword">const</span> NameInput.pure() : <span class="hljs-keyword">super</span>.pure(<span class="hljs-string">''</span>);

  <span class="hljs-comment">/// <span class="markdown">Call super.dirty to represent a modified form input.</span></span>
  <span class="hljs-keyword">const</span> NameInput.dirty({<span class="hljs-built_in">String</span> value = <span class="hljs-string">''</span>}) : <span class="hljs-keyword">super</span>.dirty(value);

  <span class="hljs-comment">/// <span class="markdown">Override validator to handle validating a given input value.</span></span>
  <span class="hljs-meta">@override</span>
  NameInputError? validator(<span class="hljs-built_in">String</span> value) {
    <span class="hljs-keyword">return</span> value.isNotEmpty == <span class="hljs-keyword">true</span> ? <span class="hljs-keyword">null</span> : NameInputError.empty;
  }
}
</code></pre>
<p>Do not focus too much on the logic of the code, the important thing is to understand that now the validation is decoupled from the rest of the logic with the <code>validator</code> method.</p>
<h2 id="heading-connecting-dependencies">Connecting dependencies</h2>
<p>The other error is to call an API from the business logic or user interface, this would not fulfill the principle since the connection with the API is a complex functionality by itself, so it would be best to implement a class as <code>Repository</code> to which we pass the parameters that we are going to send and delegate the rest of the process to it.</p>
<pre><code class="lang-dart"><span class="hljs-comment">/// <span class="markdown">Repository that handles the relationship</span></span>
<span class="hljs-comment">/// <span class="markdown">between app logic and data source or API.</span></span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthRepository</span> </span>{
  AuthRepository({
    http.Client? client,
  }) : _client = client ?? http.Client();

  <span class="hljs-keyword">final</span> http.Client _client;

  <span class="hljs-comment">/// <span class="markdown">Method that makes the API call to sign-up a user.</span></span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; signUpUser(User user) <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> _client.post(
        <span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">'https://noscope.dev/user/create'</span>),
        body: user.toMap(),
      );
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-keyword">throw</span> NetworkException();
    }
  }
}
</code></pre>
<p>This repository concept is key to meeting clean architecture standards but we can see that the principle of single responsibility is behind this whole idea.</p>
<p>By implementing these classes applying the principle we would achieve a simpler method compared to how we started with:</p>
<pre><code class="lang-dart">Future&lt;<span class="hljs-keyword">void</span>&gt; signUp({
  <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> name,
  <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> password,
  <span class="hljs-keyword">required</span> <span class="hljs-built_in">String</span> email,
}) <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">final</span> newUser = User(
    email: email,
    password: password,
    name: name,
  );
  <span class="hljs-keyword">await</span> _authRepository.signUpUser(newUser);
}
</code></pre>
<p>Simpler, more maintainable, and decoupled.</p>
<h1 id="heading-o-stands-for-openclosed">O stands for Open/Closed</h1>
<blockquote>
<p>An entity must be open to extending but closed to modify.</p>
</blockquote>
<p>This principle tells us that we must extend our classes to add new code, instead of modifying the existing one.</p>
<p>The first time we read this it can be a bit confusing but it just is:</p>
<blockquote>
<p>Don't modify what already works, just extend and add new code.</p>
</blockquote>
<p>n this way, we can develop without damaging the previously tested code. To understand this principle we can see an <a target="_blank" href="https://www.youtube.com/watch?v=rtmFCcjEgEw">example</a> given by Katerina Trjchevska at LaraconEU 2018.</p>
<p>Let's imagine that our app has a payment module that currently only accepts debit/credit cards and PayPal as payment methods.</p>
<pre><code class="lang-dart">Future&lt;<span class="hljs-keyword">void</span>&gt; pay(<span class="hljs-built_in">String</span> paymentType) <span class="hljs-keyword">async</span> {
  <span class="hljs-keyword">if</span> (paymentType == <span class="hljs-string">'card'</span>) {
    <span class="hljs-keyword">await</span> _paymentRepository.payWithCard();
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (paymentType == <span class="hljs-string">'paypal'</span>) {
    <span class="hljs-keyword">await</span> _paymentRepository.payWithPaypal();
  }
}
</code></pre>
<p>At a first glance at the code, we may think that everything is fine, but when we analyze its long-term <strong>scalability</strong>, we realize the problem.</p>
<p>Let's imagine that our client asks us to add a new payment method such as Alipay, gift cards, and others.</p>
<p>Each new payment method implies a new function and a new conditional in the <code>pay</code> method and we could say that this is not a problem, but if we keep adding code within the same class, we would never achieve a stable, ready for production code.</p>
<p>By applying the open/closed principle, we can create an abstract class <code>PayableInterface</code> that serves as a payment interface. In this way, each of our payment methods extends this abstract class and it can be a separate class that is not affected by modifications made to another.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayableInterface</span> </span>{
  Future&lt;<span class="hljs-keyword">void</span>&gt; pay();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CardPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PayableInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; pay() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// Card payment logic.</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaypalPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PayableInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; pay() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// Paypal payment logic.</span>
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AliPayPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PayableInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; pay() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// AliPay payment logic.</span>
  }
}
</code></pre>
<p>After having our payment logic implemented, we can receive a parameter with the <code>paymentType</code> that allows us to select the <code>PayableInterface</code> indicated for the transaction, and in this way we do not have to worry about how the <code>pay</code> method makes the payment, only to make a type of filtering so that the correct instance of the interface is used; be it Card, PayPal or Alipay.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">enum</span> PaymentType { card, payPal, aliPay }

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentFactory</span> </span>{
  <span class="hljs-keyword">const</span> PaymentFactory();

  PayableInterface initializePayment(PaymentType paymentType) {
    <span class="hljs-comment">// Filter by `paymentType` and return the correct [PayableInterface].</span>
    <span class="hljs-keyword">switch</span> (paymentType) {
      <span class="hljs-keyword">case</span> PaymentType.card:
        <span class="hljs-keyword">return</span> CardPayment();
      <span class="hljs-keyword">case</span> PaymentType.payPal:
        <span class="hljs-keyword">return</span> PayPalPayment();
      <span class="hljs-keyword">case</span> PaymentType.aliPay:
        <span class="hljs-keyword">return</span> AliPayPayment();
    }
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentRepository</span> </span>{
  PaymentRepository({
    <span class="hljs-keyword">required</span> PaymentFactory paymentFactory,
  }) : _paymentFactory = paymentFactory;

  <span class="hljs-keyword">final</span> PaymentFactory _paymentFactory;

  Future&lt;<span class="hljs-keyword">void</span>&gt; pay(PaymentType paymentType) <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// Get the respective payableInterface based on the `paymentType`.</span>
    PayableInterface payment = _paymentFactory.initializePayment(paymentType);

    <span class="hljs-comment">// Make payment.</span>
    payment.pay();
  }
}
</code></pre>
<p>In the end, we would have a method like this where we can see that the code was reduced to only 3 lines and it is much easier to read.</p>
<p>It is also more scalable since if we wanted to add a new type of payment method we would only have to extend from <code>PayableInterface</code> and add it as an option in the filtering method.</p>
<blockquote>
<p>👆 These concepts of abstractions and instances are confusing at first but throughout this series of articles and by practice they'll become simple concepts.</p>
</blockquote>
<h1 id="heading-l-stands-for-liskov-substitution">L stands for Liskov Substitution</h1>
<blockquote>
<p>We can change any concrete instance of a class with any class that implements the same interface.</p>
</blockquote>
<p>The main objective of this principle is that we should always obtain the expected behavior of the code regardless of the class instance that is being used.</p>
<p>To be able to fulfill this principle correctly, there are 2 important parts:</p>
<ul>
<li>Implementation.</li>
<li>Abstraction.</li>
</ul>
<p>The first we can see in the previous example of open/closed principle when we have <code>PayableInterface</code> and the payment methods that implement it as<code>CardPayment</code> and <code>PaypalPayment</code>.</p>
<p>In the implementation of the code we see that it doesn't matter with the implementation we choose, our code should continue to work correctly, this is because both make correct implementation of the <code>PayableInterface</code> interface.</p>
<p>With this example, the idea is easy to understand but in practice, there are many times that we perform the abstraction process wrong, so we cannot truly make great use of the principle.</p>
<p>If you are not very familiar with concepts such as interface, implementation, and abstraction this may sound a bit complex but let's see it with a simple example.</p>
<p><img src="https://i.stack.imgur.com/ilxzO.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644121976110/I2U1PUmwY.jpeg" /></p>
<p>This is one of the iconic images of the principle as it makes it easy to understand.</p>
<p>Let's imagine that in our code we have a class called <code>DuckInterface</code>.</p>
<p>This gives us the basic functionality of a duck: fly, swim, and quack. And we would have the<code>RubberDuck</code> class that implements the interface.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DuckInterface</span> </span>{
  <span class="hljs-keyword">void</span> fly();
  <span class="hljs-built_in">String</span> swim();
  <span class="hljs-built_in">String</span> quack();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RubberDuck</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DuckInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> fly() {
    <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">'Rubber duck cannot fly'</span>);
  }

  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">String</span> quack() {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Quack!!!"</span>;
  }

  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">String</span> swim() {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Duck Swimming"</span>;
  }
}
</code></pre>
<p>At a first glance, we could say that our abstraction is fine since we are using an interface that gives us the functionality we need, but the <code>fly</code> method does not apply to a rubber duck,  imagine that our program is going to have different Animals with shared functionality such as flying and swimming, so it would not make sense to leave this method on the <code>DuckInterface</code> interface.</p>
<p>To solve this and comply with the Liskov principle, we can create more specific interfaces that allow us to reuse code, which also makes our code more maintainable.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuackInterface</span> </span>{
  <span class="hljs-built_in">String</span> quack();
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FlyInterface</span> </span>{
  <span class="hljs-built_in">String</span> fly();
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SwimInterface</span> </span>{
  <span class="hljs-built_in">String</span> swim();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RubberDuck</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">QuackInterface</span>, <span class="hljs-title">SwimInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">String</span> quack() {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Quack!!!"</span>;
  }

  <span class="hljs-meta">@override</span>
  <span class="hljs-built_in">String</span> swim() {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Duck Swimming"</span>;
  }
}
</code></pre>
<p>With this implementation, our <code>RubberDuck</code> class only implements the methods it needs and now, for example, if we need an animal that fulfills a specific function such as swimming, we could use any class that implements the <code>SwimInterface</code> interface. This is because by fulfilling the Liskov principle we can switch any declaration of an <code>abstract class</code> by any class that implements it. </p>
<h1 id="heading-i-stands-for-interface-segregation">I stands for Interface Segregation</h1>
<blockquote>
<p>The code should not depend on methods that it does not use.</p>
</blockquote>
<p>At first, this could seem to be the simplest principle but for this very reason, in the beginning, it can even confuse us.</p>
<p>In the previous principles, we have seen the importance of interfaces to decouple our code.</p>
<p>This principle ensures that our abstractions for creating interfaces are correct since we cannot create a new instance of an interface without implementing one of the methods defined by them. The above would be violating the principle</p>
<p><img src="https://innovationm.co/wp-content/uploads/2017/11/InterfaceSegregationPrinciple.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644121983608/1y86n5w6n.jpeg" /></p>
<p>This image shows the problem of not fulfilling this principle, we have some instances of classes that do not use all the interface methods, which lead to a dirty code and indicate bad abstraction. </p>
<p>It is easier to see it with the typical anima example, this is very similar to the example we saw from Liskov.</p>
<blockquote>
<p>💡 At this point the examples become similar but the important thing is to see the code from another perspective.</p>
</blockquote>
<p>We have an abstract class <code>Animal</code> that is our interface, it has 3 methods defined  <code>eat</code>, <code>sleep</code>, and <code>fly</code>.</p>
<p>If we create a <code>Bird</code> class that implements the animal interface we don't see any problem, but what if we want to create the <code>Dog</code> class?</p>
<p>Exactly, we realize that we cannot implement the <code>fly</code> method because it does not apply to a dog.</p>
<p>We could leave it like that and avoid the time needed to restructure the code since we logically know that this would not affect our code, but this breaks the principle.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-keyword">void</span> eat();
  <span class="hljs-keyword">void</span> sleep();
  <span class="hljs-keyword">void</span> fly();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> eat() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> sleep() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> fly() {}
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> eat() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> sleep() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> fly() =&gt; <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">'Dogs cannot fly!'</span>);
}
</code></pre>
<p>The mistake is made by having a bad abstraction in our class and the right thing to do is always refactor to ensure that the principles are being met.</p>
<p>It may take us a little longer at the moment but the results of having a clean and scalable code should always be priorities.</p>
<p>A solution to this could be that our <code>Animal</code> interface only has the methods shared by animals like <code>eat</code>, <code>sleep</code> and we create another interface for the <code>fly</code> method. In this way, only animals that need this method to implement its interface.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FlyInterface</span> </span>{
  <span class="hljs-keyword">void</span> fly();
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-keyword">void</span> eat();
  <span class="hljs-keyword">void</span> sleep();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Animal</span>, <span class="hljs-title">FlyInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> eat() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> sleep() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> fly() {}
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> eat() {}

  <span class="hljs-meta">@override</span>
  <span class="hljs-keyword">void</span> sleep() {}
}
</code></pre>
<h1 id="heading-d-stands-for-dependency-inversion">D stands for Dependency Inversion</h1>
<blockquote>
<p>High-level modules should not depend on low-level modules. Both must depend on abstractions.</p>
</blockquote>
<p>This principle tells us:</p>
<ul>
<li><p>You never have to depend on a concrete implementation of a class, only on its abstractions (interfaces).</p>
</li>
<li><p>Same as the image presented on <a target="_blank" href="https://marcossevilla.dev/cleaner-flutter-vol-1">volume 1</a>, we follow the rule that high-level modules should not strictly rely on low-level modules.</p>
</li>
</ul>
<p>To understand it more simply, let's look at the example.</p>
<p>Nowadays, every app or software that is developed needs to communicate with the outside world. Normally this is done through code repositories that we instantiate and call from the business logic in our software.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataRepository</span> </span>{
  Future&lt;<span class="hljs-keyword">void</span>&gt; logInUser() <span class="hljs-keyword">async</span> {}

  Future&lt;<span class="hljs-keyword">void</span>&gt; signUpUser() <span class="hljs-keyword">async</span> {}
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BusinessLogic</span> </span>{
  <span class="hljs-keyword">const</span> BusinessLogic({
    <span class="hljs-keyword">required</span> DataRepository repository,
  }) : _repository = repository;

  <span class="hljs-keyword">final</span> DataRepository _repository;

  Future&lt;<span class="hljs-keyword">void</span>&gt; logIn() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> _repository.logInUser();
  }

  Future&lt;<span class="hljs-keyword">void</span>&gt; signUp() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> _repository.signUpUser();
  }
}
</code></pre>
<p>Declaring and using a concrete class, such as the <code>DataRepository</code> within <code>BusinessLogic</code>, is a very common practice and is one of the common mistakes that make our code not very scalable. By depending on a particular instance of a class we surely know it will never be stable because you are constantly adding code to it.</p>
<p>To solve this problem, the principle tells us to create an interface that communicates both modules. You can even develop the whole functionality of the business logic and user interface of an app by depending on an interface that hasn't been implemented. </p>
<p>This also allows better communication in a team of developers because when creating an interface, everyone is clear about the objectives of the module, and from that definition, it can be verified that the SOLID principles are being met.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataRepositoryInterface</span> </span>{
  Future&lt;<span class="hljs-keyword">void</span>&gt; logInUser();

  Future&lt;<span class="hljs-keyword">void</span>&gt; signUpUser();
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">DataRepositoryInterface</span> </span>{
  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; logInUser() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// Implementation...</span>
  }

  <span class="hljs-meta">@override</span>
  Future&lt;<span class="hljs-keyword">void</span>&gt; signUpUser() <span class="hljs-keyword">async</span> {
    <span class="hljs-comment">// Implementation...</span>
  }
}
</code></pre>
<p>With this implementation, we create a <code>DataRepositoryInterface</code> that we can then implement in<code>DataRepository</code> and the magic happens inside the class that uses this functionality when we do not depend on a concrete instance but instead on an interface we could pass as parameters any concrete class that implements this interface.</p>
<p>It could be a local or external database and that would not affect the development, I repeat it: <strong>we do not depend on a single concrete instance, we can use any class that complies with the implementation of the interface</strong>.</p>
<p>And this is what allows us to fulfill the magic word of clean architecture: decoupling!</p>
<h1 id="heading-wrap-up">Wrap-up</h1>
<p>I remind you that these are principles, not rules, so there is no single way to follow them, their use and compliance with the code will depend on each project since for many of these the objectives of the project are key to making decisions. Just as something within the scope of a project can be considered small it may under other requirements become something large.</p>
<hr />
<p>If you liked <a target="_blank" href="https://elianortega.dev/">Elian</a>'s content, you can find even more and keep in touch with him on his social networks:</p>
<ul>
<li><a target="_blank" href="https://github.com/elian-ortega">GitHub</a>.</li>
<li><a target="_blank" href="https://www.linkedin.com/in/elian-ortega">LinkedIn</a>.</li>
<li><a target="_blank" href="https://twitter.com/ElianOrtegaNCA">Twitter</a>.</li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCPz6bJ3DptMMXu7_hMb1oJQ">YouTube</a>.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Cleaner Flutter Vol. 1: Intro to Clean]]></title><description><![CDATA[Do you remember the first time you wrote code? Maybe it was a hello world or some other first little program. It was great, seeing a couple of lines of code start to work... A couple of lines unless it was Java code.
If you are reading this, it may h...]]></description><link>https://marcossevilla.dev/cleaner-flutter-vol-1</link><guid isPermaLink="true">https://marcossevilla.dev/cleaner-flutter-vol-1</guid><category><![CDATA[Dart]]></category><category><![CDATA[Flutter Examples]]></category><category><![CDATA[clean code]]></category><category><![CDATA[architecture]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Sun, 03 Jan 2021 04:50:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644126742776/CEsSgdd66.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Do you remember the first time you wrote code? Maybe it was a <em>hello world</em> or some other first little program. It was great, seeing a couple of lines of code start to work... A couple of lines unless it was Java code.</p>
<p>If you are reading this, it may have been a long time since you wrote that little program. The world has changed, it's not like before. We have gotten into projects and experiences much more complex than our first contact with the world of software development.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644121703618/lSsp0v87H.png" alt="logan" /></p>
<h1 id="heading-challenges">Challenges</h1>
<blockquote>
<p>Challenges arise from complexity.</p>
</blockquote>
<p>I don't know if anyone said that but it sounded cool.</p>
<p>One of the biggest to come out has been <strong>scalability</strong>, which in short terms is defined as the ability of a system to grow in workload without dying while trying.</p>
<p>Also, when a project grows, it must be reliable, meaning that we can rest assured that it will not die or at least not easily. To ensure <strong>reliability</strong>, you have to maintain code with its tests passed. In a nutshell, your code must be properly tested to ensure it works.</p>
<p>Finally, there is a feature that many users do not perceive since they don't see the codebase, but this says a lot about any system that has it. This is called <strong>decoupling</strong>, which is closely related to code reuse and independence of each piece of software. </p>
<p>We decouple so that our code is modular and we can play with it as if they were LEGO pieces that we can change in size, shape, or color as long as it fits. This way we have reusable parts and we are more productive with organized code.</p>
<p>I could spend a lot of time talking about how we can write better code and good practices, but we better explain Clean.</p>
<p>Clean is an architecture suggested by Robert C. Martin, <em>Uncle Bob</em> for friends. It claims to meet all of the characteristics I mentioned previously and has a ... let's call it <em>golden rule</em>.</p>
<h1 id="heading-the-dependency-rule">The Dependency Rule</h1>
<p>To save me complex explanations, I am going to show you a graph. Don't over-analyze it, I just want you to think about the shapes that are presented:</p>
<p><img src="https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644120769766/uxBjVPFtM.jpeg" /></p>
<p>Ignore the words and notice that they are only circles containing smaller ones. That's the graphical representation of the dependency rule, which if paraphrased would be something like:</p>
<blockquote>
<p>Dependencies go from the outside in. That said, dependencies don't know anything about the components that depend on them.</p>
</blockquote>
<p>Still don't understand? Let's use the words that are there.</p>
<p>The circle that contains everything we can see that has the <strong>UI</strong>, let's use it in the example. Our rule says the UI depends on the <strong>Controllers</strong> but a Controller doesn't know what's in the UI. So with the other circles and those that contain them.</p>
<p>Once again and in another way: The small circle is used in the large circle and NOT vice versa.</p>
<p>I hope you understood because from now on I am going to assume that you did. If not, there is more information on Uncle Bob's <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">Clean Coder Blog</a>.</p>
<blockquote>
<p>⚠️ Given the most basic concepts of this huge topic, I want to clarify that I'm going to focus the following volumes of this series of articles on the development of apps in Flutter with Clean since that is what I do.</p>
</blockquote>
<p>Specifically for Flutter, Clean has a slightly different implementation because of how the framework works in the integration of logic and the graphical interface. We can't decouple much in this case since they are too closely related, but we can extract in two layers:</p>
<ul>
<li><strong>Domain</strong>: extracts the contracts in the system (interfaces, or abstract classes in Dart).</li>
<li><strong>Data</strong>: implements the contracts and obtains the data that the system uses.</li>
</ul>
<p>Later we will delve into the components of these layers.</p>
<h1 id="heading-a-common-use-case">A common use-case</h1>
<p>At this point, we have already explained quite a bit of the basics that are required to understand the following articles, but I wanted to make a few last observations and conclude.</p>
<p>Each of the layers or circles that Clean has can work independently of its outer dependencies or the circles that contain them.</p>
<p>I'll give you a practical example of why's that.</p>
<p>Let's say we are doing a project that initially has a REST API to interact with the backend and we make all the models of our application closely linked to the JSON format. Everyone lived together in harmony, but everything changed when we were asked to switch to an API with GraphQL.</p>
<p>Rings a bell? Yes, it happens to the best teams. And if we don't have a good architecture, we will probably have to make that migration from scratch.</p>
<p>The advantage of a good architecture is that our entities allow us to implement models with their own properties based on the technology they have to implement. So that our JSON models have the same properties as GraphQL and only vary in implementation.</p>
<p>Oops, we haven't talked about entities yet, sorry. If something I said didn't make sense to you and left you confused, then calm down, the following volumes are coming for you to understand better.</p>
<p>In the meantime, let's wrap up this article.</p>
<h1 id="heading-wrap-up">Wrap-up</h1>
<p>I tried to make a slightly more beginner-friendly version of the original Clean Architecture article on the Clean Coder Blog (I left the link before, but I leave it <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012">here</a> again).</p>
<p>So as in that post, I will emphasize that implementing this clean architecture doesn't mean following the graph you saw before. If you search for more on the subject, you will find many more graphics that mention other aspects and that's the point, this changes depending on the project.</p>
<p>What you have to take into consideration is to really implement the architecture by always using the dependency rule. With that principle, we already follow the decoupling as it really should. The level of abstraction you want to implement in your code is up to you. As you become more abstract, even more layers can emerge.</p>
<p>I finish by saying that following this rule is very simple so I hope you do it and we will still have examples and more advice in the following articles (I have already said it a lot but it's for you to stay tuned) so that you do not suffer making and --more importantly-- maintaining good software.</p>
<p><img src="https://media.giphy.com/media/efDT7dqlF5N2LVHG8C/giphy.gif" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1644120771434/07oonoV6_.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[FlutterGen Code Generation]]></title><description><![CDATA[One of the most important programming principles I've heard since my freshman year of college is DRY, or Don't Repeat Yourself.
DRY gives us a way to solve problems through code that applies to almost any problem. It is even a way of applying algorit...]]></description><link>https://marcossevilla.dev/flutter-gen</link><guid isPermaLink="true">https://marcossevilla.dev/flutter-gen</guid><category><![CDATA[Dart]]></category><category><![CDATA[generators]]></category><dc:creator><![CDATA[Marcos Sevilla]]></dc:creator><pubDate>Sat, 12 Dec 2020 06:43:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643931433247/td3HAbZc0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the most important programming principles I've heard since my freshman year of college is <strong><em>DRY</em></strong>, or <strong><em>Don't Repeat Yourself</em></strong>.</p>
<p>DRY gives us a way to solve problems through code that applies to almost any problem. It is even a way of applying algorithms in our daily lives.</p>
<p>Do not repeat yourself, if you do, there is room for optimization. From a technical point of view, this principle urges us to automate a repetitive process that, at first suggests the implementation of a loop such as <code>for</code> or <code>while</code> as a solution. Or write a script that runs that action that takes us more time and effort than we would like.</p>
<p>There is a type of super useful tool when we're programming, the famous code-gen or code generators. They consist of a program that is incorporated into our project to run in development and create files with all the settings that would have lengthened development time.</p>
<h1 id="heading-why">Why?</h1>
<p>Before getting into business, I would like to show you a typical problem where we can see the reason for these programs.</p>
<pre><code class="lang-dart">Image imageFile = Image.asset(<span class="hljs-string">'assets/img/my_image.png'</span>);
</code></pre>
<p>In this case, we are declaring an image that is initialized as an asset that we loaded from the same project. To assign this asset, we must provide the <strong>path</strong> of the <em>.png</em> file to the method. This is not safe because we are human beings and we tend to make errors (typos) that may not be detected by a linter or compiler.</p>
<p>In short, code generation handles these problems as it is responsible for writing the code that we need so that we can use it and we can identify/correct errors more easily.</p>
<p>Now that we know that, let's use these utilities.</p>
<blockquote>
<p>⚠️ Disclaimer: 95% of the time I find myself writing Dart code, so this article will be focused on how we can be more efficient when programming apps with Flutter, using code generation tools.</p>
</blockquote>
<h1 id="heading-how">How?</h1>
<p><strong><em>FlutterGen</em></strong> is a relatively new code generator, it takes care of many of the big problems when working with local files, specifically resources that our apps use for branding (the logo, for example).</p>
<p>Well, a good practice is to always store the values that are used many times in the app in variables and classes.</p>
<p>We can move on from this:</p>
<pre><code class="lang-dart">Future callToAPI() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(<span class="hljs-string">'url_to_my_api.dev/api'</span>);
}

Future anotherCallToAPI() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(<span class="hljs-string">'url_to_my_api.dev/api/another'</span>);
}
</code></pre>
<p>To this:</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">API</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> url = <span class="hljs-string">'url_to_my_api.dev/api'</span>;
}

Future callToAPI() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(API.url);
}

Future anotherCallToAPI() <span class="hljs-keyword">async</span> {
    <span class="hljs-keyword">await</span> http.<span class="hljs-keyword">get</span>(<span class="hljs-string">'<span class="hljs-subst">${API.url}</span>/other'</span>);
}
</code></pre>
<p>A very simple way of only accessing the <code>url</code> property of the <code>API</code> class and that way we can use the same variable in other parts of our app. It is also easier if we change the string that contains <code>url</code> since it would be changed in all the parts where we use it.</p>
<h1 id="heading-setup">Setup</h1>
<p>To use FlutterGen, we need to configure it. We have 3 options:</p>
<ul>
<li>Homebrew.</li>
</ul>
<pre><code class="lang-dart">brew install FlutterGen/tap/fluttergen
</code></pre>
<ul>
<li>Pub.</li>
</ul>
<pre><code class="lang-dart">dart pub global activate flutter_gen
</code></pre>
<ul>
<li>build_runner. With Dart's build system there are usually some versioning conflicts between packages, so let's skip that for now.</li>
</ul>
<p>My suggestion, <strong><em>use Pub</em></strong>. You will have to update your <code>PATH</code> at the end of the installation, running the following command in the terminal: </p>
<pre><code class="lang-dart"><span class="hljs-keyword">export</span> PATH =<span class="hljs-string">"<span class="hljs-subst">$PATH</span>"</span>:<span class="hljs-string">"<span class="hljs-subst">$HOME</span>/.pub-cache/bin"</span>
</code></pre>
<p>Next, we must do the <code>pubspec.yaml</code> configuration. At this point, we must have assets included in the pubspec. Here is what you can copy and paste at the end of your file, the explanation goes in the comments.</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># here goes all the config for flutter_gen</span>
<span class="hljs-comment"># watch out for the indentations</span>
<span class="hljs-attr">flutter_gen:</span>
    <span class="hljs-comment"># by default, the generate files are in `lib/gen/`</span>
    <span class="hljs-comment"># you can set other directories like `lib/src/gen` using [output]</span>
  <span class="hljs-attr">output:</span> <span class="hljs-string">lib/src/gen/</span>

    <span class="hljs-comment"># if you use some linter that is line-of-code-sensitive</span>
    <span class="hljs-comment"># you can satisfy the lines it demands with [lineLength]</span>
    <span class="hljs-comment"># the default value is 80</span>
  <span class="hljs-attr">lineLength:</span> <span class="hljs-number">90</span>

  <span class="hljs-comment"># integrations are optional if you use another 3rd party</span>
    <span class="hljs-comment"># package, like [flutter_svg] to use .svg files like we</span>
    <span class="hljs-comment"># do with fonts and images</span>
    <span class="hljs-comment">#</span>
    <span class="hljs-comment"># it's important to have your integrations as project dependencies</span>
  <span class="hljs-attr">integrations:</span>
    <span class="hljs-attr">flutter_svg:</span> <span class="hljs-literal">true</span>

    <span class="hljs-comment"># you can also add color files in XML format</span>
    <span class="hljs-comment"># if you're reusing from an android project</span>
  <span class="hljs-attr">colors:</span>
    <span class="hljs-attr">inputs:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">assets/color/colors.xml</span>
</code></pre>
<p>Ok, that was all the configuration we had to do. Now let's see the magic.</p>
<h1 id="heading-generation-and-usage">Generation and usage</h1>
<p>We run the command:</p>
<pre><code class="lang-sh">fluttergen -c pubspec.yaml
</code></pre>
<p>Taking into consideration that the path to the pubspec may vary and must be checked in the case of getting an error. If all goes well, you will have a new <code>gen/</code> folder in the path you specified in the pubspec.</p>
<p>Now we are going to use the generated code. In the case of images, we access through <code>Assets</code>, until we reach the one we're going to use. Since our image becomes an <code>Image</code> object, then it is not necessary to wrap it in the widget, we just call the <code>image()</code> method:</p>
<pre><code class="lang-dart">Assets.images.background.image();
</code></pre>
<p>If we need text fonts, we have a class called <code>FontFamily</code>, where we have as properties the text strings that contain the identifiers of our fonts. We use them like this:</p>
<pre><code class="lang-dart">Text(
  <span class="hljs-string">'We\'re using fonts generated by FlutterGen'</span>,
  style: TextStyle(fontFamily: FontFamily.googleSans),
);
</code></pre>
<p>Finally, in order not to leave you without the example of the colors (in case someone uses them that way), we have a class called <code>ColorName</code> that allows us to access them.</p>
<pre><code class="lang-dart">Container(height: <span class="hljs-number">100</span>, width: <span class="hljs-number">100</span>, color: ColorName.justBlack);
</code></pre>
<p>Now we have our generated code and we know how to use it, we just have to start implementing it in our apps.</p>
<p>If you have any questions regarding this package, in this <a target="_blank" href="https://pub.dev/packages/flutter_gen">link</a> you can browse the documentation and you can also check its source code in its <a target="_blank" href="https://github.com/FlutterGen/flutter_gen">repo</a> from GitHub.</p>
]]></content:encoded></item></channel></rss>