<?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: Firman Maulana</title>
    <description>The latest articles on DEV Community by Firman Maulana (@firmanmaulanaid).</description>
    <link>https://dev.to/firmanmaulanaid</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%2F1265643%2Fcd257161-bd4d-44a9-a57b-e1a72390b5fc.jpg</url>
      <title>DEV Community: Firman Maulana</title>
      <link>https://dev.to/firmanmaulanaid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/firmanmaulanaid"/>
    <language>en</language>
    <item>
      <title>Avoid Boilerplate with Code Generator in Flutter</title>
      <dc:creator>Firman Maulana</dc:creator>
      <pubDate>Thu, 19 Dec 2024 03:08:49 +0000</pubDate>
      <link>https://dev.to/tentanganak/avoid-boilerplate-with-code-generator-in-flutter-nb8</link>
      <guid>https://dev.to/tentanganak/avoid-boilerplate-with-code-generator-in-flutter-nb8</guid>
      <description>&lt;p&gt;As a software developer, you may encounter situations like writing code repeatedly for standard tasks. Imagine creating an application that needs integration with various APIs, managing JSON data, or performing tests. These tasks usually involve writing a lot of boilerplate code, which is time-consuming and increases the chance of mistakes.&lt;/p&gt;

&lt;p&gt;This can be very frustrating, especially when deadlines are approaching or when you are working on a complex project with many dependencies. Instead of focusing on innovation and solving more creative problems, you get stuck in a seemingly endless routine of writing code. This wastes valuable time and reduces your enthusiasm as a developer.&lt;/p&gt;

&lt;p&gt;This is where the importance of using code generators comes in. By utilizing code generation, you can reduce your workload in application development. You can automate repetitive processes, allowing you to focus on more strategic aspects and solve project-related problems. How can you use this in Flutter projects? Let's find out!&lt;/p&gt;

&lt;p&gt;The Dart ecosystem provides developers with a variety of powerful tools, one of which is code generation techniques. Yes, that's right! As the name suggests, this tool helps programmers generate code so that we don't need to write the whole code, but only the parts we need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Generation with build_runner
&lt;/h2&gt;

&lt;p&gt;Creating applications with Flutter often involves many common tasks, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deserializing JSON&lt;/li&gt;
&lt;li&gt;Using backend APIs&lt;/li&gt;
&lt;li&gt;Managing navigation&lt;/li&gt;
&lt;li&gt;Writing tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typically, completing these tasks involves writing repetitive code, which can be time-consuming and error-prone. However, we can reduce the amount of code we need to write manually by using build_runner to generate the required code.&lt;/p&gt;

&lt;p&gt;In simple terms, &lt;strong&gt;build_runner&lt;/strong&gt; is a tool for generating output files from input files. We can create a code generator that works with this mechanism, which allows us to read input files, usually written in Dart code, and generate the corresponding output files.&lt;/p&gt;

&lt;p&gt;Using this generator, we only need to provide a minimal configuration for the desired code. After the build process is complete, we will receive a valid Dart code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are the steps to use build_runner:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add it as a development dependency in the &lt;strong&gt;pubspec.yaml&lt;/strong&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   dev_dependencies:
     build_runner: x.y.z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the code generation command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   flutter pub run build_runner build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, build_runner will execute all the code generators added as dependencies and generate output based on the input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch Mode and Handling Existing Files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;build_runner also has a watch mode that monitors the file system and automatically updates the output files when the input files change. If files are considered existing and not generated by build_runner, a reminder will appear to delete those files.&lt;/p&gt;

&lt;p&gt;The -d option (short for --delete-conflicting-outputs) allows build_runner to delete conflicting files before starting code generation, making the process easier.&lt;/p&gt;

&lt;p&gt;For a more detailed explanation, you can check here: build_runner &lt;a href="https://pub.dev/packages/build_runner" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;There are many packages we can use, but this time we will look at some of the most popular ones. Some of these packages work with the build_runner tool. They make app development easier, so developers can focus more on what they want to create instead of how to create it. Here are some commonly used packages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;json_serializable&lt;/strong&gt;&lt;br&gt;
This package makes it easy to turn JSON data into Dart objects and vice versa.&lt;br&gt;
By using these packages together, we can work faster and more efficiently when building Flutter apps.&lt;/p&gt;

&lt;p&gt;For example, we can create an app that shows data from a JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "id": 1,
     "user": {
       "name": "Asep Saepul",
       "avatar": "https://images.pexels.com/photos/27659838/pexels-photo-27659838/free-photo-of-portrait-of-a-man-on-a-white-background.jpeg?auto=compress&amp;amp;cs=tinysrgb&amp;amp;w=800",
       "place": "Bandung, Indonesia"
     },
     "content": {
       "isLike": false,
       "image": "https://images.pexels.com/photos/3386600/pexels-photo-3386600.jpeg?auto=compress&amp;amp;cs=tinysrgb&amp;amp;w=600",
       "likes": "1.000 likes",
       "description": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor."
     }
   },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be used further in the application and take advantage of the typed nature of Dart, this data must be transformed into an instance of a Dart class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Feed {
 final int id;
 final User user;
 Content content;


 Feed({
   required this.id,
   required this.user,
   required this.content,
 });
}


class Content {
 final String image;
 late final String likes;
 final String description;
 bool isLike;
  Content({
   required this.image,
   required this.likes,
   required this.description,
   required this.isLike,
 });
}


class User {
 final String name;
 final String avatar;
 final String place;


 User({
   required this.name,
   required this.avatar,
   required this.place,
 });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To implement JSON deserialization in the &lt;code&gt;fromJson()&lt;/code&gt; and &lt;code&gt;toJson()&lt;/code&gt; methods within a class to allow the following usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Feed {
  final int id;
  final User user;
  Content content;

  Feed({
    required this.id,
    required this.user,
    required this.content,
  });

  // Method to convert Feed object to JSON
  Map&amp;lt;String, dynamic&amp;gt; toJson() {
    return {
      'id': id,
      'user': user.toJson(),
      'content': content.toJson(),
    };
  }

  // Method to create Feed object from JSON
  factory Feed.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) {
    return Feed(
      id: json['id'],
      user: User.fromJson(json['user']),
      content: Content.fromJson(json['content']),
    );
  }
}

class Content {
  final String image;
  late final String likes;
  final String description;
  bool isLike;

  Content({
    required this.image,
    required this.likes,
    required this.description,
    required this.isLike,
  });

  // Method to convert Content object to JSON
  Map&amp;lt;String, dynamic&amp;gt; toJson() {
    return {
      'image': image,
      'likes': likes,
      'description': description,
      'isLike': isLike,
    };
  }

  // Method to create Content object from JSON
  factory Content.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) {
    return Content(
      image: json['image'],
      likes: json['likes'],
      description: json['description'],
      isLike: json['isLike'],
    );
  }
}

class User {
  final String name;
  final String avatar;
  final String place;

  User({
    required this.name,
    required this.avatar,
    required this.place,
  });

  // Method to convert User object to JSON
  Map&amp;lt;String, dynamic&amp;gt; toJson() {
    return {
      'name': name,
      'avatar': avatar,
      'place': place,
    };
  }

