# FlutterGen Code Generation

One of the most important programming principles I've heard since my freshman year of college is ***DRY***, or ***Don't Repeat Yourself***.

DRY gives us a way to solve problems through code that applies to almost any problem. It is even a way of applying algorithms in our daily lives.

Do not repeat yourself, if you do, there is room for optimization. From a technical point of view, this principle urges us to automate a repetitive process that, at first suggests the implementation of a loop such as `for` or `while` as a solution. Or write a script that runs that action that takes us more time and effort than we would like.

There is a type of super useful tool when we're programming, the famous code-gen or code generators. They consist of a program that is incorporated into our project to run in development and create files with all the settings that would have lengthened development time.

# Why?

Before getting into business, I would like to show you a typical problem where we can see the reason for these programs.

```dart
Image imageFile = Image.asset('assets/img/my_image.png');
```

In this case, we are declaring an image that is initialized as an asset that we loaded from the same project. To assign this asset, we must provide the **path** of the *.png* file to the method. This is not safe because we are human beings and we tend to make errors (typos) that may not be detected by a linter or compiler.

In short, code generation handles these problems as it is responsible for writing the code that we need so that we can use it and we can identify/correct errors more easily.

Now that we know that, let's use these utilities.

>⚠️ Disclaimer: 95% of the time I find myself writing Dart code, so this article will be focused on how we can be more efficient when programming apps with Flutter, using code generation tools.

# How?

***FlutterGen*** is a relatively new code generator, it takes care of many of the big problems when working with local files, specifically resources that our apps use for branding (the logo, for example).

Well, a good practice is to always store the values that are used many times in the app in variables and classes.

We can move on from this:

```dart
Future callToAPI() async {
	await http.get('url_to_my_api.dev/api');
}

Future anotherCallToAPI() async {
	await http.get('url_to_my_api.dev/api/another');
}
```

To this:

```dart
class API {
	static const url = 'url_to_my_api.dev/api';
}

Future callToAPI() async {
	await http.get(API.url);
}

Future anotherCallToAPI() async {
	await http.get('${API.url}/other');
}
```

A very simple way of only accessing the `url` property of the `API` class and that way we can use the same variable in other parts of our app. It is also easier if we change the string that contains `url` since it would be changed in all the parts where we use it.

# Setup

To use FlutterGen, we need to configure it. We have 3 options:

- Homebrew.

```dart
brew install FlutterGen/tap/fluttergen
```

- Pub.

```dart
dart pub global activate flutter_gen
```

- build_runner. With Dart's build system there are usually some versioning conflicts between packages, so let's skip that for now.

My suggestion, ***use Pub***. You will have to update your `PATH` at the end of the installation, running the following command in the terminal: 

```dart
export PATH ="$PATH":"$HOME/.pub-cache/bin"
```

Next, we must do the `pubspec.yaml` configuration. At this point, we must have assets included in the pubspec. Here is what you can copy and paste at the end of your file, the explanation goes in the comments.

```yaml
# here goes all the config for flutter_gen
# watch out for the indentations
flutter_gen:
	# by default, the generate files are in `lib/gen/`
	# you can set other directories like `lib/src/gen` using [output]
  output: lib/src/gen/

	# if you use some linter that is line-of-code-sensitive
	# you can satisfy the lines it demands with [lineLength]
	# the default value is 80
  lineLength: 90

  # integrations are optional if you use another 3rd party
	# package, like [flutter_svg] to use .svg files like we
	# do with fonts and images
	#
	# it's important to have your integrations as project dependencies
  integrations:
    flutter_svg: true
	
	# you can also add color files in XML format
	# if you're reusing from an android project
  colors:
    inputs:
      - assets/color/colors.xml
```

Ok, that was all the configuration we had to do. Now let's see the magic.

# Generation and usage

We run the command:

```sh
fluttergen -c pubspec.yaml
```

Taking into consideration that the path to the pubspec may vary and must be checked in the case of getting an error. If all goes well, you will have a new `gen/` folder in the path you specified in the pubspec.

Now we are going to use the generated code. In the case of images, we access through `Assets`, until we reach the one we're going to use. Since our image becomes an `Image` object, then it is not necessary to wrap it in the widget, we just call the `image()` method:

```dart
Assets.images.background.image();
```

If we need text fonts, we have a class called `FontFamily`, where we have as properties the text strings that contain the identifiers of our fonts. We use them like this:

```dart
Text(
  'We\'re using fonts generated by FlutterGen',
  style: TextStyle(fontFamily: FontFamily.googleSans),
);
```

Finally, in order not to leave you without the example of the colors (in case someone uses them that way), we have a class called `ColorName` that allows us to access them.

```dart
Container(height: 100, width: 100, color: ColorName.justBlack);
```

Now we have our generated code and we know how to use it, we just have to start implementing it in our apps.

If you have any questions regarding this package, in this [link](https://pub.dev/packages/flutter_gen) you can browse the documentation and you can also check its source code in its [repo](https://github.com/FlutterGen/flutter_gen) from GitHub.
