<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bernardo Iribarne</title>
    <description>The latest articles on DEV Community by Bernardo Iribarne (@iriber).</description>
    <link>https://dev.to/iriber</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1161542%2F2e25e7b5-e854-4cb3-a1a7-88ff4d89fcc6.png</url>
      <title>DEV Community: Bernardo Iribarne</title>
      <link>https://dev.to/iriber</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iriber"/>
    <language>en</language>
    <item>
      <title>Dependency Injection in Flutter: implementing the Dependency Inversion principle</title>
      <dc:creator>Bernardo Iribarne</dc:creator>
      <pubDate>Fri, 15 Sep 2023 14:30:40 +0000</pubDate>
      <link>https://dev.to/iriber/dependency-injection-in-flutter-implementing-the-dependency-inversion-principle-1e0p</link>
      <guid>https://dev.to/iriber/dependency-injection-in-flutter-implementing-the-dependency-inversion-principle-1e0p</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/es/@varpap?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Vardan Papikyan&lt;/a&gt; on &lt;a href="https://unsplash.com/es/fotos/DnXqvmS0eXM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are looking to get your code to the next level, you have to know about dependency injection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When we write code we follow the SOLID guidelines. One of those principles (“D”) take care of Dependency Inversion. Let's see what it means.&lt;/p&gt;

&lt;p&gt;Suppose you have a service class called “UserService” that uses a datasource called UserSqlite to get users from a SQLite database:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VXcK8DYX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjfitifjiql9zurxb66i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VXcK8DYX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjfitifjiql9zurxb66i.png" alt="Package 1 depends on Package 2" width="535" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So Package 1 depends on Package 2. If you have this relation on your code, Mr. SOLID will go to your desktop and say: “Ey, do NOT couple your code with other libraries, what are you thinking about?”.&lt;/p&gt;

&lt;p&gt;What about this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NMeIpfex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hae2ez5kjbqrgq3cjx4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NMeIpfex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hae2ez5kjbqrgq3cjx4f.png" alt="Package 2 depends on Package 1" width="490" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What we have already done was change the dependency direction. Now, Package 2 depends on Package 1. The right direction of dependency makes our code reusable, and eliminates cyclic dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Injection
&lt;/h3&gt;

&lt;p&gt;The dependency injection concept will help us to drive the right implementation of the interface IUserDataSource to our UserService.&lt;/p&gt;

&lt;p&gt;UserService wouldn’t be concerned about the IUserDataSource implementation, it just uses it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can you implement Dependency Injection in Flutter?
&lt;/h2&gt;

&lt;p&gt;I use a package called get_it, you can find it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/get_it?source=post_page-----41094bd6b38c--------------------------------"&gt;GetIt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like to wrap the third party packages, because maybe tomorrow I want to change it to another that I like more than this. It is a premise that I have, you can skip that step, but it is one more thing that helps me to have my code the most descouple than I can.&lt;/p&gt;

&lt;p&gt;So, I created a class called DependencyManager which wraps the get_it library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PuJhwQJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/saameh20pxvebwlmp1gj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PuJhwQJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/saameh20pxvebwlmp1gj.png" alt="Dependency Manager" width="518" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inject dependencies
&lt;/h3&gt;