  // Method to create User object from JSON
  factory User.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) {
    return User(
      name: json['name'],
      avatar: json['avatar'],
      place: json['place'],
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the static method &lt;code&gt;Feed.fromJson()&lt;/code&gt; handles the parsing logic for the various field types in Feed, such as int and the custom classes User and Content, which also have &lt;code&gt;User.fromJson()&lt;/code&gt; and &lt;code&gt;Content.fromJson()&lt;/code&gt; factories. Additionally, the example above also includes the Feed.toJson() method that performs the inverse transformation.&lt;/p&gt;

&lt;p&gt;The json_serializable package allows for the same result with much less code. It can generate methods like &lt;code&gt;Feed.fromJson()&lt;/code&gt; and &lt;code&gt;Feed.toJson()&lt;/code&gt; and provides a mechanism to perform all the formatting adjustments as in the manual implementation above.&lt;/p&gt;

&lt;p&gt;To take advantage of code generation for JSON deserialization, add the following dependency in your &lt;strong&gt;pubspec.yaml&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  json_annotation: x.y.z

dev_dependencies:
  build_runner: x.y.z
  json_serializable: x.y.z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then an example of implementation by creating a Feed class as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;part feed.g.dart';

@JsonSerializable(explicitToJson: true, includeIfNull: false)
class Feed with _$Feed {
  const factory Feed({
    required int id,
    required User user,
    required Content content,
  }) = _Feed;

  factory Feed.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt; _$FeedFromJson(json);

Map&amp;lt;String, dynamic&amp;gt; toJson() =&amp;gt; _$FeedToJson(this);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@JsonSerializable()&lt;/code&gt; annotation above the Feed class indicates that this class is subject to code generation, and the declaration of the &lt;strong&gt;feed.g.dart&lt;/strong&gt; section file ensures that the generated code is in the same &lt;strong&gt;feed.dart&lt;/strong&gt;. Once the code is generated, a new feed.g.dart file is added with the private methods &lt;code&gt;_$FeedFromJson()&lt;/code&gt; and &lt;code&gt;_$FeedToJson()&lt;/code&gt;, allowing the same results as the previous manual implementation.&lt;/p&gt;

&lt;p&gt;Using code generation significantly reduces the amount of code that needs to be written compared to a manual JSON deserialization implementation. Additionally, every time the JSON format or Dart class structure is updated, a manual implementation requires changes in several places, which are easy to miss until a serialization exception is raised at runtime. With code generation, we can ensure that all necessary changes are applied automatically.&lt;/p&gt;

&lt;p&gt;This guide only shows the basic usage of the json_serializable package. Check the official documentation for more information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhance Classes with Freezed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are several operations that developers perform on Dart class instances explicitly or implicitly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;value-based comparisons&lt;/li&gt;
&lt;li&gt;hash code calculations&lt;/li&gt;
&lt;li&gt;using string representations&lt;/li&gt;
&lt;li&gt;making copies with modifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implementations of some of these operations, such as the ==() operator, hashCode, and toString(), are already built into the language but do not provide the best development experience and therefore require improvement, such as the &lt;code&gt;copyWith()&lt;/code&gt; method, must be written from scratch.&lt;/p&gt;

&lt;p&gt;Let’s consider the Feed class from the example above as an example. Two instances with the same field value are not equal, and their hash values ​​are also different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final feed1 = Feed(
        id: 1,
        user: User(
          name: 'John Dhoe',
          avatar:
              'https://images.png’,
          place: 'Bandung, Indonesia',
        ),
        content: Content(
          isLike: false,
          image:
                 'https://images.png’,
          likes: '1.000 likes',
          description:
              'Lorem ipsum dolor sit amet',
        ),
      ),
final feed2 = Feed(
        id: 1,
        user: User(
          name: 'John Dhoe',
          avatar:
              'https://images.png’,
          place: 'Bandung, Indonesia',
        ),
        content: Content(
          isLike: false,
          image:
                 'https://images.png’,
          likes: '1.000 likes',
          description:
              'Lorem ipsum dolor sit amet',
        ),
      ),
assert(feed1 == feed2);                    // false
assert(feed1.hashCode == feed2.hashCode);  // false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can cause problems when Feed instances are added to a Set, used as Map keys, or verified in tests.&lt;/p&gt;

&lt;p&gt;At the same time, the string representations of two instances with different field values ​​are the same and return an Instance of Feed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assert(feed1.toString() == feed2.toString());  // true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enhance the Feed class, we need to provide implementations of the following methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   // Override == operator
  @override
  bool operator ==(Object other) =&amp;gt;
      identical(this, other) ||
      other is Feed &amp;amp;&amp;amp;
          runtimeType == other.runtimeType &amp;amp;&amp;amp;
          id == other.id &amp;amp;&amp;amp;
          user == other.user &amp;amp;&amp;amp;
          content == other.content;

  // Override hashCode
  @override
  int get hashCode =&amp;gt;
      id.hashCode ^ user.hashCode ^ content.hashCode;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the problem doesn't stop there, because the &lt;code&gt;user == other.user&lt;/code&gt; check will likely fail most of the time even if both collections are empty or contain the same objects. To compare collections based on their contents, it should be replaced with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const DeepCollectionEquality().equals(user, other.user)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Freezed&lt;/strong&gt; package allows us to not worry about this situation. To take advantage of Freezed in code generation to enhance Dart classes, add this dependency in the pubspec.yaml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  freezed_annotation: x.y.z

dev_dependencies:
  build_runner: x.y.z
  freezed: x.y.z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is an example of its implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@freezed
class Feed with _$Feed {
 const factory Feed({
   required int id,
   required User user,
   required Content content,
 }) = _Feed;


 factory Feed.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt; _$FeedFromJson(json);
}


@freezed
class Content with _$Content {
 const factory Content({
   required String image,
   required String likes,
   required String description,
   required bool isLike,
 }) = _Content;


 factory Content.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt; _$ContentFromJson(json);
}


@freezed
class User with _$User {
 const factory User({
   required String name,
   required String avatar,
   required String place,
 }) = _User;


 factory User.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) =&amp;gt; _$UserFromJson(json);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@freezed&lt;/code&gt; annotation above the Feed class indicates that it is subject to code generation, and the declaration of the '&lt;strong&gt;feed.freezed.dart&lt;/strong&gt;' file section ensures that the generated code is part of the same as &lt;strong&gt;feed.dart&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fz4kdegsa1bfdmv0i1agn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fz4kdegsa1bfdmv0i1agn.png" alt="Feed Directory" width="380" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the Feed, Content, and User classes. You can check from the examples repository for the complete implementations. Once the code is generated, a new file &lt;strong&gt;feed.freezed.dart&lt;/strong&gt; is added with implementations of &lt;code&gt;the ==()&lt;/code&gt;, &lt;code&gt;hashCode&lt;/code&gt;, &lt;code&gt;toString()&lt;/code&gt;, and &lt;code&gt;copyWith()&lt;/code&gt; operator methods, allowing for the same results as the manual implementation above.&lt;/p&gt;

&lt;p&gt;As with JSON deserialization, using code generation to enhance Dart classes reduces the effort of creating and maintaining them, ensuring that any necessary changes are automatically applied when the class structure changes.&lt;/p&gt;

&lt;p&gt;This guide only shows the basic usage of the freezed package. It has many useful features and can also be easily combined with &lt;strong&gt;json_serializable&lt;/strong&gt;. Check the official &lt;a href="https://pub.dev/packages/freezed" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;There are still many packages that you can use for code generation, such as for RESTful API Consumption needs you can use &lt;strong&gt;Retrofit&lt;/strong&gt;, Flutter Dependency Injection with &lt;strong&gt;Injectable&lt;/strong&gt;, Documentation and Tests with &lt;strong&gt;mockito&lt;/strong&gt;, and many more. Hopefully, in the next article, we can try to learn each of these packages to compare and learn how to implement them in our projects.&lt;/p&gt;

&lt;p&gt;But for now, I think it's enough to know examples of using &lt;strong&gt;json_serializable&lt;/strong&gt; and &lt;strong&gt;freezed&lt;/strong&gt; as a first step to finding out the benefits of codegen and how we use it in a flutter project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawback
&lt;/h2&gt;

&lt;p&gt;Okay, we already know how many benefits we can get from code generators. But keep in mind, we often have to look at things from both sides. Yes, codegen also has disadvantages that we need to consider before using it. In my Flutter project, I found some things when using codegen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time-consuming&lt;/strong&gt;: Basic code generation can be time-consuming for complex data structures or requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initial setup&lt;/strong&gt;: Code generation requires some initial setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slows down the build process&lt;/strong&gt;: The generated code can slow the build process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clutters the project&lt;/strong&gt;: The generated code can clutter your project with extra files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requires team members to run the codegen step&lt;/strong&gt;: If you don't commit the generated files to git, every team member must remember to run the codegen step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requires a custom CI build step&lt;/strong&gt;: If you don't commit the generated files to git, a custom CI build step is required to build the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;A simple Flutter demo project using &lt;strong&gt;Freezed&lt;/strong&gt; package is available on &lt;a href="https://github.com/firman-ta/flutter-simplecodegen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fir4iim5nd6btf080g3bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fir4iim5nd6btf080g3bf.png" alt="App Screenshots" width="800" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Code generation is a powerful tool that can make us more productive by facilitating many repetitive or typical tasks in Flutter application development.&lt;/p&gt;

&lt;p&gt;In addition, those packages not only speed up the development process but also maintain the consistency and accuracy of the generated code. By utilizing these tools, developers can streamline their workflows, improve project maintenance, and ensure that structural changes in the code are automatically updated, which is an important step in maintaining the quality and sustainability of the application in the future.&lt;/p&gt;

&lt;p&gt;However, besides the many benefits of using code generation, there are also things to consider. For example, parts of the code that have changed and impacted other parts must be re-generated, which may take more time than changing it manually. So, it is adjusted again to the needs of the project you are working on. If you have tried it, don't hesitate to share your experience in the comments; hopefully, it's useful!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.flutter.dev/" rel="noopener noreferrer"&gt;https://docs.flutter.dev/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pub.dev/packages/build_runner" rel="noopener noreferrer"&gt;https://pub.dev/packages/build_runner&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pub.dev/packages/freezed" rel="noopener noreferrer"&gt;https://pub.dev/packages/freezed&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>softwaredevelopment</category>
      <category>mobile</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Your Flutter App Feels Slow and How to Fix It?</title>
      <dc:creator>Firman Maulana</dc:creator>
      <pubDate>Mon, 09 Sep 2024 08:43:49 +0000</pubDate>
      <link>https://dev.to/tentanganak/why-your-flutter-app-feels-slow-and-how-to-fix-it-294d</link>
      <guid>https://dev.to/tentanganak/why-your-flutter-app-feels-slow-and-how-to-fix-it-294d</guid>
      <description>&lt;p&gt;Have you ever used an app and noticed the UI is choppy on some pages? This might not be a big deal for some people as long as the main process is running smoothly. However, if this happens continuously, it can be very annoying, and users might start looking for other similar apps that are more convenient to use, which will cause a decrease in the number of users of your app 😢.&lt;/p&gt;

&lt;p&gt;Maybe some of you think that the slowness of an application is very subjective based on user experience, right? It could be that the application is fine but users feel very slow and vice versa. If so, it will be difficult to assess the quality of an application. So we should look at other more measurable ways. One of them is for Android applications, you can use &lt;strong&gt;Android Vitals&lt;/strong&gt; in &lt;strong&gt;Google Play Console&lt;/strong&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%2Fnlv05t2gfadi2hbxpl95.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%2Fnlv05t2gfadi2hbxpl95.png" alt="Android Vitals"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see comparison metrics that show how well or poorly &lt;strong&gt;your application&lt;/strong&gt; performs compared to other &lt;strong&gt;similar applications&lt;/strong&gt; on the market, which is useful for helping developers identify areas that need improvement. As developers, we want our apps to be useful and provide a good experience for users. In app development, an optimal user experience often depends on how good the user interface (UI) looks. A slow or inefficient UI can lead to performance degradation.&lt;/p&gt;

&lt;p&gt;You may have heard this before: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Flutter is fast by default, so you don’t need to worry about performance. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this is generally true, you don’t need to optimize your app prematurely or when it’s not needed. We need to understand what might be causing your app to slow down and focus more on how Flutter’s rendering works underneath the widgets you use. Well, this is something I experienced a while back too. So, I explored the app and there are a few things I want to share with you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Rendering Phases&lt;/strong&gt;&lt;br&gt;
Before doing anything, even fixing our code, the important thing is you must first understand the process so you can figure out what the problem is and how to fix it later. There are several phases for UI rendering. You can see the sequencing diagram below.&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%2F4qhzhftadsfm8oequevt.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%2F4qhzhftadsfm8oequevt.png" alt="Flutter sequencing diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The build phase is our responsibility as Flutter developers and the one we have the most control over. Here, our widgets are rebuilt, and the related elements for them are created. From those widgets, we also create the relevant rendering objects. Then, we enter the layout and painting phase, which is managed by the framework or the rendering object, and in general, we don’t need to worry about layout and painting. Of course, you can create custom-rendered objects or manage &lt;code&gt;CustomPainting&lt;/code&gt; via &lt;code&gt;CustomPainter&lt;/code&gt;. Maybe later, we will try to understand it in more detail.&lt;/p&gt;

&lt;p&gt;Now, I want to talk about rendering jank. Flutter targets 60 frames per second, which is good for mobile apps. If it takes too long, it will cause janks. Jank can be triggered for various reasons, one of which is because a lot of work is done on the UI thread or raster thread, which causes delays in completing frames. Work on the UI thread usually involves updating the state, rebuilding widgets, or performing heavy operations such as calculations, parsing, or fetching data. The work on the raster thread can be complex graphic rendering, such as drawing large images, complex animations, or other visual effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolate
&lt;/h2&gt;

&lt;p&gt;To reduce the risk of jank, we must be careful in writing code to avoid heavy operations on the UI thread or Raster thread. For example, heavy operations can be moved to isolate to run in the background, so that the UI thread remains responsive. We can also optimize the code with good state management, use widgets that are appropriate for our needs, and avoid complex animations or large images that require a lot of GPU resources. An isolate is like a separate worker that can do heavy tasks in the background without blocking the main UI thread. This way, the UI stays smooth and responsive even when your app is doing something complex.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does an Isolate Work?&lt;/strong&gt;&lt;br&gt;
Think of the main UI thread as a waiter in a restaurant. If you give the waiter too many tasks, like cooking food or washing dishes, they won't have time to serve the customers. In Flutter, if the main UI thread is busy doing heavy tasks, the app becomes slow.&lt;/p&gt;

&lt;p&gt;Instead, we can hire another worker (an isolate) to handle those heavy tasks, like calculating big numbers or processing large data files. The main UI thread can keep handling user interactions, like scrolling or tapping buttons, while the isolate does the heavy lifting in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of Using an Isolate&lt;/strong&gt;&lt;br&gt;
Let's say we want to calculate a list of prime numbers, which is a heavy task. Instead of doing this on the main thread, we use an isolate to do it in the background:&lt;/p&gt;

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

void calculatePrimes(SendPort sendPort) {
  final List&amp;lt;int&amp;gt; primes = [];
  int num = 2;

  // Calculate prime numbers
  while (primes.length &amp;lt; 10000) {
    if (isPrime(num)) {
      primes.add(num);
    }
    num++;
  }

  // Send the results back to the main thread
  sendPort.send(primes);
}


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

&lt;/div&gt;

&lt;p&gt;We create a separate worker (isolate) to calculate prime numbers.&lt;br&gt;
The calculatePrimes function runs in the isolate, so it doesn't slow down the main thread. When the calculation is done, the isolate sends the result back to the main thread using SendPort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing Build
&lt;/h2&gt;

&lt;p&gt;Flutter provides &lt;a href="https://docs.flutter.dev/tools/devtools" rel="noopener noreferrer"&gt;devtools&lt;/a&gt; that can help monitor your app's performance and identify potential causes of jank. This allows you to determine what steps you can take to improve performance, especially in rendering the UI in your app. There are several things I noticed and found from the case I experienced and of course, based on articles and other developers who encountered similar cases. So I tried to group action items that you can try to improve performance, especially in rendering the app you created. There will be many things based on the project you are working on. Here I will try to focus on one thing that can be done on any project, &lt;strong&gt;build optimization&lt;/strong&gt;. What are those things? Let's find out!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Use Constant Widgets&lt;/strong&gt;&lt;br&gt;
The first thing, you should always do is take advantage of constant widgets whenever possible. We can talk a lot about the benefits of const. &lt;code&gt;Const&lt;/code&gt; variables are compile-time constants, meaning one const object will be created and reused no matter how much the const expression is evaluated. For widgets, this means Flutter will not unnecessarily rebuild widgets marked as const. Flutter will be smart in determining that the build of that widget will not change, so it can sometimes skip the rebuild process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Static and Non-const Objects&lt;/strong&gt;&lt;br&gt;
You can also use static objects for objects that cannot become constants. Use static when the class cannot become constant, but you only need one instance throughout your project.&lt;/p&gt;

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

class NotConstant {
  static final anotherContConstant = NotConstantAnother();
  NotConstant() {
    print(anotherContConstant);
  }
}



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

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

class NotConstantAnother {}


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

&lt;/div&gt;

&lt;p&gt;For example, both of these classes are not constants, and we create 100 instances of the NotConstant class. Inside that class, we create a static final NotConstantAnother, and inside the constructor, we print the &lt;code&gt;static&lt;/code&gt; object.&lt;/p&gt;

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

void createInstance() {
  for (var i = 0; i &amp;lt; 50; i++) {
    final notConstant = NotConstant();
  }
}


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

&lt;/div&gt;

&lt;p&gt;When we try to create 50 instances of notConstant as in the code above, we only have an instance of anotherContConstant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Optimizing Execution&lt;/strong&gt;&lt;br&gt;
We can also sometimes improve readability by using the late keyword. This example is the same as before, but note that operation1 and operation2 will only call the expensive operation when we try to access them because of the late keyword. This is called lazy computation.&lt;/p&gt;

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

void doSomething() {
  const condition = true;
  late final hasPubspecFile = File('pubspec.yaml').existsSync();
  late final hasTestFolder = Directory('test').existsSync();

  // if the condition is false, has TestFolder/has PubspecFile will not be computed
  // Similarly if "hasTestFolder" is false, hasPubspecFile will not be computed
  if (condition &amp;amp;&amp;amp; hasTestFolder &amp;amp;&amp;amp; hasPubspecFile) {
    print('Hello world');
  }
}


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;4. Prefer Small Widgets&lt;/strong&gt;&lt;br&gt;
Back to widgets. The next important thing to reduce the cost of building widgets is to prefer smaller widgets. The main benefit is reducing the number of widgets that need to be rebuilt when calling &lt;code&gt;setState&lt;/code&gt;, and it also makes testing much easier.&lt;/p&gt;

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


class _MyHomePageState extends State&amp;lt;MyHomePage&amp;gt; {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: &amp;lt;Widget&amp;gt;[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}


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

&lt;/div&gt;

&lt;p&gt;Here we have the old example with the counter. When you press the floating button, it calls &lt;code&gt;setState&lt;/code&gt;, which causes all widgets in MyHomePage to be rebuilt, except that marked const. Can you think of a better way to avoid all these widgets being rebuilt unnecessarily? You're right, state management. The state management frameworks we have are great, and they all have their ways of reducing widget rebuilds in your app. You can use flutter_bloc, riverpod, or whatever you like and fits the project you're developing.&lt;/p&gt;

&lt;p&gt;The next question is which is better, preferring widgets or making helper methods? Try looking at the code below:&lt;/p&gt;

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


@override
Widget build(BuildContext context) {
  return const MyHomePage();
}


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

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

@override
Widget build(BuildContext context) {
  return myHomePage();
}


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

&lt;/div&gt;

&lt;p&gt;We have indirectly touched on some points as to why you should prefer custom widgets. The main reason is that when we call &lt;code&gt;setState&lt;/code&gt; to rebuild certain widgets, we want to limit that to only rebuilding what is needed. This becomes very difficult to do with helper methods because our build becomes very large, and as a result, just because of the use of helper methods.&lt;/p&gt;

&lt;p&gt;Helper methods cause unwieldy big widgets. Calling &lt;code&gt;setState&lt;/code&gt; in a helper method will cause the entire widget and all other helper methods in that widget to rebuild. Custom widgets have the option to be marked as const when possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Using Lazy Loading List&lt;/strong&gt;&lt;br&gt;
The main concept of a lazy loading list will render items visible on the screen, while other items will only be rendered when &lt;strong&gt;needed&lt;/strong&gt;. These practices can be very beneficial if you are working with large lists. Of course, you can apply the same principle to GridView using GridView.builder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Example
&lt;/h2&gt;

&lt;p&gt;Okay, now let’s get to the fun part and explore the tools and examples. The best way to understand Flutter is to examine the underlying code. But today I’ll try to show you a simple example app that we can use to compare the implementation of the optimizations we discussed earlier. &lt;/p&gt;

&lt;p&gt;In our Flutter app, &lt;a href="https://github.com/firman-ta/flutter-prime-number-isolate" rel="noopener noreferrer"&gt;here&lt;/a&gt; is the complete project, we have one homepage with two buttons to display the prime numbers page, each with a different approach to handling performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommended Page&lt;/strong&gt;&lt;br&gt;
The Recommended Page implements some of the things we discussed above. The app performs the heavy computation required to render the prime number list on a separate thread using Dart’s Isolate. This means that while the computation is running, the main thread, which is responsible for handling the user interface, remains free to update and respond to user interactions. As a result, users experience a smooth and responsive app because the intensive processing does not block or slow down the interface.&lt;/p&gt;

&lt;p&gt;Additionally, the Recommended Page uses lazy loading via ListView.builder. This technique ensures that only items currently visible on the screen are displayed. As the user scrolls, new items are loaded dynamically. This approach significantly reduces memory usage and improves performance because it avoids loading and rendering the entire prime list at once. Users enjoy a smoother scrolling experience without any noticeable lag or delay.&lt;/p&gt;

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


class RecommendedPage extends StatefulWidget {
  const RecommendedPage({Key? key}) : super(key: key);

  @override
  State&amp;lt;RecommendedPage&amp;gt; createState() =&amp;gt; _RecommendedPageState();
}

class _RecommendedPageState extends State&amp;lt;RecommendedPage&amp;gt; {
  late Future&amp;lt;List&amp;lt;int&amp;gt;&amp;gt; _primesFuture;
  late ReceivePort _receivePort;
  Isolate? _isolate;

  @override
  void initState() {
    super.initState();
    _receivePort = ReceivePort();
    // Initiates the prime number computation in a separate isolate.
    // This approach prevents UI blocking and ensures a smooth user experience.
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _primesFuture = _computePrimes();
    });
  }

  @override
  void dispose() {
    // Properly closes the receive port and terminates the isolate when the widget is disposed of.
    // This avoids memory leaks and ensures the isolate is not running in the background unnecessarily.
    _receivePort.close();
    _isolate?.kill(priority: Isolate.immediate);
    super.dispose();
  }

  Future&amp;lt;List&amp;lt;int&amp;gt;&amp;gt; _computePrimes() async {
    // Spawns a new isolate to perform the prime number computation.
    _isolate =
        await Isolate.spawn(_computePrimesInIsolate, _receivePort.sendPort);

    // Listens for the results sent from the isolate.
    // Using isolates allows for parallel processing without blocking the main thread.
    final List&amp;lt;int&amp;gt; primes = await _receivePort.first;
    return primes;
  }

  static void _computePrimesInIsolate(SendPort sendPort) {
    // Performs the prime number computation in a separate isolate.
    // The computation does not affect the UI performance.
    final List&amp;lt;int&amp;gt; primes = [];
    int num = 2;
    while (primes.length &amp;lt; 10000) {
      if (_isPrime(num)) {
        primes.add(num);
      }
      num++;
    }
    sendPort.send(
        primes); // Sends the computed list of primes back to the main isolate.
  }

  static bool _isPrime(int number) {
    // Determines if a number is prime.
    if (number &amp;lt;= 1) return false;
    for (int i = 2; i &amp;lt;= number ~/ 2; i++) {
      if (number % i == 0) return false;
    }
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Recommended'),
      ),
      body: FutureBuilder&amp;lt;List&amp;lt;int&amp;gt;&amp;gt;(
        future: _primesFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          } else if (snapshot.hasData) {
            final primes = snapshot.data!;
            // Efficiently displays the list of prime numbers using ListView.builder.
            // This approach lazily builds widgets only for the visible items, optimizing memory usage.
            return ListView.builder(
              itemCount: primes.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text('Prime ${primes[index]}'),
                );
              },
            );
          } else {
            return const Center(child: Text('No data available'));
          }
        },
      ),
    );
  }
}



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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NotRecommended Page&lt;/strong&gt;&lt;br&gt;
The NotRecommended Page handles prime number computation directly on the main thread. This means the app’s interface can become unresponsive during the computation because the main thread is busy processing tasks. Users may experience freezing or slowdowns because the UI thread cannot update or handle interactions while it is busy generating the main list.&lt;/p&gt;

