avatarFred Grott

Summary

The article argues that using a Globals dart file for dependency injection in Flutter applications is an anti-pattern, advocating instead for dependency injection via Factory Method and Service Locator Pattern to improve app performance and architecture.

Abstract

The author of the article, who is creating a series on Flutter Application Development and Design, asserts that the practice of using a Globals dart file to manage dependencies in Flutter apps is detrimental. This approach, known as the Globals dart file anti-pattern, indicates a lack of understanding in object-oriented architecture and can lead to poor app performance. The article suggests that developers should use atomic coding structures in Dart and Flutter, which promote the encapsulation of related classes, variables, and functions within a single file. It emphasizes the importance of dependency injection through Factory Method and Service Locator Pattern, which Google has found to be more performance-efficient than code-generation style dependency injection. The author provides examples of how to implement these patterns correctly and warns that improper use of singletons without a clear understanding can also be an anti-pattern. The article concludes by stating that singletons are not inherently bad if used creatively with proper testing and logging to track errors, which are not caught at compile time.

Opinions

  • The author believes that the use of a Globals dart file is indicative of a developer's lack of knowledge in OOP principles and app architecture.
  • It is emphasized that every unnecessary dependency injection increases app initialization time, negatively impacting user experience.
  • The author suggests that using atomic coding structures can lead to better-designed apps by forcing developers to consider what truly needs to be dependency injected.
  • The article criticizes the use of bare singletons without proper understanding, considering it an anti-pattern.
  • The author advocates for the use of Factory Dependency Injection and Service Locator Pattern as superior alternatives to the Globals dart file approach.
  • The author is not convinced about the use of packages like Get-It for dependency injection, preferring methods that allow for comprehensive logging to catch errors that are not evident at compile time.
  • The article concludes with the opinion that singletons can be used effectively when implemented in a way that supports testing and error tracking, contrary to the belief that singletons are always an anti-pattern.

Globals Dart File Is An AntiPattern

You might think putting a Globals dart file in your Flutter App is a good idea. I am here to show you that it’s not a good idea.

Background

I am creating a series of Medium articles and a book series on Flutter Application Development and Design. Popular articles are:

Things Covered

- Globals dart file anti-pattern

- Dependency Injection via Factory Method, Service Locator Pattern

- Using A Singleton the Correct Way To Solve A problem

A Typical Globals Dart File Use Case

You look in that globals dart file, and you ask, How Many Items Do I have to-Dependency Inject in that Globals dart file? An example, a device-info dart file:

and the globals dart file:

Every dependency injection you do that is not needed is time costs spent during app initialization. So, it impacts how much time the app-user is forced to wait for the app to be ready to be used.

Why not instead use your coding style to force you to ask a more effective question?

Atomic Coding Structures In Dart And Flutter

Ever wonder why the Dart computer language allows including classes, variables, and or functions into one file that also can be a one file library? The concept can be termed atomic. Atomic in this case refers to an API unit and basically includes everything local to that *atomic API unit*.

One can re-apply that to force one to ‘ask’ the question well out things that are non-local to the atomic API-unit of the app API components, what should be dependency injected?

Globals Dart file is The Anti-Pattern

hat Globals Dart file in a Flutter App is an anti-pattern. That anti-pattern indicates:

1. You do not know enough about architecture OOP-wise to reduce and or eliminate singletons.

2. You lack a clear understanding between poor architecture choices and app performance.

This an example of not doing the globals dart file anti-pattern:

Note that the local variables are put at the top of the dart file rather than a separate globals dart file.

And yes, you will get fired for such bad architecture choices! And before you shout that you cannot; let me show you how easy factory dependency injection is to cook up. Thus, instead, you want a device-info dart file with the local variables in the file rather than in a globals dart file.

Factory Dependency Injection, Service Locator Pattern

The whole reason we use this instead of code-generation style dependency injection is that Google did test the other dependency injection way and found it to be somewhat worse performance-wise.

A Serice Locator pattern is an abstraction layer that manages the process of obtaining a service. It’s called a service locator as the implementation usually includes a way to register the service in a central registry.

Note, however it does share a limitation with other dependency injection methods as the error shows up as run-time errors instead of compile-time errors. This then indicates that logging is a requirement for any service-locator dependency injection implementation. Also, note that when we test we have to interact with the registry to test it, normally by sometimes setting a fake dependency for example.

Here is the Factory Dependency Injection, Service Locator Pattern:

Let’s go through Factories. A factory returns not a new instance but an already existing instance. Hence, it’s less expensive than constructing a new instance which is why we are using it to inject dependencies. We cannot use a generative constructor as that returns a new instance every time even though it does not use a return keyword.

class Person {
String name;
String country;
// unnamed generative constructor
Person(this.name, this.country);
}

That returns a new instance of Person every time the Person object is referenced.

We have two service locators, ie factories. You can see that better by how this service locator is called:

final sl =
ServiceLocator(); // this is the same as ServiceLocator.sharedContainer
sl.registerFactory<MyLogging>((container) => MyLoggingAdaptor());
sl.registerFactory1<MyLoggingAdaptor, String>(
(container, title) => MyLoggingAdaptor(),
);

The first service locator, ServiceLocator is just a function container named shared container that happens to be set up as a Singleton. But, because we registry other factories to it; it’s fully testable, unlike the traditional bare singleton you are warned away from using. Thus, in fact, we use a very focused way of using a singleton that has a named registry entry for every created factory instance to solve our dependency injection get rid of globals-dart-file-anti-pattern. And, that is why I cannot claim singletons are an anti-pattern.

Using bare singletons without knowledge is the anti-pattern of not fully getting rid of singletons!

The second ServiceLocator is just a single factory-non-singleton or the factory-singleton version instance if we need that. It’s registering the instance and the name in our first or parent ServiceLocator container singleton. The second example uses a factory implementation where we supply a human-readable name.

Do We Need To Log Dependency Injection

Considering my correction of singletons are bad and anti-patterns what guess do you have about my feelings on logging dependency injections? Yes, we should do that which is why I am not as of yet convince to use the Get-It package or even leary of the Getx package we need to log all dependency injections as any mistake will not show up as a compile-time error; and, thus we need logging to track such a hidden error down.

Conclusion

It’s not Singletons are bad. It’s using naked singletons is bad and gathering everything in a globals dart file is bad when we can creatively use singletons in a way that provides something that can be tested and something we can log so as to track down errors.

General Flutter and Dart resources:

Flutter Community Resources

Flutter SDK

Android Studio IDE

MS’s Visual Studio Code

Flutter Docs

Dart Docs

Google Firebase Mobile Device TestLab

Google LLC owns the trademarks of Dart, Flutter, Noto, Roboto, and Android. Apple Inc owns the trademarks of iOS, MacOSX, Swift, SF-Pro, SF-Compact, SF-Mono, New York Typeface, and Objective-C. JetBeans Inc owns the trademarks of JetBeans, Kotlin, and IntelliJ. Oracle Inc owns the trademarks of Java and Solaris. Microsoft owns the trademarks of MS Windows and PowerShell. Gradle owns the trademark to Gradle. The Git project owns the trademark to Git. The Linux Foundation owns the trademark of Linux. Smartphone OEM’s trademarks to their mobile phone product names. Samsung owns the trademark to Tizen.

Flutter
Dart
Development
Software Development
Software Engineering
Recommended from ReadMedium