&lt;p&gt;In your app config class or your app initializer you have to inject the dependencies you want to have. In the example of the second picture, we have to inject the implementation of IUserDataSource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; void injectDependencies() {
    try {

      /// Get dependency manager
      DependencyManager manager = DependencyManager();

      /// Register UserSQLite as IUserDataSource
      manager.registerFactory&amp;lt;IUserDataSource&amp;gt;(() =&amp;gt; UserSQLite());


    } catch (e2) {
      debugPrint("Manage depency injections error");
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we must use this manager everywhere we need to use the user data source implementation. Let’s see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserService {

  /// User datasource.
  final IUserDataSource datasource= DependencyManager().get&amp;lt;IUserDataSource&amp;gt;();

  ....
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DependencyManager manages the implementations of our interface. It registers and returns concrete classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  DependencyManager
&lt;/h3&gt;

&lt;p&gt;To have the example simple I just showed you how to register a factory for our user datasource, but the dependency manager also could call constructors that requires some parameters, could be a little more complex.&lt;/p&gt;

&lt;p&gt;My DependencyManager looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:get_it/get_it.dart';

class DependencyManager {

  /// GetIt instance.  
  final getIt = GetIt.instance;

  /// I use singleton to create this manager.
  DependencyManager._internal();

  static final DependencyManager _singleton = DependencyManager._internal();

  factory DependencyManager() {
    return _singleton;
  }

  T get&amp;lt;T extends Object&amp;gt;(){
     return getIt.get&amp;lt;T&amp;gt;();
  }

  T getWithParam&amp;lt;T extends Object, P1&amp;gt;(dynamic p){
    return getIt.get&amp;lt;T&amp;gt;(param1: p);
  }

  T getWith2Param&amp;lt;T extends Object, P1, P2&amp;gt;(dynamic p1, dynamic p2){
    return getIt.get&amp;lt;T&amp;gt;(param1: p1, param2: p2);
  }

  bool isRegistered&amp;lt;T extends Object&amp;gt;(){
    return getIt.isRegistered&amp;lt;T&amp;gt;();
  }

  void registerLazySingleton&amp;lt;T extends Object&amp;gt;(FactoryFunc&amp;lt;T&amp;gt; factoryFunc){
    getIt.registerLazySingleton&amp;lt;T&amp;gt;(factoryFunc );
  }

  void registerFactory&amp;lt;T extends Object&amp;gt;(FactoryFunc&amp;lt;T&amp;gt; factoryFunc){
    getIt.registerFactory&amp;lt;T&amp;gt;(factoryFunc );

  }

  void registerFactoryParam&amp;lt;T extends Object, P1, P2&amp;gt;(
      FactoryFuncParam&amp;lt;T, P1, P2&amp;gt; factoryFunc, {
        String? instanceName,
      }){
    getIt.registerFactoryParam&amp;lt;T,P1,P2&amp;gt;(factoryFunc);
  }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;We talked about a &lt;strong&gt;SOLID&lt;/strong&gt; principle, the &lt;strong&gt;dependency inversion&lt;/strong&gt;, we introduced to &lt;strong&gt;dependency injection&lt;/strong&gt; and saw how to get implemented it in Flutter.&lt;/p&gt;

&lt;p&gt;Now you have the concept, and you know how to apply it. You will drive your code to the next level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Descoupled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testeable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy to mantain&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thanks for reading, Clap if you like it!&lt;/p&gt;

&lt;p&gt;Let me know your comments below.&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>dependencyinversion</category>
      <category>flutter</category>
      <category>cleancoding</category>
    </item>
    <item>
      <title>How to set environment variables in Flutter: a cleaned way</title>
      <dc:creator>Bernardo Iribarne</dc:creator>
      <pubDate>Thu, 14 Sep 2023 22:18:10 +0000</pubDate>
      <link>https://dev.to/iriber/how-to-set-environment-variables-in-flutter-a-cleaned-way-3fak</link>
      <guid>https://dev.to/iriber/how-to-set-environment-variables-in-flutter-a-cleaned-way-3fak</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/es/@rimakruciene?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Rima Kruciene&lt;/a&gt; on &lt;a href="https://unsplash.com/es/fotos/gpKe3hmIawg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since Flutter doesn’t have a standard way to use environment settings I will share a cleaned way to do it.&lt;/p&gt;

&lt;p&gt;I don’t like using plain text files so I design a few classes to manage the environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo7nxy7wku3u9nrgag0f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo7nxy7wku3u9nrgag0f.png" alt="Configuration classes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s see how this look like in our code.&lt;/p&gt;

&lt;p&gt;I created a simple AppConfig to show you how it works where I’ve just added a simple variable called appVersion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class AppConfig {

  /// App name
  String appName =&amp;gt; "My App";

  /// App version
  String appVersion =&amp;gt; "1.0.0";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I have a concrete AppConfig for each environment where I’ve rewrited the app version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AppConfigDev extends AppConfig{

  /// App version
  String appVersion =&amp;gt; "1.0.0-dev";
}

class AppConfigStaging extends AppConfig{

  /// App version
  String appVersion =&amp;gt; "1.0.0-staging";
}

class AppConfigProd extends AppConfig{

  /// App version
  String appVersion =&amp;gt; "1.0.0-release";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Environment class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The magic happens in Environment class. When you run your app in Flutter, you can send some parameters to your app, so I will show you how to send the environment you want to execute. Let’s see the Environment class and then I will talk about that parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '/src/config/app_config_prod.dart';
import '/src/config/app_config.dart';
import '/src/config/app_config_dev.dart';
import '/src/config/app_config_staging.dart';

/// Enumeration type for each environment
enum EnvironmentType {
  dev("DEV"), staging("STAGING"), prod("PROD");

  final String name;
  const EnvironmentType(this.name);
}

class Environment {

  /// Implements singleton
  Environment._internal();
  static final Environment _singleton = Environment._internal();

  factory Environment() {
    return _singleton;
  }

  late AppConfig config;

  Future&amp;lt;void&amp;gt; initConfig(String environment) async{

    config = _getConfig(environment);
  }

  AppConfig _getConfig(String environment) {
    Map&amp;lt;String, AppConfig&amp;gt; factories = &amp;lt;String, AppConfig&amp;gt;{};
    factories.putIfAbsent( EnvironmentType.dev.name, () =&amp;gt; AppConfigDev() );
    factories.putIfAbsent( EnvironmentType.staging.name, () =&amp;gt; AppConfigStaging() );
    factories.putIfAbsent( EnvironmentType.prod.name, () =&amp;gt; AppConfigProd() );

    AppConfig? config ;
    if( factories.containsKey(environment) ){
      config = factories[environment];
    }

    return config??AppConfigDev();
  }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This class has a method to initialize the configuration where it receives a string called environment. We are going to send that string to our App from the Run/Debug Configuration or from the command line. So, when we initialize our App, we have to include this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await Environment().initConfig(
       String.fromEnvironment('ENVIRONMENT')
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run your App with the desired environment
&lt;/h2&gt;

&lt;p&gt;Now when you run your app you have to send a parameter called ENVIRONMENT. You can do it from the command line or from your IDE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the command line:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flutter run --dart-define=ENVIRONMENT=DEV&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flutter run --dart-define=ENVIRONMENT=STAGING&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flutter run --dart-define=ENVIRONMENT=PROD&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From Android Studio:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have to go to “Edit Configurations” and create one entry for each environment. Below you can see some screenshots&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzugq00khpgvoumwnht81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzugq00khpgvoumwnht81.png" alt="Edit Configurations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ggwuxp2q2g0lfh368zj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ggwuxp2q2g0lfh368zj.png" alt="Entry for Staging"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrst2kssfl8ta5ew7y0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrst2kssfl8ta5ew7y0x.png" alt="I have one entry for each environment"&gt;&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpk3uf6ycwmke6abqdst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbpk3uf6ycwmke6abqdst.png" alt="Run for Staging"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ywlz1d8dj8ay2omwp0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ywlz1d8dj8ay2omwp0c.png" alt="A simple view with the App version that takes from the Environment"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We have configured our Flutter environment in a cleaned way. We saw a very simple case but you can improve AppConfig to have anything you want to manage as configuration. For example, I use to have the dependency injections in the AppConfig, so I can change the dependencies regarding to the environment, it is very useful to me.&lt;/p&gt;

&lt;p&gt;Thanks for reading, Clap if you like it!&lt;/p&gt;

&lt;p&gt;Let me know your comments below.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>tutorial</category>
      <category>development</category>
      <category>configuration</category>
    </item>
  </channel>
</rss>