&lt;p&gt;The NotRecommended Page also uses a traditional ListView that simultaneously loads and renders all list items. This method increases memory usage because all items are processed and stored in memory at once. As a result, scrolling becomes less smooth and can cause lag, especially if the list is very large. Users may notice performance issues like stuttering or slowness when interacting with the list.&lt;/p&gt;

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

class NotRecommendedPage extends StatefulWidget {
  const NotRecommendedPage({Key? key}) : super(key: key);

  @override
  State&amp;lt;NotRecommendedPage&amp;gt; createState() =&amp;gt; _NotRecommendedPageState();
}

class _NotRecommendedPageState extends State&amp;lt;NotRecommendedPage&amp;gt; {
  late Future&amp;lt;List&amp;lt;int&amp;gt;&amp;gt; _primesFuture;

  @override
  void initState() {
    super.initState();
    // Initialize the future that will compute prime numbers.
    // This computation happens on the main thread, which may cause the UI to freeze.
    _primesFuture = _computePrimes();
  }

  Future&amp;lt;List&amp;lt;int&amp;gt;&amp;gt; _computePrimes() async {
    // Simulates heavy computation on the main thread.
    // This can block the UI, making it unresponsive during the calculation.
    final List&amp;lt;int&amp;gt; primes = _generatePrimes();
    return primes;
  }

