How do you order members in your Dart files?

I just filed a bug (Keep State ordered just below its Widget · Issue #62927 · dart-lang/sdk · GitHub) but I realized maybe there are other automatic ordering tools than the Dart analysis server. Do people use https://dcm.dev/, for example? Does it have an ordering solution that is more clever than the one that ships with Dart?

This is obviously a rabbit hole. Every programmer has their own idea for how things should be ordered. I’d personally rather have something like dart format for ordering. But see, for example, Enforce consistent order of class members · Issue #58283 · dart-lang/sdk · GitHub, for a taste of how hard it is to get people on the same page.

1 Like

Dart has a member orderer? :face_with_raised_eyebrow:

I tried once a VSCode plugin for that, but it never worked.

I have some pretty niche formatting rules (and some decades of hard-to-change habits). It was a pain for me to use { on the same line (I always used C# style).

That’s a good candidate for a Dart CLI tool. I don’t think dart format should touch the order of members at all (I think messing with line width is enough).

That being said:

  1. Orders of classes in the same file must not be touched (I usually group members together by feature, for example, an enum just above a class that uses it).

  2. Orders of members inside a class: constructor, static variables, local variables, methods (again, sorted by feature).

  3. Whenever something breaks a line or belongs to a block, it must have blank lines separating them from the rest of the code (var blocks, {} or multiline statements, return, continue, etc. Example:

Future<void> _signInWithGoogleNative() async {
  await GoogleSignIn.instance.initialize();
// new line because of variable blocks: (inherited from Pascal)
  String idToken;
  final account = await GoogleSignIn.instance
      .attemptLightweightAuthentication();
// new line because of the var block above
  if (account != null) {
    idToken = account.authentication.idToken!;
  } else {
    final auth = await GoogleSignIn.instance.authenticate(
      scopeHint: [
        "openid",
        "https://www.googleapis.com/auth/userinfo.email",
      ],
    );
// new line because of var block above
    idToken = auth.authentication.idToken!;
  }
// new line because of { } block above
  final oAuthCredential = OAuthCredential(
    providerId: GoogleAuthProvider.PROVIDER_ID,
    signInMethod: GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD,
    idToken: idToken,
  );
// variable block
  await FirebaseAuth.instance.signInWithCredential(oAuthCredential);
}

Delegating this to Dart would create a lot of friction (it’s an opinion, so, obviously, it will be discussed for generations, lead to some wars and it will never be solved) and would add load to the Dart team (they could use the extra time and energy by giving us macros! :angry:)

IMO, that would be a dart cli tool (just like the mentioned dcm - but free).

Not even an IDE Glorified Notepad plugin: some uses VSCode, some uses Android Studio, some uses Zed. Writing the same plugin in 3 languages is a no-no.

2 Likes

I use DCM across all my packages for this, it has a member-ordering rule to enforce where getters, setters, private, public etc. members are placed.

Pesonally I don’t particularly care what the order is a long as it is consistent across all my packages so readers of the code get the same ‘look and feel’.

Same with formatting, the formatting scheme used is far less important to me than the fact it is the same everywhere.

You don’t need any of these of course, you can do it all manually to your own personal taste, just do it everywhere.

1 Like

Cool! Do you know if DCM orderer tries to keep things like StatefulWidget + its State together? Or sealed class and its descendants? Is there some kind of dcs order command, or is that just a linter (that tells you something is wrong but you have to fix it yourself)?