“This is the 26th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

This article is a translation from the Official Dart programming guide: Effective Dart Design.

Dart is a “pure” object-oriented programming language in which all objects are instances of classes. But Dart does not require all code to be defined in a class. We can define top-level variables, constants, and functions outside of a class — just like in a procedural language. Because of this, Dart coding has some special recommendations.

Suggestion 1: If an abstract class has only one function, it is better to define the function directly

Suppose we need a callback function or use a function, in a language like Java you need to define a class. However, in Dart, defining a class makes the code unmaintainable if it’s just a function. It is recommended to use typedefs directly to define function aliases at this point.

// Correct example
typedef Predicate<E> = bool Function(E element);

// Error example
abstract class Predicate<E> {
  bool test(E element);
}
Copy the code

Suggestion 2: If a class has only static variables or functions, define top-level constants and functions instead

In Java or C#, if you want to define a constant, you usually need to define a static constant class to do so, for example:

/ / Java code
public class ConstParams {
    public static int maxLength = 256;
    public static int minLength = 5;
}
Copy the code

This has the advantage of avoiding collisions through namespaces, assuming static constant names are defined in multiple classes. For Dart, variables and functions defined outside of the class can be distinguished using the library as the namespace, so that even if variable names are consistent, there will be no conflict.

// const_params.dart
const int maxLength = 256;
const int minLength = 5;

// test.dart
import 'const_params.dart' as ConstParams;

void main() {
   print('max: ${ConstParams.maxLength}');
}
Copy the code

Therefore, the following is not recommended in Dart.

class ConstParams {
  static const maxLength = 256;
  static const minLength = 256;
}
Copy the code

Of course, this is not a hard and fast rule, as using classes makes code more readable if there is a set of constants of the same class, as in the color example below.

class Color {
  static const red = '#f00';
  static const green = '#0f0';
  static const blue = '#00f';
  static const black = '# 000';
  static const white = '#fff';
}
Copy the code

Tip 3: Don’t use inheritance lightly

This has been introduced in many languages, and inheritance should only be used if a subclass conforms to the “is a” parent class relationship. For example, the Dog class can inherit from Animal, but this should be limited to a parent class that is abstract enough with few personalized features and few future changes.

Using inheritance does reduce coding, but any changes to the base class can cause your subclass code to be abnormal. If you have a lot of subclasses, it can be pretty scary to maintain. A good suggestion is to uniformly name table names for base classes that support inheritance, such as IterableBase. At the same time, the base class must be well documented, so that subclasses that want to inherit the class are aware of the possible impact.

Suggestion 4: Do not implement non-interface classes using implements

The advantage of defining an interface class is that it can be switched between multiple implementations without changing the code, and interface-oriented programming is often used in dependency injection frameworks or code structures. For an article on dependency injection, you can see dependency injection from a startup CEO looking for a programmer. Implements methods of a class that is not designed to be used as an interface is strange behavior. Adding a member variable to the class doesn’t cause any problems, but adding new methods means the code will break. Therefore, if interface oriented programming is to be adopted, the interface class defined should be a “virtual” class with only necessary method declarations and no other attributes. Also, the class should be well documented so that the implementation class knows exactly how to implement the corresponding interface.

Suggestion 5: Use it firstmixinKeyword definitionmixintype

Prior to Dart version 2.1.0, there were no keyword mixins, and classes were used to define mixins for other features. Dart 2.1.0 introduces mixins to define mixins specifically to make the semantics clearer. Compare these two implementations. Obviously, using mixins makes it clearer that it is a mixin type and not used as a class. The official recommendation is that since Dart version 2.1.0, you should not use the class keyword to define mixins to avoid unmaintainable code.

/ / a mixin
mixin SpeakEnglishMixin {
  void speakEnglish() {
    print('I can speak English fluently'); }}/ / class
class SpeakEnglishMixin {
  void speakEnglish() {
    print('I can speak English fluently'); }}Copy the code

Mixins can also use the on keyword to specify that they apply only to specific classes, limiting scope and avoiding abuse. In the example declared below, SpeakEnglishMixin can only be mixed with the Person subclass.

mixin SpeakEnglishMixin on Person {
  void speakEnglish() {
    print('I can speak English fluently'); }}Copy the code

conclusion

This article looks at some of the features that are unique to Dart compared to other object-oriented languages, such as variables outside classes, function definitions, mixins, and more. Dart combines the advantages of object-oriented and dynamic languages and is closer to the features of modern programming languages. But coding is always the same, and Dart’s features should be used to write more maintainable code, not to misuse new features.

I am dao Code Farmer with the same name as my wechat official account. This is a column about the introduction and practice of Flutter, providing systematic learning articles about Flutter. See the corresponding source code here: The source code of Flutter Introduction and Practical column. If you have any questions, please add me to the wechat account: island-coder.

👍🏻 : feel the harvest please point a praise to encourage!

🌟 : Collect articles, easy to look back!

💬 : Comment exchange, mutual progress!