  List&amp;lt;int&amp;gt; _generatePrimes() {
    // Generates a list of prime numbers up to a certain count.
    final List&amp;lt;int&amp;gt; primes = [];
    int num = 2;
    while (primes.length &amp;lt; 10000) {
      if (_isPrime(num)) {
        primes.add(num);
      }
      num++;
    }
    return primes;
  }

  bool _isPrime(int number) {
    if (number &amp;lt;= 1) return false;
    for (int i = 2; i &amp;lt;= number ~/ 2; i++) {
      if (number % i == 0) return false;
    }
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Not Recommended'),
      ),
      body: FutureBuilder&amp;lt;List&amp;lt;int&amp;gt;&amp;gt;(
        future: _primesFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          } else if (snapshot.hasData) {
            final primes = snapshot.data!;
            // Displays the list of prime numbers in a scrollable column.
            // This approach may cause performance issues for a large number of items because it renders all items at once.
            return SingleChildScrollView(
              child: Column(
                children: primes.map((prime) {
                  return ListTile(
                    title: Text('Prime $prime'),
                  );
                }).toList(),
              ),
            );
          } else {
            return const Center(child: Text('No data available'));
          }
        },
      ),
    );
  }
}



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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Run Our Flutter App&lt;/strong&gt;&lt;br&gt;
Okay, now let’s try running our app in &lt;strong&gt;profile mode&lt;/strong&gt;. Of course, profile mode still has some pretty cool debugging capabilities for profiling your app’s performance. So, here’s what our simple app looks like.&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%2Fakz2y9rczrxi25rdr6ns.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%2Fakz2y9rczrxi25rdr6ns.png" alt="App UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Profile mode is disabled on the emulator and simulator because its behavior does not represent real-world performance, so you need to make changes on the device.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When running with &lt;strong&gt;profile mode&lt;/strong&gt; you can see in the terminal there is a Flutter &lt;strong&gt;DevTools&lt;/strong&gt; URL that you can use to monitor your application. Now you open it in the browser and will be directed to the devtools page, we are talking about UI rendering so we go to the &lt;strong&gt;performance&lt;/strong&gt; tab. &lt;/p&gt;

&lt;p&gt;You can also activate the enhance tracing menu to add detail to the trace timeline. Here I try to check the &lt;strong&gt;Track Widget Builds&lt;/strong&gt; section. &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%2F53tqi3hfplz3ynnkgp1k.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%2F53tqi3hfplz3ynnkgp1k.png" alt="Enhance Tracing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you enter the &lt;strong&gt;recommended page&lt;/strong&gt;, you can see that there are no distracting UI blocks. While using Isolate helps move heavy computations (such as generating a list of prime numbers) off the main thread, there are still some operations or UI elements that may require uncompiled shaders, and triggering the first shader compilation. Okay, then you scroll the page and look back at the devtools. As you can see the page scrolls smoothly, and there is no jank found.&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%2Fglty1bkkswt3boxahofh.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%2Fglty1bkkswt3boxahofh.png" alt="Recommended Page Devtools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's try to tap the &lt;strong&gt;Not Recommended&lt;/strong&gt; button to enter the page. You will be stuck for a while before being directed to the not recommended page and after that try to scroll and look back at the devtools. You will find so much jank and the user experience becomes uncomfortable because the scrolling does not run smoothly.&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%2Fg8idkxpyitiagf8uzxl3.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%2Fg8idkxpyitiagf8uzxl3.png" alt="Not Recommended Page"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Performance optimization, especially related to UI rendering, which is the focus of this discussion, may not be something that must be done from the beginning of the project, but it is important enough to understand to determine our steps and know which parts are the main priority or can be postponed for the next stage.&lt;/p&gt;

&lt;p&gt;Keep in mind that many factors cause it. There are also those that we can control as developers, which are difficult or even impossible, such as things that are directly related to the characteristics of the technology we use or even the user's device. So once again, let's focus on the parts that we can control, one of which is improving code quality.&lt;/p&gt;

&lt;p&gt;The few ways I mentioned above may be just a part of improving UI rendering based on what I have found and experienced. Maybe next time we can discuss other things that help optimize rendering, such as border repainting, caching, animations, and so on.&lt;/p&gt;

&lt;p&gt;I think there might be many other ways to improve your app performance. If you have similar experiences or other methods that you do, feel free to share them in the comments 💬! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/firman-ta/flutter-prime-number-isolate" rel="noopener noreferrer"&gt;Source Codes&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://docs.flutter.dev" rel="noopener noreferrer"&gt;https://docs.flutter.dev&lt;/a&gt;&lt;br&gt;
&lt;a href="https://x.com/remi_rousselet?lang=en" rel="noopener noreferrer"&gt;https://x.com/remi_rousselet?lang=en&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@flutterdev" rel="noopener noreferrer"&gt;https://www.youtube.com/@flutterdev&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@streamdevelopers" rel="noopener noreferrer"&gt;https://www.youtube.com/@streamdevelopers&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>mobile</category>
      <category>performance</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Goodbye, Singleton! Should We Implement this in Flutter?</title>
      <dc:creator>Firman Maulana</dc:creator>
      <pubDate>Fri, 28 Jun 2024 08:47:53 +0000</pubDate>
      <link>https://dev.to/tentanganak/goodbye-singleton-should-we-implement-this-in-flutter-4gf4</link>
      <guid>https://dev.to/tentanganak/goodbye-singleton-should-we-implement-this-in-flutter-4gf4</guid>
      <description>&lt;p&gt;Singleton is one of the debated topics by several software developers. Some say it is best to avoid it. But on the other hand, some people think it is good and use it in certain cases. Of course, several factors make them think like that. Which camp are you in? By the way, in the end, you may become more confident or it may become the opposite. Let's find out!&lt;/p&gt;

&lt;p&gt;Before we discuss this further, we should first know &lt;strong&gt;what a singleton is&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Singleton Pattern is a design paradigm in object-oriented programming that restricts the instantiation of a class to a single object. &lt;br&gt;
&lt;em&gt;- studysmarter.co.uk&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Importance of Singleton Design Pattern in Programming&lt;/strong&gt;&lt;br&gt;
Why should you care about the Singleton Design Pattern? There are a handful of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforced control over the access to shared resources&lt;/li&gt;
&lt;li&gt;Reduced system complexity&lt;/li&gt;
&lt;li&gt;Providing a shared state among all instances&lt;/li&gt;
&lt;li&gt;Generation of unique global access point&lt;/li&gt;
&lt;/ul&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%2F97egsrd8dzrum99krt8u.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%2F97egsrd8dzrum99krt8u.png" alt="Deep dive"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of debating whether this is good, let's consider the advantages and disadvantages of implementing it in our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement a Singleton in Dart
&lt;/h2&gt;

&lt;p&gt;Simplest way By making the constructor private, we ensure that the class cannot be instantiated outside of the file in which it is defined. &lt;/p&gt;

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

class Singleton {
  //private constructor
  Singleton._();
  //the one instance of this singleton
  static final instance = Singleton._();
}


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

&lt;/div&gt;

&lt;p&gt;As a result, the way to access this is to call &lt;code&gt;Singleton.instance&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is similar to when you use Firebase. Maybe you are quite familiar with the following code:&lt;/p&gt;

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

FirebaseAuth.instance.signInAnonymously();


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

&lt;/div&gt;

&lt;p&gt;A singleton pattern is used by Firebase plugins. And the only way to call their methods is with an instance getter. So does this mean we can also design classes in the same way? 🤔 💭&lt;br&gt;
You see, these classes are designed as singleton classes to prevent you from creating more than one instance in your code:&lt;/p&gt;

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

// inside Widget A
final auth1 = FirebaseAuth();
// inside Widget B
// with the different instances:
final auth2 = FirebaseAuth();



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

&lt;/div&gt;

&lt;p&gt;The code above should not be done, because you should only have one authentication service. Although singletons are often a reasonable solution for &lt;strong&gt;library or package design&lt;/strong&gt; when writing &lt;strong&gt;application code&lt;/strong&gt;, we must be careful about how we use it, as it can cause many problems in our code base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Singleton Drawbacks &amp;amp; Solutions
&lt;/h2&gt;

&lt;p&gt;As mentioned previously, several things make singletons problematic. Here we will talk about three disadvantages of singletons and how to solve them in Flutter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Singletons are hard to test&lt;/strong&gt;&lt;/p&gt;

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

class FirebaseAuthRepository {
  Future&amp;lt;void&amp;gt; signInAnonymously() =&amp;gt; FirebaseAuth.instance.signInAnonymously();
}


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

&lt;/div&gt;

&lt;p&gt;In this case, it's hard to write a test to check that &lt;code&gt;FirebaseAuth.instance.signInAnonymously()&lt;/code&gt; is called:&lt;/p&gt;

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

test('calls signInAnonymously', ()async {
final authRepository = FirebaseAuthRepository();
await authRepository.signInAnonymously();
  // how to expect FirebaseAuth.instance.signInAnonymously() was called?
});


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br&gt;
A simple solution is to &lt;strong&gt;inject&lt;/strong&gt; &lt;code&gt;FirebaseAuth&lt;/code&gt; as a &lt;strong&gt;dependency&lt;/strong&gt;, like this:&lt;/p&gt;

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

class FirebaseAuthRepository {
  // declare a FirebaseAuth property and pass it as a constructor argument
  const FirebaseAuthRepository(this._auth);
final FirebaseAuth _auth;

  // use it when needed
  Future&amp;lt;void&amp;gt; signInAnonymously() =&amp;gt; _auth.signInAnonymously();
}



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

&lt;/div&gt;

&lt;p&gt;As a result, we can easily &lt;strong&gt;mock&lt;/strong&gt; the dependency in our test and write expectations against it:&lt;/p&gt;

&lt;p&gt;Create a mock file! for example, &lt;code&gt;test/mocks/firebase_auth_mocks.dart&lt;/code&gt;, and run &lt;code&gt;build_runner&lt;/code&gt; to generate the &lt;strong&gt;mock class&lt;/strong&gt;.&lt;/p&gt;

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

@GenerateMocks([FirebaseAuth])
void main() {}


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

&lt;/div&gt;

&lt;p&gt;Create a test file! for example, &lt;code&gt;test/firebase_auth_repository_test.dart&lt;/code&gt;:&lt;/p&gt;

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

test('calls signInAnonymously', () async {
      // create the mock dependency
      final mock = MockFirebaseAuth();
      // stub its method(s) to return a value when called
      when(mock.signInAnonymously()).thenAnswer((_) =&amp;gt; Future.value(UserCredential(user: MockUser())));
      // create the object under test and pass the mock as an argument
      final authRepository = FirebaseAuthRepository(mock);
      // call the desired method
      await authRepository.signInAnonymously();
      // check that the method was called on the mock
      verify(mock.signInAnonymously()).called(1);
    });


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the &lt;strong&gt;mockito&lt;/strong&gt; package for more info about how to write tests using mocks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Lazy Initialization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initializing certain objects can be expensive. Let's take a look at this example:&lt;/p&gt;

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

class GoodBaller {
  GoodBaller._() {
    print('Player is ready to play');
    // Perform some heavy processing, like loading player data
  }
  static final instance = GoodBaller._();
}


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

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

void main() {
  // Prints 'Player is ready to play' immediately
  final player = GoodBaller.instance;
}


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

&lt;/div&gt;

&lt;p&gt;In the example above, the heavy processing of loading player data runs as soon as we initialize the player variable inside the main() method. This can be inefficient if we don't need the GoodBaller instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br&gt;
To defer the initialization until the object is needed, we can use the &lt;code&gt;late&lt;/code&gt; keyword:&lt;/p&gt;

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

void main() {
  // Initialization will happen later when we use the player
  late final player = GoodBaller.instance;
  ...
  // Initialization happens here
  player.startPlaying();
}


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

&lt;/div&gt;

&lt;p&gt;However, this approach is error-prone as it's easy to forget to use &lt;code&gt;late&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Dart, all global variables are &lt;strong&gt;lazy-loaded&lt;/strong&gt; by default (and this is also true for static class variables). This means that they are only initialized when they are first used. On the other hand, local variables are initialized as soon as they are declared unless they are declared as &lt;code&gt;late&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As an alternative, we can use packages such as &lt;code&gt;[get_it](https://pub.dev/packages/get_it)&lt;/code&gt;, which makes it easy to register a &lt;strong&gt;lazy singleton&lt;/strong&gt;:&lt;/p&gt;

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

class GoodBaller {
  GoodBaller() {
    // Perform some heavy processing, like loading player data
  }
}


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

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

// Register a lazy singleton (won't be created yet)
getIt.registerLazySingleton&amp;lt;GoodBaller&amp;gt;(() =&amp;gt; GoodBaller());

// When we need it, do this
final player = getIt.get&amp;lt;GoodBaller&amp;gt;();


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;the GetIt class is itself a singleton. But this is ok because what matters is that it allows us to decouple our dependencies from the objects that need them. For a more in-depth overview, read the package documentation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we can do the same thing with Riverpod, since all providers are lazy by default:&lt;/p&gt;

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

// Create a provider
final playerProvider = Provider&amp;lt;GoodBaller&amp;gt;((ref) {
  return GoodBaller();
});

// Read the provider
final player = ref.read(playerProvider);



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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. Instance Lifecycle&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we initialize a singleton instance, it will remain alive until the application is closed. If the instance consumes a lot of memory or keeps an open network connection, we can't release it early if we want to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br&gt;
Some packages like &lt;strong&gt;get_it&lt;/strong&gt; and &lt;strong&gt;Riverpod&lt;/strong&gt; give us more control over when a certain instance is disposed.&lt;/p&gt;

&lt;p&gt;Riverpod is quite smart and lets us easily control the lifecycle of the state of a provider. For example, we can use the &lt;code&gt;autoDispose&lt;/code&gt; modifier to ensure our AppConnection is disposed as soon as the last listener is removed:&lt;/p&gt;

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

final playerProvider = Provider.autoDispose&amp;lt;GoodBaller&amp;gt;((ref) {
  return GoodBaller();
});


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

&lt;/div&gt;

&lt;p&gt;This is most useful when we want to &lt;code&gt;dispose&lt;/code&gt; an object as soon as the widget is unmounted.&lt;/p&gt;

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

&lt;p&gt;Now that we've covered the main drawbacks of using singletons and solutions. As we know, singletons have several advantages and are useful in certain cases. However, on the other hand, singleton does have several disadvantages. As software developers, we must be wise about when to use it and how we look for alternatives or solutions to the problems. There are several important things based on what I have experienced, but they could be different from the current conditions of your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It's better not to create your "own" singleton&lt;/strong&gt;&lt;br&gt;
Yes, this could be good if you are working on a project that is small and easy to maintain or you want to create a package and have a good reason to do so. But imagine, if it gets bigger, you will have a lot of difficulty maintaining your code in the future because you will create code that is difficult to test. The point is it depends on your needs, there is no absolute good or bad but which one is more suitable for you. Instead, you can consider step two!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use a package like get_it or Riverpod&lt;/strong&gt;&lt;br&gt;
You can't use the package as you please, you need to consider how big your needs are and the impact you get from using it.&lt;br&gt;
But in this case, you can use get_it or Riverpod.&lt;br&gt;
These packages give you better control over your dependencies, meaning you can easily initialize, access, and remove them, without any of the drawbacks outlined above.&lt;/p&gt;

&lt;p&gt;Once you understand this, you need to know what dependencies exist between different types of objects (widgets, controllers, services, repositories, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/get_it" rel="noopener noreferrer"&gt;https://pub.dev/packages/get_it&lt;/a&gt;&lt;br&gt;
&lt;a href="https://riverpod.dev/" rel="noopener noreferrer"&gt;https://riverpod.dev/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.studysmarter.co.uk/" rel="noopener noreferrer"&gt;https://www.studysmarter.co.uk/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://resocoder.com/" rel="noopener noreferrer"&gt;https://resocoder.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programmers</category>
      <category>flutter</category>
      <category>pattern</category>
      <category>mobile</category>
    </item>
    <item>
      <title>7 Habits that Programmers Must Have!</title>
      <dc:creator>Firman Maulana</dc:creator>
      <pubDate>Tue, 11 Jun 2024 02:46:01 +0000</pubDate>
      <link>https://dev.to/tentanganak/7-habits-that-programmers-must-have-1dfj</link>
      <guid>https://dev.to/tentanganak/7-habits-that-programmers-must-have-1dfj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As a programmer, you know that your work requires high focus, so it often takes up a lot of your time. Yes, this also happens to me, I spend a lot of time doing tasks but sometimes the results don't meet expectations. I realized several things that I had gained from my work experience and insights from my colleagues, and there was a book that was interesting and very helpful in improving my habits.&lt;/p&gt;

&lt;p&gt;Did you know that we live by following patterns and habits that we do every day, these habits will influence the results of our goals. So if you want to change your life and achieve what you want, the first thing you have to do is change your habits. Stephen R. Covey in his book &lt;em&gt;&lt;strong&gt;7 Habits of Highly Effective People&lt;/strong&gt;&lt;/em&gt; says that: “&lt;em&gt;the way we see the world is entirely based on our own perceptions.&lt;/em&gt;”&lt;/p&gt;

&lt;p&gt;Instead of looking at the world that is so big for us, let's look at the smaller things first and relate to our daily activities. Yup, that's right, I want to share from my perspective as a programmer. There are several habits you should know to increase productivity when working as a programmer. Some of these things are also based on my experience, so the results may be different for you, but believe me, this will be useful if you practice it well. OK, let's get started!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Be Proactive&lt;/strong&gt;&lt;br&gt;
In his book, Covey describes the two-circle types of people that exist in our lives. &lt;strong&gt;Circle of concern&lt;/strong&gt; which is a circle containing things outside our control. Meanwhile, the smaller circle is the &lt;strong&gt;circle of influence&lt;/strong&gt;, which contains things that we can control.&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%2Fp50j7r9vgw6hhipidjz2.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%2Fp50j7r9vgw6hhipidjz2.png" alt="Proactive and Reactive"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on these two circles, &lt;strong&gt;reactive&lt;/strong&gt; people will think more about the &lt;strong&gt;circle of concern&lt;/strong&gt; while &lt;strong&gt;proactive&lt;/strong&gt; people focus more on the &lt;strong&gt;circle of influence&lt;/strong&gt;. It's the same with programmers, among us there are definitely two types of people. &lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;reactive programmers&lt;/strong&gt; who are busy with things that cannot be controlled such as office conditions, and company finances, they even believe that their career can be determined by the video "&lt;em&gt;How to Become the Best Programmer in Three Months&lt;/em&gt;". On the other hand, there are also &lt;strong&gt;proactive programmers&lt;/strong&gt; who choose to practice, try several interviews and competitions, to open up opportunities to become a programmer or whatever their dream job.&lt;/p&gt;

&lt;p&gt;Proactive people know they need to know external things, but they are the ones who are responsible for their careers. In other words, to be proactive you can focus more on looking for inspiration from within yourself and you can control it without ignoring important things outside of yourself rather than just expecting other people to give you a "&lt;em&gt;magic recipe&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Begin With the End in Mind&lt;/strong&gt;&lt;br&gt;
Many of us spend our lives going with the flow and we don't even know our purpose. So all we have is hope which is not a good strategy in any case. Stephen Covey says "Start with the end in mind" In other words, in doing anything, including starting a project, you must determine clear measures of success and a plan to achieve them.&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%2Fb1bbrkhtnd78rarqcfd8.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%2Fb1bbrkhtnd78rarqcfd8.png" alt="Begin With the End in Mind"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you apply this to programming, whenever you start a new project, you'll take the time to understand the final product. What are the functional and non-functional requirements of the features to be built?&lt;/p&gt;

&lt;p&gt;I remember someone saying software engineering is the art of making trade-offs. There are rarely right and wrong answers but rather a matter of determining the different types of design, and what the pros and cons are in a given case. Believe it or not, I have experienced that spending 30 minutes on careful planning can save you more than 10 hours of programming.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“People are working harder than ever, but because they lack clarity and vision, they aren’t getting very far. They, in essence, are pushing a rope with all of their might.” Dr. Stephen R. Covey&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, this is not easy because every plan can go wrong, I also fell into it several times. But this is still much better than not planning anything at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Put First Things First&lt;/strong&gt;&lt;br&gt;
Having the ability to choose what is important and what is not is also an effective habit. By being able to sort your interests according to your needs, you will be able to prioritize the order of work that will be done first.&lt;/p&gt;

&lt;p&gt;This habit is closely related to time management. Covey advises us to do the main thing based on the four quadrants he created which he called the Eisenhower Matrix.&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%2Fhv4j1roh5p3f4gaw52uc.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%2Fhv4j1roh5p3f4gaw52uc.png" alt="Eisenhower Matrix"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Previously I thought this quadrant was not that important for my tasks. And it turns out that this is often ignored by most programmers. When I worked as a Software Engineer, I was constantly bombarded by bugs that needed to be resolved. On the other hand, I also have long-term projects to complete.&lt;/p&gt;

&lt;p&gt;When you are under so much pressure, you will forget to learn. So if your code has a problem, you just want to go to Google or use AI and copy-paste the solution without really understanding it. Yes, truly understanding the cause of the problem is important for learning, but it is not urgent. For many programmers, learning stops as our careers progress. That's why you need to pay attention to the tasks that fall into this quadrant and schedule specific times for your long-term success. In other words, prioritize and achieve your most important goals rather than constantly reacting to urgency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Think Win-Win&lt;/strong&gt;&lt;br&gt;
One person's &lt;strong&gt;gain&lt;/strong&gt; is another person's &lt;strong&gt;loss&lt;/strong&gt; - this idea is very familiar in our brains probably because of the various competitions and sporting events that we usually watch. In this book, Dr. Covey considers it important to develop an "abundance mentality". That is, believing that there are enough resources and opportunities for everyone to succeed. This mindset is crucial to having a successful career as a Software Engineer. We work alongside other engineers and people in other job functions such as Data Science and Product Management.&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%2Fw1thqzuw744a9usc2ezo.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%2Fw1thqzuw744a9usc2ezo.png" alt="Win-Win Agreement"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Being able to collaborate effectively is one of the main skills you need to have. So, it is very important to be able to rise above personal career goals and have a win-win mindset for the team. Not just winning yourself by making other people lose, or giving in to others so they win, or even making other people lose because we also lose.&lt;/p&gt;

&lt;p&gt;Getting used to always thinking about being able to win over many parties will make us always try to achieve the best results. More than that, this also greatly affects our relationships with other people in the long term.&lt;/p&gt;

&lt;p&gt;To build good relationships in the long term, we need to establish relationships with many people. Through &lt;strong&gt;think win-win&lt;/strong&gt; this will help us build a good reputation or image in the future and will make our work more effective in the longer term.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Seek First to Understand, Then to Be Understood&lt;/strong&gt;&lt;br&gt;
Are you the type of person who is busy asking for your own feedback long before giving someone else a chance? This is not something Stephen Covey recommends.&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%2Fbg3uigm6p7xm7h9stc7v.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%2Fbg3uigm6p7xm7h9stc7v.png" alt="Seek First to Understand, Then to Be Understood"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to be understood by other people, the first thing we need to do is &lt;strong&gt;understand other people first&lt;/strong&gt;. Effective people will be able to have great empathy and respect other people by understanding them.&lt;/p&gt;

&lt;p&gt;But how does this apply to programmers? In addition to verbal communication, engineers also use their code to communicate with each other. Effective programmers understand the importance of &lt;strong&gt;empathy&lt;/strong&gt; in coding. They prioritize clarity in their code to ensure that others, including themselves in the future, can understand and maintain it easily.&lt;/p&gt;

&lt;p&gt;Apart from other engineers, programmers also communicate with end users through their products. Effective programmers prioritize user experience by putting themselves in the end user's shoes. They anticipate user needs, design interfaces that deliver, and create error messages that guide users instead of confusing them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Synergize&lt;/strong&gt;&lt;br&gt;
People who are able to synergize well with fellow humans will be effective people. Through good relationships and collaboration, you can create better solutions than if you only relied on yourself. Mathematically 1 + 1 = 2. But in life, if the synergy is right, it can be 1 + 1 = 10.&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%2Flb8uq52jfzpkl28kyp32.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%2Flb8uq52jfzpkl28kyp32.png" alt="Synergize"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In his book, Dr. Covey emphasizes the importance of appreciating differences and using them to create a whole that is greater than the sum of its parts. So it's about getting the most out of every team member to create a product that users love. Effective programmers adopt &lt;strong&gt;collaborative&lt;/strong&gt; coding practices, such as code reviews, pair programming, and other knowledge sharing. By combining individual skills and insights, teams can build more powerful, efficient, and innovative products.&lt;/p&gt;

&lt;p&gt;Even though it is not easy, especially for programmers, most of whom work individually, by getting used to this, we can not only become independent figures but can also become people who can work together and collaborate well with anyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Sharpen the Saw&lt;/strong&gt;&lt;br&gt;
Effective people will continue to practice things in their lives so that they continue to progress and develop well. Covey said there are four main things that we must hone in our lives; &lt;em&gt;&lt;strong&gt;body, heart, mental, and spiritual&lt;/strong&gt;&lt;/em&gt;. Yes, in general, this is very important for life in any field. But let's try to focus on something more specific.&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%2Ff2tj8no1yezmseadugi4.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%2Ff2tj8no1yezmseadugi4.png" alt="Sharpen the Saw"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For programmers, this is the most important habit. To understand this habit, let's imagine there are two workers trying to chop wood. The first worker was a young man who continued chopping wood for the entire 8-hour shift without stopping. The second worker was an older man who needed a 10-minute break every hour, in between which he took time to sharpen his saw. If you think an older man will chop more wood, then you have understood this habit.&lt;/p&gt;

&lt;p&gt;As a programmer, you will be faced with so many new technologies. Effective programmers understand the importance of &lt;strong&gt;continuous learning&lt;/strong&gt;. Sharpening the saw involves investing time in acquiring new skills, staying updated on industry trends, and exploring new technologies. Effective programmers must make time for professional development by practicing, attending conferences, participating in programming communities, and so on. This habit can help us adapt to technological advances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusions&lt;/strong&gt;&lt;br&gt;
Sometimes, without us realizing it, bad habits more or less influence our lives to become ineffective. However, a habit that has been carried out continuously for too long will be difficult to break.&lt;/p&gt;

&lt;p&gt;This is what we need to understand if we want to change our lives for the better, starting from changing our views to changing our habits. The implementation of these 7 habits as said by Stephen R. Covey will help us change our lives much more effectively and meaningfully.&lt;/p&gt;

&lt;p&gt;It is not enough just to understand these habits, but we must all apply them, because each point is equally important and interrelated. Because only by living an effective life can we ease the path to greater success.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.franklincovey.com/the-7-habits/" rel="noopener noreferrer"&gt;franklincovey&lt;/a&gt;&lt;br&gt;
&lt;a href="https://books.google.co.id/books?id=36V_PAAACAAJ&amp;amp;hl=id&amp;amp;source=gbs_book_other_versions_r&amp;amp;cad=1" rel="noopener noreferrer"&gt;The 7 Habits of Highly Effective People&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programmers</category>
      <category>habit</category>
      <category>productivity</category>
    </item>
    <item>
      <title>5 Ways to Stay Motivated to Learn Programming!</title>
      <dc:creator>Firman Maulana</dc:creator>
      <pubDate>Mon, 18 Mar 2024 08:00:30 +0000</pubDate>
      <link>https://dev.to/tentanganak/5-ways-to-stay-motivated-to-learn-programming-348</link>
      <guid>https://dev.to/tentanganak/5-ways-to-stay-motivated-to-learn-programming-348</guid>
      <description>&lt;p&gt;Have you ever felt like this? You decide to learn programming, feeling excited and happy about it. You set goals and dreams for the future. So, you begin studying, either at school or with free courses. You dive into your studies, staying up late at night and going to school or work the next morning. But then, you hit a point where some concepts confuse you, and you don't know what to do. There's no one to help you out.&lt;/p&gt;

&lt;p&gt;After a while, you find yourself staying up late into the night, barely getting any sleep, feeling exhausted because your mind is tired from all the challenges you're facing. You also realize that you're nowhere close to achieving your dream job. This disappointment leaves you feeling tired, so you decide to take a break. Eventually, you put your goals aside and think they're no longer a priority.&lt;/p&gt;

&lt;p&gt;As we know, we cannot equate learning to code with some of the skills you can get just by studying in class with a teacher. Even though you take some lessons in class, you still have to practice them independently. When you learn to code on your own, you have to generate your own motivation, which is a big challenge. So how do you ensure that you keep learning, and don't give up? There are five ways that can help you stay motivated while learning to code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Have and hold tightly to your goals 🎯&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start by setting a goal &amp;amp; keep that goal in mind from the moment you start learning to code. This can make your actions clearer and you can know why you are doing them. Of course you don't want to spend time and energy learning to code in vain, right?&lt;/p&gt;

&lt;p&gt;For example, maybe your goal is to have flexibility at work because you feel pressured by the standard rules regarding time, place and systems that run in the company you work at now. So you want to be a freelancer without having a boss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Break it down into small goals 📝&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When your goals are clear, you can start breaking them down into smaller stages that are easier to achieve. This way you will feel the burden is lighter. You can also give yourself appreciation when you succeed in achieving these small goals. But even though you have shared it and feel light, don't forget your big goal. Of course, not everything is easy and there may be difficulties that you face, but make those difficulties remind you of what your goals are and why you are fighting so hard to get them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Consistent and sustainable 📈&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the big pitfalls of becoming an expert at anything is having unrealistic expectations. For example, you target yourself to become a professional programmer in just 1-2 months. Maybe for some people it can be an extra or "unnatural" process, although I still feel this is quite difficult and almost impossible for general people to do. Especially if you are actively working or have other activities, of course 1-2 years is more reasonable.&lt;/p&gt;

&lt;p&gt;Of course, this time depends on yourself and what your current condition is. Try to be wiser in setting targets and schedules, because the most important thing is that you can be consistent with what you set at the beginning. And continues to progress over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. You are not alone 🤝&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Always remember that you are not doing it alone, there are also many people out there who are your age and have the same goals as you. Build relationships, join communities so you can exchange lots of ideas, gain new knowledge from the friends you meet. An environment like this will help you to stay motivated in studying. Moreover, in this era it is very easy for us to find great online communities.&lt;/p&gt;

&lt;p&gt;Apart from the many positive things above, there are also many people who recruit programmers from communities and they even become great people in them. So make sure you also make a positive contribution because when you help others, you are also doing it for yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Stop comparing yourself with other programmers 🤼🏼‍♀️&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course it is impossible not to see what other people are doing or achieving. But don't feel like you have to always be in line with other people. Everyone has a different situation and progresses at a different pace. Some people will have more time than you, or may learn certain things faster than you. Others will have less time or learn more slowly than you.&lt;/p&gt;

&lt;p&gt;In the end, the progress of others doesn't affect you directly. Learning to code is a challenging journey, and if you're on that path, you deserve credit! Even if you feel completely lost, remember that progress takes time and persistence pays off! I hope these tips are helpful.&lt;/p&gt;

&lt;p&gt;Maybe for some people it will be different, and surely you have other ways to stay motivated and enthusiastic about learning. But hopefully some of the things above are my own experience and some are what I got from other people and some of my acquaintances. Hopefully it can help you to remain enthusiastic about learning and achieving your goals.&lt;br&gt;
Do you also feel the same way? Don't forget to leave a comment below and feel free to provide input and tips that can be useful for all of us!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was inspired by: [@sahilandsarra]&lt;/em&gt;(&lt;a href="https://www.youtube.com/@sahilandsarra"&gt;https://www.youtube.com/@sahilandsarra&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>softwareengineering</category>
      <category>motivation</category>
    </item>
  </channel>
</rss>
